中间件-Redis
常用数据结构
数据结构 | 常用场景 |
---|---|
String | 1. 单值缓存 2. 对象缓存 3. 分布式锁 4.计数器 5.session共享 |
Hash | 1. 对象缓存 2. 购物车 |
List | 1. 栈(LPUSH+LPOP) 2. 队列(LPUSH+RPOP) 3. 阻塞队列(LPUSH + BRPOP) |
Set | 抽奖,点赞,收藏,标签,关注模型以及条件筛选等 |
Sorted Set | 排行 |
持久化
- RDB快照
可以通过配置文件来设置条件来触发。生成快照有两种方式: save
(同步 )和bgsave
(异步),默认使用的是bgsave
。
# 60s内至少发生了100次改动 save 60 100
缺点: 会丢失数据。比如上述示例配置,当60秒内没有达到100次修改,此时redis服务宕机,会导致该时间内的变更都会丢失。
- AOF
会将修改的每一条指令都保存到aof
文件中(resp协议)。
# 启用 appendonly yes # 三种持久策略,默认everysec # appendfsync always appendfsync everysec # appendfsync no
- AOF重写
优化aof文件中命令。重写时使用的是bgrewriteaof
命令,执行该命令时,redis会fork一个子进程,对客户端的操作不会有太大的影响
配置
# 当aof文件达到100兆才会自动重写 auto-aof-rewrite-min-size 100mb # 自上一次重写后文件增长了100% auto-aof-rewirte-percentage 100
- 混合持久化(Redis4.0以上)
在重写的时候,将RDB数据和AOF数据都存储在AOF文件中。
配置
aof-use-rdb-preamble yes
主从架构
配置示例
redis: 配置文件位置: /usr/local/etc/redis.conf db文件位置: /usr/local/var/db/redis/ 主从结构: master: 127.0.0.1:6379 slave: 127.0.0.1:6380, 127.0.0.1:6381 配置: dir /usr/local/var/db/redis/data/6380 pidfile /var/run/redis_6380.pid port 6380 replicaof 192.168.0.119 6379 # 从节点只读 replica‐read‐only yes 启动master: redis-server /usr/local/etc/redis.conf 启动slave: redis-server /usr/local/etc/my_redis/redis-6380.conf redis-server /usr/local/etc/my_redis/redis-6381.conf
同步原理
- 全量同步
当slave节点启动时,会给master发送psync命令;master收到同步请求后,会执行bgsave,生成最新的rdb文件;master将最新的rdb文件发送给salve节点;将repl_back_buffer
中的数据也一起发送给slave;最终salve将rdb和buffer中的数据合并生成新的rdb文件,并load到内存中。 - 增量同步
当slave发送的psync(offset)命令时,若offset落在repl_back_buffer
数据中,则进行增量同步。
- 全量同步
哨兵架构
- 配置示例
配置文件位置: /usr/local/etc/my_sentinel/sentinel_26379.conf /usr/local/etc/my_sentinel/sentinel_26380.conf /usr/local/etc/my_sentinel/sentinel_26381.conf 配置: sentinel monitor mymaster 127.0.0.1 6379 2 启动: redis-sentinel /usr/local/etc/my_sentinel/sentinel_26379.conf redis-sentinel /usr/local/etc/my_sentinel/sentinel_26380.conf redis-sentinel /usr/local/etc/my_sentinel/sentinel_26381.conf
集群架构
- redis集群是由多个主从节点群组成的,集群最少需要3个master节点。
- redis集群用key值通过哈希算法(
CRC16
)计算出一个整数值后对16384进行取模,计算出槽位。集群中的master节点分别负责处理对应槽位区间的数据处理。 - redis集群中的节点通过gossip协议通信。
- 脑裂问题
因网络波动导致的脑裂问题(主从节点产生了多个master节点)可能会导致数据丢失,可以通过以下设置解决。# 写数据时,最少需要同步的slave数量 min-salves-to-write 1
但是在一定程度上损失了集群的可用性,因为如果master节点下的slave节点都挂了,master就提供不了服务了。不过redis还是尽量满足AP,保证可用性。 - 批命令操作时,若key值计算后的槽位不同,集群为了保证命令执行的原子性会让整条命令执行失败,也就是不支持。
可以通过{}形式指定参与计算slot值的key,如下mset {slotKey}:key1 xxx {slotKey}:key2 yyy
常见面试题
- redis可以用来做主键生成器吗?如何实现?
可以,使用incrby
命令,给单个应用批量获取一个id
区间,然后在该应用内存中操作,可以大大减少redis
的资源消耗。不可使用incr
。 - redis单线程为什么性能还那么高?
- 数据存在于内存,属于内存级运算。
- 单线程无线程上下文切换。
- redis单线程如何处理多客户端链接?
- 利用epoll实现IO多路复用。
- RDB和AOF均开启时,redis服务启动时,是如何恢复数据的?
会优先使用AOF文件,因为AOF数据更全。