Redis知识图谱
2022-04-14 10:56:49 77 举报
AI智能生成
Redis是一个开源的,内存中的数据结构存储系统,可以用作数据库、缓存和消息中间件。它支持多种数据结构,如字符串、哈希表、列表、集合和有序集合。Redis具有高性能、高可用性和持久化特性,广泛应用于各种场景,如缓存热点数据、分布式锁、计数器等。此外,Redis还支持事务、发布订阅、Lua脚本等功能,使其更加灵活和强大。总之,Redis知识图谱涵盖了Redis的基本概念、数据结构、应用场景和高级功能等方面的内容,对于学习和掌握Redis非常有帮助。
作者其他创作
大纲/内容
1.redis采用异步方式复制数据到slave节点,不过从redis2.8起,slave node会周期性的确认自己每次复制的数据量
2.一个master node是可以配置多个slave node的
3.slave node 也可以连接到其他的slave node
4.slave node做复制的时候,是不会阻塞master node的正常工作的
5.slave node做复制时,也不会阻塞对自己的查询操作,他会用旧的数据集提供服务,但是复制完成的时候,需要做删除数据集,加载新数据集,这个时候就会暂停对外服务了。
6.slave node 主要用来进行横向扩容,做读写分离,扩容的slave node可以提高的吞吐量
主从核心机制
Redis主从架构
集群监控,负责监控redis master和slave进程是否正常工作
消息通知,如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员
故障转移,如果master node挂掉了,会自动转移到slave node上
配置中心,如果故障转移发生了,通知client客户端新的master
主要功能
1.故障转移时,判断一个master node是宕机了,需要大部分的哨兵都同意才行,涉及到了分布式选举的问题。
2.即使部分哨兵节点挂掉了,哨兵集群还是能正常工作的,因为如果一个作为高可用机制重要的组成部分的故障转移系统本身是单点的,就很坑爹。
分布式
1.哨兵至少需要3个实例,来保证自己的健壮性。
2.哨兵+redis主从部署架构,是不会保证数据零丢失的,只能保证redis集群的高可用性
3.对于哨兵+redis主从这种复杂的部署结构,尽量在测试环境和生产环境中,都进行充足的测试和演练。
核心知识
因为master->slave的复制是异步的,所以可能有部分数据是没复制到slave,master就宕机了,此时这部分数据就丢失了。
异步复制
脑裂
数据丢失
min-slaves-to-write 1min-slaves-max-lag 10要求至少有1个slave,数据复制和同步得延迟不能超过10秒如果说一旦所有的slave,数据复制和同步都超过了10秒,那么这个时候,master就不会再接收任何请求了上面两个配置可以减少异步复制和脑裂导致得数据丢失
1.减少异步复制的数据丢失有了min-slaves-max-lag这个配置,就可以确保说,一旦slave复制数据和ack延时太长,就认为可能master宕机后损失的数据太多了,那么就拒绝写请求,这样可以把master宕机时,由于部分数据未同步到slave导致的数据丢失降低到最低的可控范围内
2.减少脑裂的数据丢失如果一个master出现了脑裂,跟其他slave丢了连接,那么上面两个配置可以确保,如果不能继续给指定数量的slave发送数据,而且slave超过10秒没有给自己ack消息,那么就直接拒绝客户端的写请求,这样脑裂后旧的master就不会接受client的新数据,那么就避免了数据丢失。上面配置确保了,如果跟任何一个slave丢了连接,在10秒后,发现没有slave给自己ack,那么就拒绝新的写请求。因此在脑裂场景下,最多就丢失了10秒数据。
解决方案
odown是客观宕机,如果quorum数量的哨兵都觉得一个master宕机了,那么就是客观宕机。sdown到odown转换条件很简单,如果一个哨兵在指定时间内,收到了quorum指定数量的其他哨兵也认为那个master是sdown了,那么就认为是odown了,客观认为master宕机。
sdown和odown两种失败状态转换机制
哨兵集群的自动发现机制
如果一个master被认为odown了,而且大部分哨兵都允许了主备切换,那么某个哨兵就会执行主备切换操作,此时首先选举一个slave来,会考虑slave的一些信息。1.跟master断开连接的市场2.slave优先级3.复制到offset4.run id
如果一个slave跟master断开连接已经超过了down-after-milliseconds的10倍,外加master的宕机时长,那么slave就会被认为不适合选举为masterdown-after-milliseconds * 10 + milliseconds_since_master_is_in_sdown_state
slave->master选举算法
底层原理
瓶颈
redis 哨兵模式
redis是会在数据达到一定程度之后,超过了一个最大的限度之后,就会将数据进行一定的清理,从内存中清理掉一些数据
redis默认情况下就是使用LRU策略,因为内存是有限的
介绍
对于64 bit的机器,如果maxmemory设置为0, 那么就默认不限制内存的使用,知道耗尽机器中所有内存为止
maxmemory-policy 可以设置内存达到最大先之后,采取什么策略来处理
缓存清理设置
2.allkey-lru: 就是我们常说的LRU算法,移除掉最近最少使用的那些keys对应的数据
3.volatile-lru: 就是采用LRU算法,但是仅针对那些设置了指定存活时间ttl的key才会清理掉
4.allkeys-random: 随机选择一些key来删除
5.volatile-random:随机选择一些设置了ttl的keyL来删除掉
6.volatile-ttl: 移除掉部分keys,选择那些ttl时间比较短的keys
清理策略
Redis回收算法
1.用作灾难恢复,数据恢复,保证高可用
2.解决缓存雪崩的问题。
3.通过备份数据快速恢复,支撑企业级业务。
Redis持久化意义
1.rdb会生成多个数据文件,每个数据文件代表了某一个时刻中redis的数据,这种多个数据文件的方式,每个文件都代表了某一个时刻的完整数据快照,非常适合做冷备。
2.rdb对redis对外提供读写服务,影响非常小,可以让redis保持高性能,因为redis主进程只需要fork一个子进程,让子进程执行磁盘IO操作来进行对RDB持久化即可。
3.相对于AOF持久化机制来说,直接基于RDB数据文件来重启和恢复redis进程,更加快速。
优点
1.如果想要在redis故障时,尽可能少的丢失数据,那么RDB没有AOF好,一般来说,RDB数据快照文件,都是每隔5分钟,或者更长时间生成一次,这个时候就得接受一旦redis进程宕机,那么会丢失最近5分钟的数据,这个问题,就是rdb更大的缺点,就是不合适做第一优先的恢复方案,如果你依赖RDB做第一优先恢复方案,会导致数据丢失的比较多。
2.RDB每次在fork子进程来执行RDB快照数据文件生成的时候,如果数据文件特别大,可能会导致对客户提供的服务暂停数毫秒,或者数秒。一般不要让RDB的间隔时间太长,否则每次生成的RDB文件太大,对redis本身的性能可能也会有影响。
缺点
配置
1.redis根据配置尝试自己生成一个rdb快照文件。
2.fork一个子进程出来
3.子进程尝试将数据dump到临时的rdb快照文件中
4.完成rdb快照文件生成之后,就替换之前旧的快照文件dump.rdb,每次生成一个新的快照,就会覆盖之前的老快照,dump.rdb只有一个
工作流程
通过redis-cli shutdown这种方式去停掉redis,其实是一种安全退出的模式,redis在退出的时候,会将内存中数据立即生成一个完整的rdb快照。
用kill -9 粗暴杀死redis进程,模拟redis异常退出,导致内存数据丢失的场景,这次就发现,redis进程被杀掉,数据没有进dump文件,几条最新的数据丢失了。
模拟实验
RDB
1,AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次sync操作,最多丢失1秒中的数据,每隔1秒,就执行一次sync操作,保证os cache中的数据写入磁盘,redis进程挂了,最多丢掉1秒中数据。
2.AOF日志文件中以Apend-only模式写入,所以没有任何磁盘寻址的开销,写入的性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修复。
3.AOF日志文件即使过大的时候,也会出现后台重写操作,也不会影响客户端的读写,因为在rewrite log的时候,会对其中的指令进行压缩,创建出一份需要恢复数据数据的最小日志来。再创建新日志文件的时候,老的日志还是照常写入。当新的merge日志文件ready的时候,再交换老日志文件即可。
4.AOF日志文件的命令通过非常可读的方式记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清除了所有的数据,只要这个时候后台rewrite还没有发生,那么立刻拷贝AOF文件,将最后一条flushall命令给删除,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据。
1.对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大。
2.AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒同步一次日志文件,当然,每秒一次同步,性能还是很高的,如果你要保证一条数据都不丢,也是可以的,AOF的同步设置每写入一条数据,同步一次,那样redis QPS大降
3.做数据恢复的时候,会比较慢,还有做冷备,定期备份,不太方便,可能要自己手写复杂的脚本去做,做冷备不合适。
1.AOF持久化,默认是关闭的,默认是打开RDB持久化,appendonly yes,可以打开AOF持久化机制,在生产环境里面,一般来说AOF都是要打开的,除非你说随便丢个几分钟的数据也无所谓,打开AOF机制后,redis每次收到一条写命令,就会写入日志文件中,当然是先写入os cache的,然后每隔一定时间再同步一下。
2.即使AOF和RDB都开启了,redis重启的时候,也是优先通过AOF进行数据恢复的,因为AOF数据比较完整。
always: 每次写入一条数据,立即将这个数据对应的写日志同步到磁盘中去,性能非常差,吞吐量很低,确保说redis里的数据一条都不丢。
mysql->内存策略,大量磁盘,OPS到多少,1k~2k,QPS每秒钟的请求数量redis->内存,磁盘持久化,OPQ到多少,单机,一般来说,上万QPS没问题
everysec:每秒将os cache中的数据同步到磁盘,这个最常用,生产环境一般都这么配置,性能很高,QPS还是可以上万的
no: 仅仅redis负责将数据写入os cache就撒手不管了,然后后面os自己会不时有自己的策略将数据写入磁盘,不可控了。
3.可以配置AOF的同步策略,有三种策略可以选择,一种是每次写入一条数据就执行一次同步,一种是每隔一秒执行一次同步,一种是不主动执行同步。
1.kill -9 杀掉redis进程,重新启动redis进程,发现数据被恢复回来了,从AOF文件中恢复回来的。在appendonly.aof中,可以看到刚写的日志,他们其实就是先写入os cache的,然后1秒以后才同步到磁盘中,才是安全的,不然光是在os cache中,机器只要重启,就什么也没有了。
2.redis进程启动的时候,直接就会从appendonly.aof中加载所有的日志,把内存中数据恢复回来。
redis中数据其实是有限的,很多数据很可能会自动过期,可能会被用户删除,可能会被redis用缓存清除算法清除掉。redis中所有数据会不断淘汰掉旧的,就一部分常用的数据会被自动保留在redis内存中。所以可能很多之前的已经被清理掉的数据,对应的写日志还停留在AOF中,AOF日志文件就一个,会不断的膨胀,到很大很大。所以AOF会自动在后台每隔一定时间做rewrite操作,比如日志里已经存放了针对100w数据的写日志了,redis内存就只剩下10w;基于内存中当前的10万数据构成一套最新的日志到AOF中;覆盖之前的老日志,确保AOF日志文件不会过大,保持和redis内存数据量一致。
在redis中,可以配置rewrite的策略auto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb比如说上一次AOF rewrite操作,是128mb,然后就会接着128mb继续写aof的日志,如果发现增长的比例,超过了之前的100%, 256mb,就可能去触发一次rewrite,但是此时还是要和min-size, 64mb去做比较, 256mb>64mb,才会触发rewrite
AOF rewrite
1.redis fork一个子进程
2.子进程基于当前内存中的数据,构建日志,开始往一个新的临时的AOF文件中写入日志
3.redis主进程,接收到client新的写操作以后,在内存中写入日志,同时新的日志也继续写入旧的AOF文件
4.子进程写完新的日志文件后,redis主进程将内存中的新日志再次追加到新的AOF文件中
5.用新的日志文件替换掉旧的日志文件
AOF
1.RDB也可以做冷备,生成多个文件,每个文件都代表了某一个时刻的完整数据快照,AOF也可以做冷备,只有一个文件,但是你可以每隔一段时间,去copy一份这个文件出来
2.RDB每次写,都是直接写redis内存,只是在一定的时候,才会将数据写入磁盘中,AOF每次都是要写文件的,虽然可以快速写入os cache中,但是还是有一定的时间开销,速度比RDB慢一些。
3.AOF存放指令日志,做数据恢复时,其实是要回访和执行所有的指令日志,来恢复出来内存中所有的数据的,RDP就是一份数据文件,恢复的时候,直接加载到内存中即可。
区别
2.如果RDB在执行snapshotting,此时用户执行BGREWRITEAOF命令,那么等RDB快照生成后,才会执行AOF rewirte
3.同时有RDB snapshot文件和AOF日志文件,那么redis重启的时候,会优先使用AOF进行数据恢复,因为其中的日志会更完整。
同时工作
RDB VS AOF
Redis持久化的两种方式
自动将数据进行分片,每个master上放一部分数据
提供内置的高可用支持,部分master不可用时,还是可以继续工作的。
Cluster
每个redis要开放两个端口号,比如一个6379,一个加10000的端口号,比如16379
16379端口号是用来进行节点间通信的,也就是cluster bus的东西,集群总线,cluster bus的通信,用来进行故障检测,配置更新,故障转移授权。Cluster bus用了另外一种二进制的协议,主要用于节点间进行高效的数据交换,占用更少的网络宽带和处理时间。
Cluster端口
redis cluster有固定的16384个hash slot, 对每个key计算CRC16值,然后后对16384取模,可以获取key对应的hash slotredis cluster中每个master都会持有部分的slot,比如3个master,那么可能每个master都持有5000个hash slot
hash slot算法
和集中式不同,不是将集群元数据(节点信息,故障,等等)集中存储在某个节点上,而是互相之间不断通信,保持整个集群所有节点的数据是完整的。
集中式,好处在于元数据的更新和读取,时效性非常好,一旦元数据出现了变更,立即就更新到集中式的存储中,其他节点读取的时候立即就可以感知到,不好在于,所有的元数据的更新压力全部集中在一个地方,可能会导致元数据的存储有压力gossip的好处在于,元数据的更新比较分散,不是集中在一个地方,更新请求会陆陆续续的,打到所有的节点去更新,有一定的延时,降低了压力,缺点,元数据更新有延时,可能导致集群的一些操作会由一些滞后。
节点间采取gossip协议进行通信
每个节点都有一个专门用于节点间通信的端口,就是自己提供服务的端口号+10000,比如7001,那么用于节点通信的就是17001端口
每个节点每隔一段时间都会往其他几个节点发送ping消息,同时其他几个节点收到ping之后返回pong
故障信息,节点的增加和移除,hash slot信息,等等
10000端口
基础通信原理
gossip协议
ping消息深入
节点间内部通信机制
核心原理
Redis Cluster
Redis
0 条评论
回复 删除
下一页