Iskren Chernev, an Independent developer, uses a lot of Redis. In this talk, Iskren will look at a particular Redis use-case -- using it as the main database (not cache). Iskren will show how to achieve reasonable guarantees about data integrity, speed, high-availability in an event of failure and infinite horizontal scalability. This particular approach has proven successful in managing clusters of up to 2400 nodes, and storing data north of 7TB before replication. We'll cover ways to separate your data appropriately into many nodes, performing different types of migrations (from another database, from one cluster to another, scaling migrations and migrating out of Redis), moving nodes without downtime, some configuration tips and monitoring.
Direct Style Effect Systems -The Print[A] Example- A Comprehension Aid
Redis as a Main Database, Scaling and HA
1. Redis as a Main Database,
Scaling and HA
It`s possible!
2. Contents
● Keep your data safe
● Redis ops
● HA is not hard
● Distributing workload
● Data migrations
● Client considerations
● Other tips
● When to use and not to use Redis
3. Overview of Environment
● Stateless Microservice Architecture (Java/Python)
● Single threaded services
● Asynchronous RPCs
● Synchronous Redis
● Zookeeper for service discovery
● I’ve tried to keep suggestions generic when possible
4. Keep Your Data Safe
● Run a single Slave for every Master
● Use AOF, disable RDB
● Do frequent backups from the Slaves
○ Partial backup if AOF inode is the same
○ Full backup if AOF inode is different
○ Hardlinks are useful
● appendfsync (always|everysec|no)
● Monitor both master and slave for liveliness, writability,
memory consumption, master/slave status
5. Redis Ops A.K.A. Deploying Right
● Place Masters and Slaves on different racks
● If there is a single client, deploy on the master machine
● Store master-slave info in a database (zk)
● Update address on disconnect
● Don’t use AOF on slave reboot
6. High Availability
● Use idempotent operations
● Auto-retry on failure
● Auto or manual flip to slave
● Keep failures local
● Use it as data storage for stateless microservices
7. Splitting your data
● The most important decisions to make
● Follow microservice splitting if possible
2 options:
● Hash-of-key
● Shard-in-key
8. Splitting your data -- hash-of-key
● Good all-round solution that will evenly distribute the
data
● Scaling only possible on multiples
● Upscaling requires delicate work
● Easier to deploy and maintain at smaller to medium
scales
self.client[hash(key) % len(self.clients)].set(key, val)
9. Splitting your data -- shard-in-key
● Better choice if you need more control on key generation
● Arbitrary upscaling
● Choose only Live shards when generating the key
● Ability to freeze shards, easily introduce new ones
● More work to maintain
key = <shard><random bytes>
10. Migrations/Scaling
● Use idempotent operations
Two ways:
● Nx scaling the Redis way
○ Use 2 slaves to duplicate your data (with slaves, so you’re always safe)
○ Shut down master and make everyone use the right slave
○ Cleanup extra data (belonging to other slave)
● Old school scaling/migration
○ Start writing to both places
○ Start migrating existing data, using cursors/scans/whatever (can take a
11. Scaling Nx -- the Redis way
● If you want to scale to N times the current capacity
● Make N slaves of every master (each with a single slave)
● Clients should know if they talk to old master or one of N
replicas
● Kill the master and force clients to use the right slave
● Cleanup the excess data when the dust settles
12. Scaling/Migrating -- the old school way (overview)
● Sometimes you don’t want to/can’t scale even 2x
● Not enough resources to keep N+1 times data in memory
● Useful when changing the schema or database
● Full control over all the steps
● More complicated than the simple Nx scaling
13. Scaling/Migrating -- the old school way (steps)
● Spin up new shards
● Start writing to new shards (effectively writing to both)
● Iterate over existing data and copy it (may take time)
○ Shouldn’t interfere with regular writes (idempotent!!)
● After iteration is complete start reading from both
● Compare the results and iterate until satisfied (sampling)
● Stop reading from old cluster
● Stop writing to old cluster and shut it down
14. Client Considerations
● Prefer idempotent ops (can’t stress that enough)
● Redo idempotent operations to handle master/slave
failover more easily
● Choose your sharding well
○ Top-level vs secondary data
○ Less top-level keys → less complexity, more uneven load (hotspots)
○ More top-level keys → more complex, uniform load, easier to scale only
what is needed
16. When NOT to use Redis
● Memory is expensive (there is Redis on Flesh)
● Consider Cassandra if you need a smart big cluster with
all the bells and whistles (and all the headache)
○ I hope you have a well paid ops team
● Consider SQL if you’re scale is small and/or you need
features then speed
○ Achieving master-slave HA is much more complicated