【Redis】概览
准备写一个关于 Redis 的系列文章,本片从全局视角概括介绍 Redis。
Redis 是一个开源(BSD 许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA 脚本(Lua scripting), LRU 驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis 哨兵(Sentinel)和自动分区(Cluster)提供高可用性(high availability)。
数据类型
Redis 支持五种数据类型:string(字符串),list(列表),hash(哈希),set(集合)及 zset(sorted set:有序集合)。
https://redis.io/topics/data-types-intro
注:后续会出单独章节介绍 Redis 数据结构及其底层实现。
string
append <key> value
set/setex/psetex/setnx/mset/msetnx/get/mget/getset/getrange/strlen
incr <key>/incrby <key> incement/incrbyfloat <key> incement
附加:bit 操作
setbit <key> offset value
getbit <key> offset
bitcount <key>
list
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
一个列表最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过 40 亿个元素)。
set
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一不可重复的。Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储 40 多亿个成员)。
zset
Redis Zset 和 Set 一样也是 string 类型元素的集合,成员也是唯一不可重复的。,但分数(score)却可以重复。zset 通过分数来为集合中的成员进行从小到大的排序。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储 40 多亿个成员)。
hash
Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,适合用于存储对象。每个 hash 可以存储 232 - 1 键值对(40 多亿)。
hyperloglogs
geo
Redis geo 主要用于存储地理位置信息,并对存储的信息进行操作
streams
Redis Stream 是 Redis 5.0 版本新增加的数据结构。
Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。
简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。而 Redis Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。
https://redis.io/topics/streams-intro
key 管理
持久化
RDB
RDB 就是 Snapshot 快照存储,是默认的持久化方式。
可理解为半持久化模式,即按照一定的策略周期性的将数据保存到磁盘。
对应产生的数据文件为 dump.rdb,通过配置文件中的 save 参数来定义快照的周期。
下面是默认的快照设置:
save 900 1 #当有一条 Keys 数据被改变时,900 秒刷新到 Disk 一次
save 300 10 #当有 10 条 Keys 数据被改变时,300 秒刷新到 Disk 一次
save 60 10000 #当有 10000 条 Keys 数据被改变时,60 秒刷新到 Disk 一次
AOF
当使用 redis 存储非临时数据时,一般需要打开 AOF 持久化来降低进程中止导致的数据丢失。AOF 可以将 redis 执行的每一条写命令追加到硬盘文件中,这一过程显然会降低 redis 的性能,但是大部分情况下这个影响是可以接受的,另外使用较快的硬盘可以提高 AOF 的性能。
开启 appendonly yes
重写机制
随着执行的命令越来越多,AOF 文件的大小也会越来越大,冗余的命令会越来越多。redis 可以自动优化 AOF 文件,每当达到一定条件时 redis 就会自动重写 AOF 文件。这个条件可以在配置文件中配置:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
auto-aof-rewrite-percentage 参数的意义是当目前的 AOF 文件大小超过上一次重写时的 AOF 文件大小的百分之多少时会再次进行重写,如果之前没重写过,则以启动时的 AOF 文件大小为依据。
auto-aof-rewrite-min-size 参数限制了允许重写的最小 AOF 文件大小,通常在 AOF 文件很小的情况下即使其中有很多冗余的命令我们也不太关心。除了让 redis 自动执行重写外,我们还可以主动使用 BGREWRITEAOF 命令手动执行 AOF 重写。
同步机制 appendfsync
always
everyseconds
no
进阶
缓存过期
过期策略
定时过期
为每一个设置了过期时间的 key 设置一个定时器,对 cpu 不友好
惰性过期
使用 key 才检查是否过期,对内存不友好,如果 key 长时间不访问容易导致内存不足
定期过期
这种方案,每隔一定时间,会扫描一定数量的数据库的 expires 字典一定数量的 key,并清除其中已经过期的 key
Redis 使用惰性过期与定期过期相结合的方式,过期策略对 rdb 及 aof 模式均没有影响
命令
expire <key> time
ttl <key>
persist <key>
淘汰键策略
volatile-lru 使用 LRU 算法删除一个键(只对设置了过期时间的键)
allkeys-lru 使用 LRU 算法删除一个键
volatile-random 随机删除一个键(只对设置了过期时间的键)
allkeys-random 随机删除一个键
volatile-ttl 删除过期时间最近的一个键
noeviction
volatile-lfu 使用 LFU 算法删除一个键(只对设置了过期时间的键)
allkeys-lfu 使用 LFU 算法删除一个键
事务
https://redis.io/topics/transactions
DISCARD
EXEC
MULTI
UNWATCH
WATCH
注:后续会出单独章节介绍 Redis 事务。
数据迁移工具
阿里巴巴:https://github.com/alibaba/RedisShake
唯品会:redis-migrate-tool
pipline
https://redis.io/topics/pipelining
注:后续会出单独章节介绍 Redis pipline。
高可用
主从复制
哨兵模式
Cluster
客户端
jredis
lettuce
redisson
业务应用场景
缓存
排行榜
基于 zset,将分数作为 score,然后做排序查询
分布式锁
基于 setnx
基于 redlock
在线用户数
SETBIT "online_users" <user_id> 1
GETBIT "online_users" <user_id>
BITCOUNT "online_users"
注意:仅统计在线用户数不关心具体在线用户的话,可以使用基数统计替代
最新列表
基于 zset,将更新时间设置为 score,然后做排序查询
队列
基于 list 的普通队列
基于 zset 的优先级队列
基数统计
基于 hyperloglogs
评论