Redis进阶
2021-01-25 15:43:55 5 举报
AI智能生成
Redis
作者其他创作
大纲/内容
内存
压缩
ziplist
<br>
intset<br>
结构图
内存释放
方式
达到内存限制,触发淘汰策略释放
流程
1. 客户端运行新命令,从而添加更多数据。<br>2. Redis会检查内存使用情况,如果大于使用<b>maxmemory</b>限制,则会根据该策略逐出密钥。<br>3. 执行新命令,依此类推。
抛弃策略
LRU算法
LRU概念的,常规实现
Redis的LRU实现
Redis LRU<b>算法不是确切的实现。是一种近似的实现</b>,它对少量密钥进行<b>采样</b>,<br>然后从采样的密钥中淘汰最好的(访问时间最长)密钥。<br><br>Redis 3.0后进行了优化,可以淘汰一批过期的key
参数
maxmemory-samples 5
LFU 更准确的算法
概念
从Redis 4.0开始,可以使用新的 LFU 算法, Redis会跟踪Key的<b>访问频率</b>,以驱逐极少使用的Key被<br><br>LFU近似于LRU:它使用概率计数器(<b>莫里斯计数器</b>),<br>仅使用每个对象的几个位来估计对象访问频率,并结合衰减周期,从而使计数随时间而减少。<br><br>LFU具有某些可调参数:例如,如果频繁访问的项不再受访问,应该将其降低多快?<br>也可以调整Morris计数器范围,以使算法更好地适应特定的用例。<br>
参数
volatile-lfu 使用具有过期集的密钥在近似的LFU中进行驱逐。<br>allkeys-lfu 使用近似的LFU退出任何密钥。
lfu-log-factor 10<br>lfu-decay-time 1
Key过期释放
释放时机
被动
主动
<ol><li>从所有密钥中测试20个随机密钥,以及相关联的到期时间。</li><li>删除找到的所有密钥已过期。</li><li>如果超过25%的密钥已过期,请从步骤1重新开始。</li></ol>
精度
Redis 2.6 以下版本为。一秒
指令
TTL key
EXPIRE / PEXPIRE
Redis不会总是将内存释放(返回)到OS <br>因为基础分配器无法轻松释放内存 <br>例如,通常大多数已删除的密钥与仍然存在的其他密钥分配在相同的页中<br>
高可用
主从复制
特点
1.master可以拥有多个slave<br>2.多个slave可以连接同一个master外,还可以连接到其他slave<br>3.主从复制不会阻塞master,在同步数据时,master可以继续处理client请求<br>
同步流程
1,定时任务每秒检查是否有新的mater需要连接,如果发现就与master建立socket连接。<br>2,slave 发送ping指令到mater。<br>3,如果mater配置require pass,slave需要发送认证给master。<br>4,Salve会发送sync命令到Master。<br>5, Master启动一个后台进程,将Redis中的数据快照rdb保存到文件中。<br>6,启动后台进程的同时,Master会将保存数据快照期间接收到的写命令缓存起来。<br>7,Master完成写文件操作后,将rdb发送给Salve。<br>8,Salve将rdb保存到磁盘上,然后加载rdb到redis内存中。<br>9,当Salve完成数据快照的恢复后,Master将这期间收集的写命令发送给Salve端。<br>10,后续Master收集到的写命令都会通过之前建立的连接,增量发送给salve端。
断点续传
1)从服务器向主服务器发送PSYNC命令,携带主服务器的runid和复制偏移量;<br>2)主服务器验证runid和自身runid是否一致,如不一致,则进行全量复制;<br>3)主服务器验证复制偏移量是否在积压缓冲区内,如不在,则进行全量复制;<br>4)如都验证通过,则主服务器将保持在积压区内的偏移量后的所有数据发送给从服务器,主从服务器再次回到一致状态。
哨兵
功能
<ol><li>集群监控:负责监控redis master和slave进程是否正常工作 </li><li>消息通知:如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员 </li><li>故障转移:如果master node挂掉了,会自动转移到slave node上 </li><li>配置中心:如果故障转移发生了,通知client客户端新的master地址</li></ol>
故障转移时,判断一个master node是宕机了,需要大部分的哨兵都同意才行,涉及到了分布式选举的问题<br>哨兵至少需要3个实例,来保证自己的健壮性<br>哨兵 + redis主从的部署架构,是不会保证数据零丢失的,只能保证redis集群的高可用性
细节
quorum和majority
quorum:确认odown的最少的哨兵数量<br>majority:授权进行主从切换的最少的哨兵数量<br>每次一个哨兵要做主备切换,首先需要quorum数量的哨兵认为odown,<br>然后选举出一个哨兵来做切换,这个哨兵还得得到majority哨兵的授权,才能正式执行切换
sdown和odown
sdown是主观宕机,就一个哨兵如果自己觉得一个master宕机了,那么就是主观宕机
odown是客观宕机,如果quorum数量的哨兵都觉得一个master宕机了,那么就是客观宕机
Redis Cluster
hash槽
扩容/移除<br>
缺点
通常不支持涉及多个键的操作。例如,如果两个集合存储在映射到不同Redis实例的键中,则无法执行它们之间的交集运算等
不能使用涉及多个密钥的Redis事务
无法使用单个大键(如非常大的排序集)对数据集进行分片
添加删除节点复杂
分布式一致性,维护
Gossip协议
流程
redis每100ms调用clusterCron函数向其他节点发送请求
为了减少交互信息产生的网络压力。<br>Redis每次只向部分节点发送消息 最多5个。<br>采用随机+最晚期望时间(很久没有交互过的节点加入到通知队列)的方式,进行交互
故障发现
1. 单节点发线<br>比如A 节点 ping B节点。B节点超时未响应。A节点认为B节点下线;<br>A节点会在消息互通时传播B节点疑似下线
2. 信息传播<br>A节点对C节点 发送B节点下线消息,<br>C会将A节点的意见保存起来(C节点后面会优先PING A节点)<br>C节点自己检测到B节点下线的话也会继续走<b>步骤1</b>
3. 判决下线<br>C节点保存的B节点下线意见,已超过节点数一半时,向所有节点广播Fail消息,<br>所有收到消息的节点都会标记B节点为下线状态
故障转移
当B的从节点接到Fail消息后<br>
对从节点的资格进行检查<br>每个从节点检查与故障主节点的断线时间<br>超过cluster-node-timeout * cluster-slave-validity-factor数字,则取消资格<br>cluster-node-timeout默认为15秒,cluster-slave-validity-factor默认值为10<br>默认延时如果超过150秒,则这个节点就没有成为替换主节点的可能性
有权限的从节点会向其他主节点广播(只有主节点有权投票)<br>让他们投票给自己
投票发起延时<br><br>延迟公式:DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms<br>rank是复制偏移量排名倒序排名,排名高优先发起投票
子主题
脑裂
min-slaves-to-write 3<br><br>min-slaves-max-lag 10<br>
性能优化
Big keys
定义
引发的问题
大value带来的IO负担
大集合,大value,造成集群内存分布不均匀
阻塞
删除阻塞
排查
bigkeys
其他地方工具
延迟删除
禁用透明大页
页交换引起的延时
大量密钥同时过期,引起延迟
数据结构<br>
strings
lists
sets
sorted sets
跳表(实现方式)<br>
优点
区间查找操作,红黑树的效率没有跳表高。<br>
相比于红黑树,跳表还具有代码更容易实现、可读性好、不容易出错、更加灵活等优点
缺点
额外内存
bitmaps
场景
登录天数
在线人数
连续登录天数等
语法
setbit key offset value
getbit key offset
bitcount [start][end]
位运算
bitpos <br>
hyperloglogs
原理
geospatial indexes
高级特性<br>
事物
概念
事务的本质是一组命令的集合
没有隔离级别的概念
不保证原子性,且没有回滚
流程
开始事务<br><br>命令入队<br><br>执行事物(批量执行命令)<br><br>返回结果
发布订阅(pub/sub)
<span style="font-size: inherit;">Redis发布订阅有一个明显的问题,订阅者如果重启(上线下线)<br>就会丢失这段时间的消息,<br></span>所以一般在项目中应用场景比较少
管道
概念
与事物的区别
事物命令会进入队列,等待提交时统一执行
管道会即刻执行,并缓存返回结果。只是将结果统一返回
Lua脚本
分布式锁
普通
上锁
上锁失败,短暂睡眠后进行重试
bug
线程执行时间超过,Key超时时间
当发生主从切换时可能导致,setNX的key丢失,可能产生重复上锁问题
进阶
通过异步任务,在超时之前,对未释放的锁进行续期
Redlock
1. 它以毫秒为单位获取当前时间。<br><br>2. 它尝试在所有N个实例中顺序使用所有实例中相同的键名和随机值来获取锁定。<br> 在第2步中,在每个实例中设置锁定时,客户端使用的超时时间小于总锁定自动释放时间,以便获取该超时时间。<br> 例如,如果自动释放时间为10秒,则超时时间可能在5到50毫秒之间。这样可以防止客户端长时间与处于故障状态的Redis节点通信时保持阻塞:<br> 如果一个实例不可用,我们应该尝试与下一个实例尽快通信。<br> <br>3. 客户端通过从当前时间中减去在步骤1中获得的时间戳,来计算获取锁所需的时间。<br> 当且仅当客户端能够在大多数实例中获取锁时,并且获取锁所花费的总时间小于锁有效时间,则认为已获取锁。<br><br>4. 如果获取了锁,则将其有效时间视为初始有效时间减去经过的时间,如步骤3中所计算。<br><br>5. 如果客户端由于某种原因(无法锁定(N / 2) + 1实例或获取锁超时)而未能获得该锁,<br> 它将尝试解锁所有实例(即使是它认为无法锁定的实例)。
单线程?
持久化
RDB
触发
SAVE
BGSAVE
根据redis.conf配置里的save m n定时触发
执行Shutdown且没有开启AOF持久化
主从复制时,主节点自动触发
缺点
延时比较高,断电死机等情况。数据丢失比较多
优点
体积较小,恢复快
copy on write
数据段是由很多操作系统的页面组合而成,当父进程对其中一个页面的数据进行修改时,<b>会将被共享的页面以及指向的数据复制一份分离出来(重新申请一块内存空间)</b>,<b>然后对这个新的页面进行修改。</b><br><br>这时子进程的页是没有变化的,还是进程产生时那一瞬间的数据。<br><br><b>随着父进程修改操作的持续进行,越来越多的共享页面被分离出来,内存就会持续增长。但是理论上不会超过原有数据内存的 2 倍大小。</b>
AOF
内容
记录除了查询以外的所有变更数据库状态的指令
日志重写解决AOF文件不断增大的问题,原理如下
调用fork,创建一个子进程
子进程读取旧的AOF文件,压缩并写入到一个临时AOF<br>
主进程持续将新的变动同时写到内存和原来的AOF里
主进程获取子进程重写AOF完成信号,往新AOF同步增量变动
使用新的AOF文件替换掉旧的AOF文件
优点
可读性好
数据丢失可控
缺点
文件体积大,恢复时间长<br>
<b>刷盘之前利用页缓存,会占用额外内存空间,占用多少可通过内核参数配置</b>
混合模式<br>
恢复
aof 文件开头是 rdb 的格式, 先加载 rdb 内容再加载剩余的 aof<br><br>aof 文件开头不是 rdb 的格式,直接以 aof 格式加载整个文件
备份过程
通过bgrwriteaof完成,不同的是当开启混合持久化后,<br>1 子进程会把内存中的数据以RDB的方式写入aof中,<br>2 把重写缓冲区中的增量命令以AOF方式写入到文件<br>3 将含有RDB个数和AOF格数的AOF数据覆盖旧的AOF文件
0 条评论
下一页