redis主从同步与对象模型

过期删除策略

当对key设置了过期时间,redis会把key带上过期时间存储到一个过期字典中,过期字典存储在residDB结构中,当我们查询一个 key 时,Redis 首先检查该 key 是否存在于过期字典中,是,则判断系统时间小于查询key的过期时间,如果小于则正常读。
定时删除优缺点: *优点:*由事件处理器自动执行 key 的删除操作。可以保证过期 key 会被尽快删除,定时删除对内存是最友好的。 *缺点:*在过期 key 比较多,删除过期 key 占用相当一部分 CPU 时间,在内存不紧张但 CPU 时间紧张的情况下,将 CPU 时间用于删除和当前任务无关的过期键上,无疑会对服务器的响应时间和吞吐量造成影响。所以,定时删除策略对 CPU 不友好。
惰性删除策略 不主动删除过期键,每次从数据库访问 key 时,都检测 key 是否过期,如果过期则删除该 key。(1)惰性删除策略对 CPU 时间最友好。 (2)惰性删除策略对内存不友好。
定期删除策略 每隔一段时间「随机」从数据库中取出一定数量的 key 进行检查,并删除其中的过期key。*优点:*通过限制删除操作执行的时长和频率,来减少删除操作对 CPU 的影响,同时也能删除一部分过期的数据减少了过期键对空间的无效占用。 *缺点:*难以确定删除操作执行的时长和频率。如果执行的太频繁,定期删除策略变得和定时删除策略一样,对CPU不友好;如果执行的太少,那又和惰性删除一样了,过期 key 占用的内存不会及时得到释放。

Redis 过期删除策略

Redis 选择「惰性删除+定期删除」这两种策略配和使用。
edis 在访问或者修改 key 之前,都会调用 expireIfNeeded 函数对其进行检查,检查 key 是否过期:过期 删除key,没过期 返回正常的键值对给客户端;
默认每秒进行 10 次过期检查,从过期字典随机抽取20个key,检查是否过期,删除已过期的,如果本轮检查已过期占比大于25%,继续重复操作,小于25%,停止,等下一轮检查。同时为了避免循环过渡,默认定期删除循环流程时间不超过25ms。

淘汰策略

redis在运行中会用系统资源,如果不加以限制,会将当前系统空间都用到,当达到内存限定值,则出现淘汰策略。
数据库的V都有一个空转时长,LRU会记录上一次操作V的时间。
内存淘汰策略分为八种:
不进行数据淘汰的策略:no_eviction (Redis 3.0 之后默认使用的内存淘汰策略)_禁止淘汰
进行数据淘汰的策略:
(1)在设置了过期时间的数据中进行淘汰:volatile-random volatile-ttl volatile-lru(最长时间没有使用) (Redis3.0 之前,默认的内存淘汰策略) volatile-lfu(最少次数使用)(Redis 4.0 后新增的内存淘汰策略)
(2)在所有数据范围内进行淘汰:allkeys-random allkeys-lru allkeys-lfu (Redis 4.0 后新增的内存淘汰策略)

LRU算法

LRU 全称是 Least Recently Used 翻译为最近最少使用,Redis 实现的是一种近似 LRU 算法,实现方式是在 Redis 的对象结构体中添加一个额外的字段,用于记录此数据的最后一次访问时间。随机采样的方式来淘汰数据,它是随机取 5 个值淘汰最久没有使用的那个。
*优点:*不用为所有的数据维护一个大链表,节省了空间占用;不用在每次数据访问时都移动链表项,提升了缓存的性能;
*缺点:*无法解决缓存污染问题 如应用一次读取了大量的数据,而这些数据只会被读取这一次,那么这些数据会留存在 Redis 缓存中很长一段时间,造成缓存污染。

LFU算法

为了解决LRU算法的问题,LFU 全称是 Least Frequently Used 翻译为最近最不常用,LFU 算法会记录每个数据的访问次数。当一个数据被再次访问时,就会增加该数据的访问次数。这样就解决了偶尔被访问一次之后,数据留存在缓存中很长一段时间的问题,相比于 LRU 算法也更合理一些。

持久化

AOF

AOF 日志(Append Only File,文件追加方式):记录所有的操作命令,并以文本的形式追加到文件中。
AOF采用的是写后日志的方式,Redis先执行命令把数据写入内存,然后再记录日志到文件中。AOF日志记录的是操作命令协议,不是实际的数据,故障恢复时需要重放的方式恢复。
执行过程: redis执行完命令后将命令追加到server.aof_buf缓冲区 --> 通过write系统调用,将缓冲区数据写入aof文件,此时数据拷贝到了内核缓冲区,等待内核写入硬盘,内核决定了什么时候将数据写入到硬盘,redis提供了三种写回硬盘策略,分别为 always、everysec、no;
1三种策略就是在控制fsync() 函数的调用时机,always 是每次写入aof文件后,就执行fsync()函数;everysec会创建一个异步任务来执行fsync()函数;no 永远不执行fsync()函数.

aof_rewrite

aof 持久化策略会持久化所有修改命令;里面的很多命令其实可以合并或者删除;
aof rewrite 在 aof 的基础上,满足一定策略则 fork 子进程,根据当前内存状态,转换成一系列的 redis 命令,序列化成一个新的 aof 日志文件中,序列化完毕后再将操作期间发生的增量 aof日志追加到新的 aof 日志文件中,追加完毕后替换旧的 aof 日志文件;以此达到对 aof 日志瘦身的目的;
写时复制技术
进程 通过 页表 去操作内存,fork进程是克隆出跟自己一样的进程出来,fork为了其高效,fork复制了页表,指向同一块物理内存,linux写时复制,server去操作redis时候要修改页,此时页表是只读,当父进程或者子进程在向这个内存发起写操作时,就会触发缺页中断,缺页中断函数在物理内存会复制同样的页出来,子进程就指向新的页,此时子进程和父进程指向发生分离,将父子进程的内存读写权限设置为可读写。
子进程是怎么拥有主进程一样的数据副本具体过程:
触发重写机制后,主进程就会创建重写 AOF 的子进程,此时父子进程共享物理内存,重写子进程只会对这个内存进行只读,重写 AOF 子进程会读取数据库里的所有数据,并逐一把内存数据的键值对转换成一条命令,再将命令记录到重写日志(新的 AOF 文件)。

RDB

RDB采用的是内存快照的方式,它记录的是某一时刻的数据,而不是操作,所以采用RDB方法做故障恢复时只需要直接把RDB文件读入内存即可,实现快速恢复。
它通过 fork 主进程,在子进程中将内存当中的数据键值对按照存储方式持久化到 rdb 文件中;rdb 存储的是经过压缩的二进制数据;redis提供的两个命令save、bgsave来生成rdb文件,区别是save在主线程中操作,会阻塞主线程;bgsave会fork一个子线程进行操作。
redis执行的是全量快照的方式,通常设置5分钟记录一次,若服务器宕机,则会丢失五分钟的数据。在执行快照过程中数据是可以修改的,原理就是用到写时复制技术,如果主线程要修改共享数据的某一块数据,则就会发生写时复制,于是这块物理内存会被复制一份(副本),主线程会在副本中修改数据,同时bgsave会把原本的数据写入RDB文件。

混合持久化

rdb文件小加载快丢失多,aof文件大加载慢丢失少;混合持久化集合了两者的优点,混合持久化是在aof_rewrite的时候实际持久化的是rdb,等持久化后,持久化修改的数据以aof的形式附加到文件的尾部。混合持久化前半部分是rdb的全量数据,后半部分是aof格式的增量数据。这样做的好处:重启redis时,aof文件中由于前半部分是rdb的内容,这样加载的速度快,等加载完rdb后,再加载aof内容,这里的内容是redis后台子进程重写aof期间,主线程处理的命令,这样可以使得更少的数据丢失。

高可用

如果redis宕机,系统就是一个不可用的状态,则需要备用节点进行顶替,这就是高可用,通常秒级别的主从切换,才能称为高可用。

主从复制

redis采用主从复制,主从复制主要解决单点故障,保证一台故障,其他的服务器能够继续工作,主从复制采用长链接,主从异步复制的方式工作。
第一次主从连接分为三个过程,1.建立连接,协商同步,主节点发出runid,offset偏移量;2.执行bgsave命令,主节点传输rdb文件;3.发送新的写操作指令
第一次同步后,主从维持的tcp长链接如果中断,恢复网络后,在此期间发生数据需要同步,主从节点通过比较偏移量offset在环形缓冲区(repl_abcklog_buffer)中寻找差异数据,如果存在,则采用增量同步的方式,如果不在则采用全量同步的方式。
主从复制过期key处理方式:主节点中过期key,主节点会通过模拟del命令发送给从节点,从节点收到命令,进行删除key操作。

哨兵模式

原理:
客户端来连接集群时,会首先连接 sentinel(哨兵),通过 sentinel 来查询主节点的地址,然后再连接主节点进行数据交互。当主节点发生故障时,客户端会重新向 sentinel 索要主库地址,sentinel会将最新的主库地址告诉客户端。通过这样客户端无须重启即可自动完成节点切换。
判断故障:
哨兵会每隔 1 秒给所有主从节点发送 PING 命令,当主从节点收到 PING 命令后,会发送一个响应命令给哨兵,通过接收返回判断该节点是否下线,没在规定的时间响应,则标记为主观下线;为了确认主节点是否真的下线,它会向其他哨兵节点发送命令,半数以上收到已下线回复,则会认为主节点客观下线;主节点客观下线后,则进行故障转移,需要半数以上哨兵支持,选举领头哨兵后,开始执行对主节点故障转移:
从从节点中选举一个从节点作为新的主节点;
通知其他从节点复制连接新的主节点;
将新主节点的 IP 地址和信息,通过「发布者/订阅者机制」通知给客户端;
继续监视旧主节点,当这个旧主节点重新上线时,将它设置为新主节点的从节点;
哨兵模式缺陷:
redis 采用异步复制的方式,意味着当主节点挂掉时,从节点可能没有收到全部的同步消息,这部分未同步的消息将丢失。如果主从延迟特别大,那么丢失可能会特别多。

cluster集群

Redis cluster 将所有数据分为16384(2^14)个槽位,每个redis节点负责一部分槽位,cluster集群是一种去中心化的集群方式,当 redis cluster 的客户端来连接集群时,会得到一份集群的槽位配置信息。这样当客户端要查找某个 key 时,可以直接定位到目标节点。客户端为了定位key所在节点,通过 crc16(key) % (2 ^14) 缓存相关信息,这样才能准确快速定位到相应的节点,避免连接切换。
特征:去中心化;主节点对等;解决了数据扩容;客户端与服务端缓存槽位信息,以服务端为主,客户节点缓存为了避免连接切换;可人为数据迁移;
流程;选择集群任意一个节点;若数据不在该节点,回收到连接切换的命令继而连接目标节点;故障转移:集群接地那会互相发送消息,交换节点的状态信息;若主节点下线,将会被其他主节点标记下线;接着在该下线主节点的从节点中选择一个数据最新的从节点作为主节点;从节点继承下线主节点槽位信息,并广播该消息给集群中其他节点;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值