本文以 Redis 5.0.7 为准。
基本概念
Redis 是开源的(BSD 协议)内存数据存储。
以 KV 的方式存储数据。
key 类型固定为 string,value 支持的类型有:
- string
- list
- set
- zset
- hashtable
淘汰策略
- volatile-lru:从已设置过期的数据集中挑选最近最少使用的淘汰
- volatile-lfu:从已设置过期的数据集中挑选使用频率最少的淘汰
- volatile-ttl:从已设置过期的数据集中挑选将要过期的数据淘汰
- volatile-random:从已设置过期的数据集中任意挑选数据淘汰
- allkeys-lru:从数据集中挑选最近最少使用的数据淘汰
- allkeys-lfu:从数据集中挑选使用频率最少的淘汰
- allkeys-random:从数据集中随机挑选数据淘汰
- noenviction:不淘汰
持久化
RDB
定期将数据全量保存到磁盘。
保存的文件名默认为 dump.rdb,所在目录默认为 %REDIS_HOME%/etc。
文件名和所在目录均可配。
1#x秒内如果有超过y个key被修改则发起保存快照 2save x y 3 4#900秒内如果有超过1个key被修改则发起保存快照 5save 900 1 6#300秒内如果有超过10个key被修改则发起保存快照 7save 300 10 8#60秒内如果有超过1000个key被修改则发起保存快照 9save 60 10000
AOF
记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。
这种方式也可能丢数据:程序将记录写入文件,但操作系统实际上是将修改保存到了缓冲区,还没来得及同步到磁盘。
1#启用AOF 2appendonly yes 3 4# always - 每次有新命令追加到 AOF 文件时就调用 fsync 5# everysec - 每秒调用一次 fsync 6# no - 从不调用 fsnyc,即交给操作系统去同步 7# 这三种方式,可靠性递减,性能递增 8appendfsync always
事务
MULTI 开启一个事务。当客户端发出了MULTI 命令时,客户端和服务端的连接就进入了一个事务上下文的状态。MULTI 执行之后, 客户端可以继续向服务器发送任意多条命令, 这些命令不会立即被执行, 而是被放到一个队列中, 当 EXEC 命令被调用时, 所有队列中的命令才会被执行。
EXEC 顺序执行事务队列中的命令。
1192.168.2.129:6379> multi 2OK 3192.168.2.129:6379> set name "zhangsan" 4QUEUED 5192.168.2.129:6379> set age 20 6QUEUED 7192.168.2.129:6379> exec 81) OK 92) OK 10192.168.2.129:6379> keys * 111) "age" 122) "name"
DISCARD 取消事务。当执行 DISCARD 命令时, 事务会被放弃, 事务队列会被清空, 并且客户端会从事务状态中退出。
1192.168.2.129:6379> multi 2OK 3192.168.2.129:6379> set name2 "lisi" 4QUEUED 5192.168.2.129:6379> set age 22 6QUEUED 7192.168.2.129:6379> discard 8OK 9192.168.2.129:6379> exec 10(error) ERR EXEC without MULTI
发布订阅
Redis的发布以及订阅有点类似于聊天,是一种消息通信模式。在这个模式中,发送者(发送信息的客户端)不是将信息直接发送给特定的接收者(接收信息的客户端), 而是将信息发送给频道(channel), 然后由频道将信息转发给所有对这个频道感兴趣的订阅者。SUBSCRIBE 、 UNSUBSCRIBE 和 PUBLISH 三个命令实现了消息的发布与订阅。如下
Client1发布频道mychannel与消息
1192.168.2.129:6379> publish mychannel "message from channel1" 2(integer) 1
Client2 订阅频道mychannel并接受Client1通过频道发过来的消息
1192.168.2.129:6379> subscribe mychannel 2Reading messages... (press Ctrl-C to quit) 31) "subscribe" 42) "mychannel" 53) (integer) 1 61) "message" 72) "mychannel" 83) "message from channel1"
延迟队列
运用 zset 实现
zset 的成员为事件的编号,score 为时间或时间戳(视情况)
周期性地扫描 zset,取出执行时间小于等于当前时间的任务。