前言
redis高并发:主从架构,一主多从,通常来讲,不少项目其实就足够了,单主用来写入数据,单机几万QPS,多从用来查询数据,多个从实例能够提供每秒10万的QPS。node
redis高并发的同时,还须要容纳大量的数据:一主多从,每一个实例都容纳了完整的数据,好比redis主就10G的内存量,其实你就最对只能容纳10g的数据量。若是你的缓存要容纳的数据量很大,达到了几十g,甚至几百g,或者是几t,那你就须要redis集群,并且用redis集群以后,能够提供可能每秒几十万的读写并发。小编这里整理了一份详细的Redis思惟导图,须要的朋友能够关注公众号:麒麟改bug。 面试
redis高可用:若是你作主从架构部署,其实就是加上哨兵就能够了,就能够实现,任何一个实例宕机,自动会进行主备切换。redis
redis 实现高并发主要依靠主从架构,一主多从.算法
对于性能来讲,单主用来写入数据,单机几万QPS,多从用来查询数据,多个从实例能够提供每秒 10w 的 QPS。缓存
若是想要在实现高并发的同时,容纳大量的数据,那么就须要 redis 集群。服务器
使用 redis cluster 模式,能够提供每秒几十万的读写并发。网络
redis 高可用,若是是作主从架构部署,那么加上哨兵就能够了,就能够实现,任何一个实例宕机,能够进行主备切换。架构
因此就有了几个问题?并发
-
什么是主从架构,主从如何备份?负载均衡
-
什么是redis cluster模式?
-
什么是哨兵集群?
redis 主从架构
主从(master-slave)架构,一主多从,主负责写,而且将数据复制到其它的 slave 节点,从节点负责读。全部的读请求所有走从节点。这样也能够很轻松实现水平扩容,支撑读高并发。
Redis虽然读取写入的速度都特别快,可是也会产生读压力特别大的状况,因此为了缓解读的压力,因此进行读写分类,并对读进行扩展。
优势:
一、解决数据备份问题
二、作到读写分离,提升服务器性能
缺点:
一、每一个客户端链接redis实例的时候都是指定了ip和端口号的,若是所链接的redis实例由于故障下线了,而主从模式也没有提供必定的手段通知客户端另外可链接的客户端地址,于是须要手动更改客户端配置从新链接
二、主从模式下,若是主节点因为故障下线了,那么从节点由于没有主节点而同步中断,于是须要人工进行故障转移工做
三、没法实现动态扩容
主从架构就涉及到一个数据从主节点同步到从节点的问题。涉及redis replication问题
redis replication 的核心机制
当启动一个 slave node 的时候,它会发送一个 PSYNC 命令给 master node,若是这是第一次链接master node 那么会触发一次 full resynchronization 全量复制.全量复制的时候,master 会启动一个后台线程,开始生成一份 RDB 快照文件,同时还会将从客户端新收到的全部写命令缓存在内存中。最后将生成的RDB文件发送给slave,slave会先写入本地磁盘,而后再从本地磁盘加载到内存中,接着 master 会将内存中缓存的写命令发送到 slave,slave 也会同步这些数据。
若是是链接以后 master node 仅会复制给 slave 部分缺乏的数据。master 若是发现有多个slave node都来从新链接,仅仅会启动一个rdb save操做,用一份数据服务全部slave node。
注:redis2.8 开始,就支持主从复制的断点续传,若是主从复制过程当中,断掉了,那么能够接着上次复制的地方,继续复制下去,而不是从头开始复制一份。 master node 会在内存中维护一个 backlog,master 和 slave 都会保存一个 replica offset 还有一个 master run id,offset 就是保存在 backlog 中的。若是 master 和 slave 网络链接断掉了,slave 会让 master 从上次 replica offset 开始继续复制,若是没有找到对应的 offset,那么就会执行一次 resynchronization。
redis保证数据同步机制
master和slave都会维护一个offset
master会在自身不断累加offset,slave也会在自身不断累加offset slave每秒都会上报本身的offset给master,同时master也会保存每一个slave的offset,检测offset来保证数据的一致性
backlog
master node有一个backlog,默认是1MB大小 master node给slave node复制数据时,也会将数据在backlog中同步写一份 backlog主要是用来作全量复制中断候的增量复制的
master run id
若是根据host+ip定位master node,是不靠谱的,若是master node重启或者数据出现了变化,那么slave node应该根据不一样的run id区分,run id不一样就作全量复制 若是须要不更改run id重启redis,可使用redis-cli debug reload命令
psync
从节点使用psync从master node进行复制,psync runid offset。master node会根据自身的状况返回响应信息,多是FULLRESYNC runid offset触发全量复制,多是CONTINUE触发增量复制
redis cluster 模式
redis 服务节点中任何两个节点之间都是相互连通的。客户端能够与任何一个节点相链接,而后就能够访问集群中的任何一个节点。对其进行存取和其余操做。
通常集群建议搭建三主三从架构,三主提供服务,三从提供备份功能。
每个节点都存有这个集群全部主节点以及从节点的信息。
Redis集群数据分片
在redis的每个节点上,都有这么两个东西,一个是插槽(slot)能够理解为是一个能够存储两个数值的一个变量这个变量的取值范围是:0-16383。还有一个就是cluster我我的把这个cluster理解为是一个集群管理的插件。当咱们的存取的key到达的时候,redis会根据crc16的算法得出一个结果,而后把结果对 16384 求余数,这样每一个 key 都会对应一个编号在 0-16383 之间的哈希槽,经过这个值,去找到对应的插槽所对应的节点,而后直接自动跳转到这个对应的节点上进行存取操做。
投票过程是集群中全部master参与,若是半数以上master节点与master节点通讯超时(cluster-node-timeout),认为当前master节点挂掉.
何时整个集群不可用(cluster_state:fail)?
若是集群任意master挂掉,且当前master没有slave.集群进入fail状态,也能够理解成集群的slot映射[0-16383]不完整时进入fail状态.
一个Redis实例具有了“数据存储”和“路由重定向”,彻底去中心化的设计。这带来的好处是部署很是简单,直接部署Redis就行,不像Codis有那么多的组件和依赖。但带来的问题是很难对业务进行无痛的升级,若是哪天Redis集群出了什么严重的Bug,就只能回滚整个Redis集群。
优势:
一、有效的解决了redis在分布式方面的需求
二、遇到单机内存,并发和流量瓶颈等问题时,可采用Cluster方案达到负载均衡的目的
三、可实现动态扩容
四、P2P模式,无中心化
五、经过Gossip协议同步节点信息
六、自动故障转移、Slot迁移中数据可用
缺点:
一、架构比较新,最佳实践较少
二、为了性能提高,客户端须要缓存路由表信息
三、节点发现、reshard操做不够自动化
redis 哨兵
哨兵的功能:
- 集群监控:负责监控 redis master 和 slave 进程是否正常工做。
- 消息通知:若是某个 redis 实例有故障,那么哨兵负责发送消息做为报警通知给管理员。
- 故障转移:若是 master node 挂掉了,会自动转移到 slave node 上。
- 配置中心:若是故障转移发生了,通知 client 客户端新的 master 地址。
哨兵用于实现 redis 集群的高可用,自己也是分布式的,做为一个哨兵集群去运行,互相协同工做。
故障转移时,判断一个 master node 是否宕机了,须要大部分的哨兵都赞成才行,涉及到了分布式选举的问题。
即便部分哨兵节点挂掉了,哨兵集群仍是能正常工做的。
哨兵的核心知识
- 哨兵至少须要 3 个实例,来保证本身的健壮性。
- 哨兵 + redis 主从的部署架构,是不保证数据零丢失的,只能保证 redis 集群的高可用性。
- 对于哨兵 + redis 主从这种复杂的部署架构,尽可能在测试环境和生产环境,都进行充足的测试和演练。
数据丢失问题的解决方案?
进行以下配置: min-slaves-to-write 1 min-slaves-max-lag 10
要求至少有 1 个 slave,数据复制和同步的延迟不能超过 10 秒。若是说一旦全部的 slave,数据复制和同步的延迟都超过了 10 秒钟,那么这个时候,master 就不会再接收任何请求了。
减小异步复制数据的丢失 有了 min-slaves-max-lag 这个配置,就能够确保说,一旦 slave 复制数据和 ack 延时太长,就认为可能 master 宕机后损失的数据太多了,那么就拒绝写请求,这样能够把 master 宕机时因为部分数据未同步到 slave 致使的数据丢失下降的可控范围内。 减小脑裂的数据丢失 若是一个 master 出现了脑裂,跟其余 slave 丢了链接,那么上面两个配置能够确保说,若是不能继续给指定数量的 slave 发送数据,并且 slave 超过 10 秒没有给本身 ack 消息,那么就直接拒绝客户端的写请求。
怎么保证redis是高并发以及高可用的?
1.sdown 和 odown 转换机制
sdown 是主观宕机,就一个哨兵若是本身以为一个 master 宕机了,那么就是主观宕机。odown 是客观宕机,若是 quorum 数量的哨兵都以为一个 master 宕机了,那么就是客观宕机。
sdown 达成的条件很简单,若是一个哨兵 ping 一个 master,超过了 is-master-down-after-milliseconds 指定的毫秒数以后,就主观认为 master 宕机了。sdown到odown转换的条件很简单,若是一个哨兵在指定时间内,收到了 quorum 数量的 其它哨兵也认为那个 master 是 sdown 的,那么就认为是 odown 了,客观认为master宕机。
2.哨兵集群的自动发现机制
哨兵互相之间的发现,是经过 redis 的 pub/sub 系统实现的,每一个哨兵都会往sentinel:hello这个 channel 里发送一个消息,这时候全部其余哨兵均可以消费到这个消息,并感知到其余的哨兵的存在。 每隔两秒钟,每一个哨兵都会往本身监控的某个 master+slaves 对应的sentinel:hello channel 里发送一个消息,内容是本身的 host、ip 和 runid 还有对这个 master 的监控配置。 每一个哨兵也会去监听本身监控的每一个 master+slaves 对应的sentinel:hello channel,而后去感知到一样在监听这个 master+slaves 的其余哨兵的存在。 每一个哨兵还会跟其余哨兵交换对 master 的监控配置,互相进行监控配置的同步。
3.slave 配置的自动纠正
哨兵会负责自动纠正 slave 的一些配置,好比 slave 若是要成为潜在的 master 候选人,哨兵会确保 slave 复制现有 master 的数据; 若是 slave 链接到了一个错误的 master 上,好比故障转移以后,那么哨兵会确保它们链接到正确的 master 上。
4.slave->master 选举算法
若是一个 master 被认为 odown 了,并且 majority 数量的哨兵都容许主备切换,那么某个哨兵就会执行主备切换操做,此时首先要选举一个 slave 来,会考虑 slave 的一些信息:
跟 master 断开链接的时长 0slave 优先级 复制 offset run id
若是一个 slave 跟 master 断开链接的时间已经超过了down-after-milliseconds的 10 倍,外加 master 宕机的时长,那么 slave 就被认为不适合选举为 master。
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
接下来会对 slave 进行排序:
按照 slave 优先级进行排序,slave priority 越低,优先级就越高。 若是 slave priority 相同,那么看 replica offset,哪一个 slave 复制了越多的数据,offset 越靠后,优先级就越高。 若是上面两个条件都相同,那么选择一个 run id 比较小的那个 slave。
5.quorum 和 majority
每次一个哨兵要作主备切换,首先须要 quorum 数量的哨兵认为 odown,而后选举出一个哨兵来作切换,这个哨兵还得获得 majority 哨兵的受权,才能正式执行切换。 若是 quorum < majority,好比 5 个哨兵,majority 就是 3,quorum 设置为2,那么就 3 个哨兵受权就能够执行切换。 可是若是 quorum >= majority,那么必须 quorum 数量的哨兵都受权,好比 5 个哨兵,quorum 是 5,那么必须 5 个哨兵都赞成受权,才能执行切换。
6.configuration epoch
哨兵会对一套 redis master+slaves 进行监控,有相应的监控的配置。 执行切换的那个哨兵,会从要切换到的新 master(salve->master)那里获得一个 configuration epoch,这就是一个 version 号,每次切换的 version 号都必须是惟一的。 若是第一个选举出的哨兵切换失败了,那么其余哨兵,会等待 failover-timeout 时间,而后接替继续执行切换,此时会从新获取一个新的 configuration epoch,做为新的 version 号。
7.configuraiton 传播
哨兵完成切换以后,会在本身本地更新生成最新的 master 配置,而后同步给其余的哨兵,就是经过以前说的 pub/sub 消息机制。 这里以前的 version 号就很重要了,由于各类消息都是经过一个 channel 去发布和监听的,因此一个哨兵完成一次新的切换以后,新的 master 配置是跟着新的 version 号的。其余的哨兵都是根据版本号的大小来更新本身的 master 配置的。小编这边整理了一些Redis分布式锁的资料以及2020最新的Java核心面试资料集锦,关注公众号:麒麟改bug。
小编分享的内容到这里就结束了!