Most of the contents of this note are excerpted from the Redis official documentation. It is recommended to read the official documentation directly if you want to learn Redis.
Redis data types
Data structures supported by Redis:
- Binary-safe strings
- Lists: collections of string elements sorted according to the order of insertion. They are basically linked lists.
- Sets: collections of unique, unsorted string elements.
- Sorted sets, similar to Sets but where every string element is associated to a floating number value, called score.The elements are always taken sorted by their score, so unlike Sets it is possible to retrieve a range of elements(for example you may ask: give me the top 10, or the bottom 10).
- Hashes, which are maps composed of fields associated with values. Both the field and the value are strings. This is very similar to Ruby or Python hashes.
- Bit arrays(or simply bitmaps): it is possible, using special commands, to handle String values like an array of bits: you can set and clear individual bits, count all the bits set to 1, find the first set or unset bit, and so forth.
- HyperLogLogs: this is a probabilistic data structure which is used in order to estimate the cardinality of a set.
- Streams: append-only collections of map-like entries that provide an abstract log data type.
Redis keys
- Binary safe.
- Key should not very long or very short. Name key with a stick schema.
- Max key size is 512MB.
Redis Strings
- Max value size is 512MB.
- INC, INCRBY, DECR and DECRBY can perform with string, these commands parse the string value as an integer.
- The ability to set or retrieve the value of multiple keys in a single command is also useful for reduced latency, like MGET, MSET.
Redis expires: keys with limited time to live
- They can be set both using seconds or milliseconds precision. However, the expire time resolution is always 1 millisecond.
- Information about expires are replicated and persisted on disk, the time virtually passes when your Redis server remains stopped (this means that Redis saves the date at which a key will expire).
- We can use EXPIRE to set the expire, use PERSIST to remove the expire, and we can also create keys with expires using other Redis commands, like SET options.
Redis Lists
- Redis Lists are implemented via Linked Lists. This means that you can add elements to a list in constant time. But accessing an element by index is not so fast.
- When fast access to the middle of a large collection of elements is important, there is a different data structure that can be used, called sorted sets.
Redis List Commands:
-
LPUSH/RPUSH: both are variadic commands that you can push multiple elements into a list in a single call.
-
LRANGE/RRANGE: both are technically O(N) commands
-
LPOP/RPOP
-
LTRIM/RTRIM: remove all the elemenets outside the given range
-
BLPOP/BRPOP: blocking LPOP/RPOP if the list is empty, and you can specify multiple lists in order to wait on multiple lists at the same time.
-
RPOPLPUSH/BRPOPLPUSH
//a simple lpoprpush.lua script: local src_list = ARGV[1] local dst_list = ARGV[2] local value = redis.call('lpop', src_list) if value then -- avoid pushing nils redis.call('rpush', dst_list, value) end return value
Redis Hashes
- Some commands: HMSET/HGET/HMGET/HGETALL
- It is worth noting that small hashes (i.e., a few elements with small values) are encoded in special way in memory that make them very memory efficient.
Redis Sets
- Some commands: SADD/SMEMBERS/SISMEMBER/SCARD/SRANDMEMBER/SPOP
- Redis is free to return the elements in any order at every call
Redis Sorted sets
- Assume A and B are two elements in a sorted set, if (A.score > B.score) || (A.score == B.score and A.string > B.string) then A > B else A < B
- Some commands: ZADD( O(log(N)) )/ZRANGE/ZREVRANGE/ZRANGEBYSCORE/ZRMRANGEBYSCORE/ZRANK/ZREVRANK
Redis Bitmaps
- Some commands: SETBIT/GETBIT/BITOP/BITCOUNT/BITPOS
HyperLogLogs
- A HyperLogLog is a probabilistic data structure used in order to count unique things (technically this is referred to estimating the cardinality of a set).
- A HyperLogLog do not include actual elements, it trade memory for precision, 12k bytes in the worst case with a standard error less than 1%.
- Some commands: PFADD/PFCOUNT
Remarks
- Redis ZSET 内部实现是 skiplist,参考Redis内部数据结构详解(6)——skiplist (需要系统了解)
- Redis 源码阅读
Redis Lua scripting
- Keys must be passed explicitly
- If you want to return a float from Lua you should return it as a string
- Redis guarantees that a script is executed in an atomic way, this also means that executing slow scripts is not a good idea.
- Calls to redis.call() resulting in a Redis command error will stop the execution of the script and return an error, while using redis.pcall() no error is raised, but an error object is returned in the format specified above (as a Lua table with an err field)
- Using EVALSHA to reduce the bandwidth penalty.
- The only way to flush the script cache is by explicitly calling the SCRIPT FLUSH command, which will completely flush the scripts cache removing all the scripts executed so far.
- Restarting a Redis instance flushes the script cache, which is not persistent.
- Scirpts as pure functions:
- Before Redis 3.2, scripts are replicated by sending the whole script. Let’s call this replication mode whole scripts replication.
- Things like using the system time, calling Redis random commands like RANDOMKEY, or using Lua random number generator, could result into scripts that will not always evaluate in the same way, so it will cause the consensus problem of replication.
- In order to enforce this behavior in scripts Redis does the following:
- Lua does not export commands to access the system time or other external state.
- Redis will block the script with an error after a Redis random command like RANDOMKEY, SRANDMEMBER, TIME, except read-only scripts.
- In Redis version 4,Commands that may return elements in random order, like SMEMBERS, when called from Lua, and undergo a silent lexicographical sorting filter before returning data to Lua scripts. So redis.call(“smembers”,KEYS[1]) will always return the Set elements in the same order. However starting with Redis 5 there is no longer such ordering step, because Redis 5 replicates scripts in a way that no longer needs non-deterministic commands to be converted into deterministic ones. In general, even when developing for Redis 4, never assume that certain commands in Lua will be ordered, but instead rely on the documentation of the original command you call to see the properties it provides.
- Lua pseudo random number generation functions math.random and math.randomseed are modified in order to always have the same seed every time a new script is executed. This means that calling math.random will always generate the same sequence of numbers every time a script is executed if math.randomseed is not used.
- Starting with Redis 3.2, we can just replicate single write commands generated by the script, we call this script effects replication.
- In order to enable script effects replication, you need to issue the following Lua command before any write operated by the script:
redis.replicate_commands()
- Redis scripts are not allowed to create global variables, in order to avoid leaking data into the Lua state. If a script needs to maintain state between calls (a pretty uncommon need) it should use Redis keys instead.
Redis 持久化
Redis Sentinel
- Sentinel capablilities at a macroscopical level:
- Monitoring
- Notifaction
- Automactic failover
- Configuration provider
- Sentinel is a distributed system
- A stable release of Redis Sentinel called Sentinel 2 is shipped since Redis 2.8. Redis Sentinel 1, shipped with Redis 2.6, is deprecated and should not be used.
- You need at least three Sentinel instances for a robust deployment.
- Subjectively Down(SDOWN) / Objectively Down(ODOWN) . The ODOWN condition only applies to masters.
- Sentinel uses the Redis instances Pub/Sub capabilities in order to discover the other Sentinels that are monitoring the same masters and replicas.
本文地址