Redis Cheatsheet
Key Concepts
- a in-memory key-value store, store and retrieve using a unique key
- can be used as a database, cache, and/or messsage broker
- supports numbers, strings, hashes, lists, sets, sorted sets
- key-eviction, expiration, hashes, string, set, order-set, pub/sub, channel, RDB, AOL,
WHy do we need it?
- It's an in-memory key-value data store, so it's very fast for read and write. Suitable for caching, session management, pub/sub applications, and leaderboards
Differs between traditional database?
- in memory and key-value store (NoSQL)
What is Redis Hashes?
- an key-value object, strings only
Can Redis be used in a multi-threaded application?
- Redis is single-threaded, but it is event-driven and asynchronous I/O to handle multiple client connections
What is pub/sub?
- channels, producers push data into the channel, and redis distributes the data into subscribers/listeners
How to ensure persistence?
- Snapshots: RDB, and AOF: append only file
- RDB, write a new RDB file, and only replace the old one when new one is completed
What is Redis Transactions?
- like a SQL transaction, grouping a set of commands together so that they either all executes or not execute at all
Diff between RDB and AOF?
- RDB takes a snapshot of all data into a single file, runs less frequently. it's efficient, but can result in data loss.
- AOF stores only new data to the file. runs more frequently to prevent dataloss, but can be inefficient and larger files
- RDB is generally faster and consumes less CPU because AOF tracks repeated or overlapping operations.
How to scale Redis?
- replication
- Redis Sentinel for HA
- Redis Cluster for sharding
why is it so fast?
- Redis keeps everything in RAM
Data types?
- string, list, set, and sorted set
- Keys are binary safe, so any binary sequence is allowed
What is key eviction?
- when memory is reached, some keys can be evicted to make room. like volatile-lru or allkeys-lru.
How does Redis manage memory?
- maxmemory, keyeviction, RDB, AOF
When would Redis not be an appropriate choice?
- When data is large, or requires complex transactions. OR ACID compliance is required for data consistency. Heavy write may impace performance as well. Full text search.
What is Redis Sentinel?
- Provides High Availability for Redis, it monitors and detects failures, and halding automatic failover to a replica.
How to search for values in Redis?
- Redis doesn't provide search functionality in redis by default.
- RediSearch is a module pluggable to Redis to allow searching.
How to optimize Redis for high read volumes?
- using replicas
What is pipelining in Redis?
- Send multiple commands to Redis without waiting for results from previous ones. Fast and efficient, reduces round trip costs.
Limitations of Redis?
- not suitable for complex operations like table joins
- doesn't support for BLOB
How to monitor and debug performance issues?
-
redis-cli provides tools like:
- monitor: watch commands being executed in real-time
- slowlog: log slow operations
- info: for statistics about operation performance
-
Slowlog:
- logs operations that are slower than a target limit (set in configuration file)
- in memory only
- has max-len set in configuration files, stored in circular buffers
- SLOWLOG GET, SLOWLOG LEN, SLOWLOG RESET
How does it manage data?
- data expirations (set expiration times for keys)
- data partitioning (divide large datasets into smaller, more manageable chunks)
- offloading to persistent storage (store less frequently accessed data on disk, snapshots or log files)
- clustering (distribute across multiple redis instances)
Lua scripting?
- like SQL script to MySQL
- Redis lets users upload and execute Lua scripts on the serve
- used for atomic execution of complex operations
How to handle caching in a distributed enironment?
- redis instances has a caching layer in front of my database. Use consistent hashing to distribute keys across the cache nodes, ensures evey load distribution and reduces cache misses.
what happens if data in memory grows beyond the configured memory limit?
-
data eviction
- volatile-lru: evicts the LRU key from among the keys with an expiration set
- allkeys-lru: evicts the LRU key from all keys
- volatile-ttl: evicts the key with the nearest expiration time
- allkeys-random: evicts a random key from all keys
- volatile-random: evicts a random key from among the keys with an expiration set
- noeviction: error when memory limit is reached
- Disk Persistence
- RDB (Redis Database Backup): snapshot-based persistence method. configure to take period snapshots and save them to disk in binary format
- AOF (append-only file): this log is written to disk, allow redis to replay the log
- can be configured to save after every command, every second, or at specific times
- No Persistence
- RDB and AOF can be configure to work together
In case of hardware failure or server restarts, what happens?
- Redis can load data back into memory from disk (from most recent snapshots or append-only-files)
Configuration in redis.conf
- uncomment
requirepassdirective to enable ACL - use
protected-mode noto allow connections from other hosts (a testing container on the same docker network) - comment
bind 127.0.0.1 -::1to allow connections from network interfaces other than localhost - to specify rdb filename:
dbfilename dump1.rdb -
no-appendfsync-on-rewrite noduring an AOF rewrite, fsync (flushing IO buffer to disk) might block IO for too long. If this directive is set to yes, fsync will not happen during AOF rewrites.
Redis RDB and AOF configurations
-
use
appendonly yesto turn on AOF mode -
use
appendfsync everysec,appendfsync always, orappendfsync no, to configure append frequency. "appendfsync no" depends on the OS write buffer. -
use
save 3600 1to turn on snapshotting.3600 1means after 3600 seconds if at least 1 change was performed, save to snapshot -
what if AOF file gets truncated?
- redis will complain about the truncated data, and disrecard the data
-
what if AOF file gets corrupted?
- data loss, try to fix it manually. If not, use
redis-check-aof --fix, but this tool will discard all data from the corrupted place to the end of file.
- data loss, try to fix it manually. If not, use
-
AOF rewrite is automatically done from time to time. In a AOF rewrite, a new base RDB file and new log file will be created
-
use
auto-aof-rewrite-percentage 100andauto-aof-rewrite-min-size 64mbto set automatic rewrite rules. "precentage" to compared to previous aof file be last rewrite. minSize is to prevent rewrites when the file is still small. -
use
saveorbgsaveto trigger a snapshot dump
Redis practice
# Start cli: redis-cli -u redis://host:port
$ redis-cli -u redis://redis:6379
# Force a rdb save:
redis:6379> save
OK
# or bgsave:
redis:6379> bgsave
Background saving started
Redis ACL
# current user:
redis:6379> acl whoami
(error) NOAUTH Authentication required.
redis:6379> auth cqn%M?-0KR77
OK
redis:6379> acl whoami
"default"
redis:6379> acl users
1) "default"
redis:6379> acl list
1) "user default on sanitize-payload #e2d36090f11f7f36422ab17c5e8d53e344681894a6352d2455d9ef8e0dbbbc91 ~* &* +@all"
# Create a "root" user with get and set permissions on all keys
redis:6379> acl setuser inno_root on +GET +SET allkeys
OK
redis:6379> acl list
1) "user default on sanitize-payload #e2d36090f11f7f36422ab17c5e8d53e344681894a6352d2455d9ef8e0dbbbc91 ~* &* +@all"
2) "user inno_root on sanitize-payload ~* resetchannels -@all +get +set"
# To reset previous set rules and apply new one, use "reset"
redis:6379> acl setuser inno_root reset on allkeys +GET +SET
OK
redis:6379> acl list
1) "user default on sanitize-payload #e2d36090f11f7f36422ab17c5e8d53e344681894a6352d2455d9ef8e0dbbbc91 ~* &* +@all"
2) "user inno_root on sanitize-payload ~* resetchannels -@all +get +set"
# Create a "famapp_dev" user with get and set permissions on all famapp keys
redis:6379> acl setuser famapp_dev reset on (+SET +GET ~famapp*)
OK
redis:6379> acl list
1) "user default on sanitize-payload #e2d36090f11f7f36422ab17c5e8d53e344681894a6352d2455d9ef8e0dbbbc91 ~* &* +@all"
2) "user famapp_dev on sanitize-payload resetchannels -@all (~famapp* resetchannels -@all +set +get)"
3) "user inno_root on sanitize-payload ~* resetchannels -@all +get +set"
# Add a password "inno_root_2028" to inno_root:
# the sha256 hashed value of inno_root_2028 is cad44e192e03abf60ee69c38bd7a83893eea4e25ddaa41efe28ce5dedc8aab4f
redis:6379> acl setuser inno_root >inno_root_2028
OK
redis:6379> acl list
1) "user default on sanitize-payload #e2d36090f11f7f36422ab17c5e8d53e344681894a6352d2455d9ef8e0dbbbc91 ~* &* +@all"
2) "user famapp_dev on sanitize-payload resetchannels -@all (~famapp* resetchannels -@all +set +get)"
3) "user inno_root on sanitize-payload #cad44e192e03abf60ee69c38bd7a83893eea4e25ddaa41efe28ce5dedc8aab4f ~* resetchannels -@all +get +set"
# Delete a user
redis:6379> acl setuser inno_rot
OK
redis:6379> acl list
1) "user default on sanitize-payload #e2d36090f11f7f36422ab17c5e8d53e344681894a6352d2455d9ef8e0dbbbc91 ~* &* +@all"
2) "user famapp_dev on sanitize-payload resetchannels -@all (~famapp* resetchannels -@all +set +get)"
3) "user inno_root on sanitize-payload #cad44e192e03abf60ee69c38bd7a83893eea4e25ddaa41efe28ce5dedc8aab4f ~* resetchannels -@all +get +set"
4) "user inno_rot off sanitize-payload resetchannels -@all"
redis:6379> acl deluser inno_rot
(integer) 1
redis:6379> acl list
1) "user default on sanitize-payload #e2d36090f11f7f36422ab17c5e8d53e344681894a6352d2455d9ef8e0dbbbc91 ~* &* +@all"
2) "user famapp_dev on sanitize-payload resetchannels -@all (~famapp* resetchannels -@all +set +get)"
3) "user inno_root on sanitize-payload #cad44e192e03abf60ee69c38bd7a83893eea4e25ddaa41efe28ce5dedc8aab4f ~* resetchannels -@all +get +set"
Redis Basic Operations
# List all keys
> keys *
# set a key-value
> set sName "333"
> lpush sList "item1" "item2" "item3"
# get a value
> get sName
# delete a key
> del sName
# set a expiration for key
> set key2 "value1"
> expire key2 100
# or at the same time:
> setex key2 100 "value1"
List
- lpush: push left
- rpush: push right
- llen: get length
- lrange: retreive a range from list
- lpop: pop left
- rpop: pop right
127.0.0.1:6379> rpush list1 item1 item2 item3 item4
(integer) 4
127.0.0.1:6379> lrange list1 0 -1
1) "item1"
2) "item2"
3) "item3"
4) "item4"
127.0.0.1:6379> lpush list1 item0
(integer) 5
127.0.0.1:6379> rpush list1 item5
(integer) 6
127.0.0.1:6379> lrange list1 0 -1
1) "item0"
2) "item1"
3) "item2"
4) "item3"
5) "item4"
6) "item5"
127.0.0.1:6379> lpop list1
"item0"
127.0.0.1:6379> rpop list1
"item5"
127.0.0.1:6379> lrange list1 0 -1
1) "item1"
2) "item2"
3) "item3"
4) "item4"
Set
- sadd: add element
- srem: remove an element
- sismember: exists?
- smembers: get all elements
127.0.0.1:6379> sadd set1 item1 item2 item3
(integer) 3
127.0.0.1:6379> smembers set1
1) "item1"
2) "item2"
3) "item3"
127.0.0.1:6379> sismember set1 item1
(integer) 1
127.0.0.1:6379> sismember set1 item0
(integer) 0
SortedSets
- sets with scored elements, scores are used to determine order
- zadd: add element at target index
- adding an element at existing index overwrites
- adding an existing element to a different index is not allowed
- adding an element to a far end index with empty values in between will move the element front to append to end
- zrange: get ranged elements
- zrem: remove an element
- use cases: Leaderboards, Time-Based Events, priority queues, geolocation, real-time analytics
127.0.0.1:6379> zadd set2 3.3 item1 3.2 item2 9 item3
(integer) 3
127.0.0.1:6379> zrange set2 0 -1
1) "item2"
2) "item1"
3) "item3"
127.0.0.1:6379> zrange set2 0 -1 withscores
1) "item2"
2) "3.2"
3) "item1"
4) "3.3"
5) "item3"
6) "9"
127.0.0.1:6379> zadd set2 3.3 item5
(integer) 1
127.0.0.1:6379> zrange set2 0 -1 withscores
1) "item2"
2) "3.2"
3) "item1"
4) "3.3"
5) "item5"
6) "3.3"
7) "item3"
8) "9"
# adding items with the same socre, items ares store lexicographcally
127.0.0.1:6379> zadd set2 3.3 item0
(integer) 1
127.0.0.1:6379> zrange set2 0 -1 withscores
1) "item2"
2) "3.2"
3) "item0"
4) "3.3"
5) "item1"
6) "3.3"
7) "item5"
8) "3.3"
9) "item3"
10) "9"
# change score of an item
127.0.0.1:6379> zadd set2 3.9 item5
(integer) 0
127.0.0.1:6379> zrange set2 0 -1 withscores
1) "item2"
2) "3.2"
3) "item0"
4) "3.3"
5) "item1"
6) "3.3"
7) "item5"
8) "3.9"
9) "item3"
10) "9"
# remove an element from zSet
127.0.0.1:6379> zrem set2 item5
(integer) 1
127.0.0.1:6379> zrange set2 0 -1 withscores
1) "item2"
2) "3.2"
3) "item0"
4) "3.3"
5) "item1"
6) "3.3"
7) "item3"
8) "9"
Hashes
- used to store objects (string:string key-values)
- integers are stored as strings, floats are not supported. (floats are treated as strings, and can't use hincrby function)
- similar like objects, different key-values can be organized in a single object, efficient, atomic, flexible
127.0.0.1:6379> hset user anme Alice
(integer) 1
127.0.0.1:6379> hset user age 30
(integer) 1
127.0.0.1:6379> hset user email alice@example.com mobile 12345
(integer) 2
127.0.0.1:6379> hget user email
"alice@example.com"
127.0.0.1:6379> hgetall user
1) "anme"
2) "Alice"
3) "age"
4) "30"
5) "email"
6) "alice@example.com"
7) "mobile"
8) "12345"
127.0.0.1:6379> hincrby user age 1
(integer) 31
127.0.0.1:6379> hincrby user age -5
(integer) 26
Channels
- pub/sub
Message Queues
- lists with push and pop