Redis主要用于缓存,自定义map、guava的缓存也可以用于简单缓存。
自定义缓存时,注意value要使用SoftReference包装,以便JVM回收
guava缓存:CacheBuilder、LoadingCache
1. 数据结构
1. string
2. list
3. hash
4. set
5. zset
6. stream(5.0新增)
2. 持久化
RDB | AOF | |
---|---|---|
方式 | 快照存储 | 记录操作日志 |
特点 | 性能影响小、恢复速度快;同步时会丢失数据、数据大时影响对外服务 | 安全、易读;文件体积大、性能损耗大、数据大时恢复慢 |
策略 | 如:每5s操作2次。每5s检测一次,累计2次操作就开始持久化 | 每次操作记录/每秒记录/不记录 |
过期key处理逻辑 | 存储时过期key不会持久化到文件; 载入时过期key会通过主动清理和被动清理方式清理 | 存储时遇到过期key,就追加一条del命令 载入时会删除过期key |
3. 内存管理
默认:String
的value最大存储512M,list
、set
、 hash
元素最多2^32-1
个。
maxmemory
:最大内存阈值
maxmemory-policy
:到达阈值时执行的策略
noeviction
客户端执行会让更多内存被使用的命令直接报错allkeys-lru
在所有key里执行LRU算法volatile-lru
在所有已经过期key里执行LRU算法allkeys-lfu
在所有key使用近似LFU算法volatile-lfu
在所有已经过期key里执行LRU算法allkeys-random
在所有key里随机回收volatile-random
在所有过期的key里随机回收volatile-ttl
回收已经过期的key,优先回收TTL(存活时间)较短的key
主动处理和被动处理(时间以计算机本身时间)
-
主动
每秒执行10次
从所有过期的key集合中随机找20个,删除其中过期的key,如果删除的数量超过25%,则(认为过期的比较多,就)继续从头执行。
-
被动
每次访问key时,发现过期就清理掉。
4. 主从复制
-
解决单点故障、单节点QPS有限问题
-
场景:读写分离、故障切换
master关闭持久化、只用来处理数据和同步slave
slave只读、一个slave开启持久化 -
故障时启动流程
此时不能开启redis的自动重启,否则master是空数据,所有集群数据都会丢失。- 方法一:复制slave的持久化文件到master,启动
- 方法二:主从切换
- 1、断开slave的主从关系
- 2、原master作为原slave,作为从服务器
-
搭建
主:正常启动
从:两种方式
- 1.命令行 slaveof ip port
- 2.配置文件 加入:slaveof ip port
slave-read-only yes 从服务器是否只读
退出主从:Slaveof no one
-
主从复制流程:
- 从–psync(partial synchronization)–> 发送同步源ID、同步进度offset到主
- 如果同步源ID为当前master,则根据偏移量增量同步
- 如果不是当前master,则进行全量同步:master生成rdb,传到slave,加载到slave内存
-
核心知识:
- Redis默认使用异步复制,master、slave异步确认处理数据
- 一个master可以有多个slave
- slave可以接受其他slave的连接,slave可以有sub slave
- 同步过程中master非阻塞、slave初次同步会阻塞
-
注意事项
slave不会让key过期,而是等待master让key过期,然后同步过去。
5. 哨兵高可用
-
哨兵:监控、提醒、主从切换
SENTINEL get-master-addr-by-name mymaster(集群名称) -
哨兵集群
大家确定master有问题,才会进行主从切换
-
访问时机:(其他时间客户端与哨兵没有交集,哨兵只是给客户端提供一个redis地址)
初始启动
master节点挂掉 -
运作流程
服务发现和健康检查流程
故障切换流程 -
核心概念
- 自动发现机制
哨兵如何知道Redis主从信息
从配置文件中知道Redis master,从master获取Redis集群信息(info replication),判断master挂了的标准(如:2个哨兵任务挂了才算挂) - 什么是master主观下线
单个哨兵认为master已下线 - 什么是master客观下线
一定数量值得哨兵认为master已下线 - 哨兵之间的自动发现
哨兵直接如何通信- 哨兵自动发现:多个哨兵检测同一个Redis,通过“sentinel:hello”发布订阅。
- 哨兵通过命令直接通信
- 哨兵直接通过发布订阅进行通信
- 哨兵领导选择机制(哪个哨兵负责故障转移)
https://raft.github.io/
https://thesecretlivesofdata.com/
基于Raft算法实现选举机制(每个节点拉票前,会随机延迟一段时间)- 拉票:每个哨兵都希望成为一个领导者,向其他节点发送拉票命令
- sentinel节点收到拉票命令后,只同意接受到的第一个拉票命令(每个sentinel节点只持有一个同意票数
- sentinel节点发现自己的票数超过一半数值,就自动成为领导者,去执行故障转移
- 投票结束后,如果超过failover-timeout时间内,没有进行故障转移,则重新拉票选举。
- slave选举机制
- slave节点状态判断
- redis.conf配置文件中选优先级高的
- 数据同步情况最好的
- run id最小的(字典顺序,ASCII码)
- 最终主从切换过程
- 即将成为master的slave退出集群
- 其他slave节点成为新master的slave
- 1主2从也是非强一致性的
2主之后,旧的服从新的
- 自动发现机制
6. 集群分片存储(redis cluster)
-
场景:3kw用户,10G内存,如何设计
-
把Redis分为16383个slot(位置/槽)
solt不存储数据,只是一个位置划分 -
hash算法:crc16,计算每个key的redis-server位置
-
3主3从,有了分片存储,实际上就不需要sentinel机制了
-
问题:
- slot槽计算,性能问题
槽计算算法公开,客户端可以进行计算并缓存槽的对应关系,避免多次重定向带来的性能损耗 - redis集群,可以装多少数据
理论上16384个槽,每个槽对应一个实例。官方建议最大1000个实例。 - 节点通讯
额外TCP端口。故障检测转移方式类似哨兵模式 - ask和moved重定向
确定slot不属于当前节点、redis返回moved - 数据倾斜和访问迁移
前期:设计时提前预测,比如key规则相同,可以预测hash都会集中在一个0~1000,此时可以提前规划
后期:solt迁移,将压力分摊 - 节点之间交换信息,带来贷款消耗
避免一个大集群,可以分多个集群 - pub/sub发布订阅机制
对集群中人一个节点执行publish发布消息,这个消息会在集群中进行传播,其他节点接收到发布的消息 - 读写分离
没有读写分离 从节点只是用来备份。
默认所有从节点的读写,都会重定向到对应的主节点
可以设置可以修改
- slot槽计算,性能问题
7. Redis监控
- monitor
修改密码等管理型命令不会记录,会降低Redis的吞吐量 - info 返回Redis信息
- RedisLive 可视化监控