昨天回顾到redis的过时策略今天继续node
要搞清这个问题能够从这个四个方面来弄mysql
一、首先要知道redis高并发跟整个系统的高并发之间的关系redis
要作高并发的话,不可避免的要把底层的缓存搞得很OK
其实mysql也能够高并发,经过一系列复杂的分库分表,订单系统,
事务要求的,QPS到几万,比较高了。要是作一些电商得商品详情页
,真正得超高并发(虽然我没经历过,可是也要见识下,作好准备)其实一秒钟几百万,光redis也是不够得,可是redis是整个大型得缓存架构中支撑高并发得重要环节。
复制代码
二、redis不能支撑高并发是由于什么?算法
哈哈就是由于单机啊,俗话说双拳难敌四手
复制代码
三、假如redis要是支撑超过10万+得并发,应该怎么搞sql
除去特殊状况,能够作一个主从架构得读写分离,先假设写得操做少大部分是读操做
看图
复制代码
怎么实现呢能够了解下 redis得replication 主从复制功能
复制代码
上边说到了 redis replication这个东西缓存
借用一下图,比较清楚,最基本得就是复制安全
(1)redis采用异步方式复制数据到slave节点,不过redis 2.8开始,slave node会周期性地确认本身每次复制的数据量
(2)一个master node是能够配置多个slave node的
(3)slave node也能够链接其余的slave node
(4)slave node作复制的时候,是不会block master node的正常工做的
(5)slave node在作复制的时候,也不会block对本身的查询操做,它会用旧的数据集来提供服务; 可是复制完成的时候,须要删除旧数据集,加载新数据集,这个时候就会暂停对外服务了
(6)slave node主要用来进行横向扩容,作读写分离,扩容的slave node能够提升读的吞吐量
slave,高可用性,有很大的关系
复制代码
若是采用了主从架构,那么建议必须开启master node的持久化!
不建议用slave node做为master node的数据热备,由于那样的话,若是你关掉master的持久化,可能在master宕机重启的时候数据是空的,而后可能一通过复制,salve node数据也丢了
master -> RDB和AOF都关闭了 -> 所有在内存中
master宕机,重启,是没有本地数据能够恢复的,而后就会直接认为本身IDE数据是空的
master就会将空的数据集同步到slave上去,全部slave的数据所有清空
100%的数据丢失
master节点,必需要使用持久化机制
第二个,master的各类备份方案,要不要作,万一说本地的全部文件丢失了; 从备份中挑选一份rdb去恢复master; 这样才能确保master启动的时候,是有数据的
复制代码
可是 这个时候仍是有问题得,好比:网络
即便采用了后续讲解的高可用机制,slave node能够自动接管master
node,可是也可能sentinal尚未检测到master failure,master node就自动重启了,仍是可能致使上面的全部slave node数据清空故障
复制代码
当启动一个slave node得时候,他会发送一个PSYNC命令给master node,
若是这是一个slave node 从新链接 master node,这个时候master node仅仅会复制给slave部分缺乏得数据,若是是第一次就触发一次full resynchronization(复制全部)
开始full resynchronization得时候,master会启动一个后台线程,开始生成一份RDB快照文件,同时还会将从客户端收到得全部写命令缓存在内存中。RDB文件完过后,slave就会收到这个文件,
slave会先把他给保存到本地得磁盘中,而后再从磁盘加载到内存中。
slave node若是跟master node有网络故障,断开了链接,会自动重连
假如master发现有多个slave都来从新链接,那么那个生成得RDB文件谁来链接就给谁一份。
复制代码
从redis 2.8开始,就支持主从复制得断点续传。
master node内存中有一个backlog,master 和 slave都会保存一个replica offset,海有一个master id。
offset就是保存在backlog中得。若是master和slave网络链接断掉了,slave会让master从上次得 replica offset开始继续复制。
固然若是没有找到,就是从头再来了
复制代码
master在内存中直接建立rdb,而后给slave,本身不会保存在本地磁盘中了
因此这个时候 repl-diskless-sync-delay 这个配置就重要了,好不容易生成一个rdb,为啥很少等会看看slave还有没有再来链接得了
复制代码
slave 不会过时key(只读哪有资格过时key)。若是master过时了key,或者经过LRU淘汰了一个key,这个时候就会模拟一条del命令发送给slave。
复制代码
这节再研究下这个复制怎么搞定的架构
一、slave node启动,仅仅保存master node 的信息,包括master
node的host和ip,可是复制流程还没开始了,
问题来了 master host和ip是从哪里来的(redis.conf里面的slaveof配置的)
二、slave node内部有个定时任务,每秒检查是否有新的master node
要链接和复制,若是发现,就跟master node创建socket网链接
三、slave node发送ping命令给master node
四、口令认证,若是master设置了requirepass,那么salve node必须发送masterauth的口令过去
进行认证
五、master node第一次执行全量复制,将全部数据发给slave node
六、master node后续持续 将没有在rdb内的数据,异步复制给slave node
复制代码
#####二、数据同步相关的核心机制并发
指的就是第一次slave链接msater的时候,执行的全量复制,那个过程里面你的一些细节的机制
(1)master和slave都会维护一个offset
master会在自身不断累加offset,slave也会在自身不断累加offset
slave每秒都会上报本身的offset给master,同时master也会保存每一个slave的offset
这个也不是说就是用在全量复制的,主要master和slave都要知道本身数据的offset,才能互相知道数据不一致的状态
二、backlog,master node有一个backlog,默认的大小是1MB,master node
给slave node复制数据的时候,也会将数据在backlog中同步写一份,
backlog主要用来作全量复制时中断后的增量复制。
三、master run id,info server,能够看到master run id,为何要这个呢?
若是根据host+ip定位maser node这样不靠谱(为何不靠谱 看下边图)。
复制代码
固然假如你就想重启一下redis没有想到要同步数据,也有办法的可使用redis-cli debug reload命令
四、psync,从节点使用psync从master node 进行复制,psync runid offset
master node会根据自身的状况返回响应信息,多是FULLRESYNC
runid offset触发全量复制,多是CONTINUE触发增量复制
复制代码
一、master执行bgsave,在本地生成一份rdb快照
二、master node将rdb快照文件发送给salve node,若是rdb复制超过60秒(repl-timeout)这个时候slave node就认为复制
失败了,若是你的网速不给力最好仍是调节一下这个参数
三、若是你的机器是千兆网卡,通常一秒传100MB,6G文件,轻松超过60秒.
四、master node 生成rdb的时候,他会将全部新的写命令存在缓存中(我一边生
rdb一边来数据,我岂不是永远写不完了),而后salve node保存rdb之后再把新数据发给他
五、client-output-buffer-limit slave 256MB 60MB 60 这个参数意思是:
若是在复制期间,内存缓冲区持续消耗超过64MB,或者一次性超过256MB,那么中止复制,复制失败
六、slave node收到rdb之后,会将之前的数据清除掉,而后从新加载rdb(这个时候有客户来访怎么办,把之前旧数据给他)
七、若是slave node开启了AOF,这个时候会当即执行BGREWRITEAOF,重写AOF
这个全量复制总的来讲:rdb生成、rdb经过网络拷贝、slave旧
数据的清理、slave aof rewrite,很耗费时间的,
若是复制在4G-6G之间,极可能要消耗一分半到2分钟
复制代码
一、若是全量复制的时候,突然断掉了,salve从新连接master的时候,就会触发增量
二、master直接从本身的backlog中获取部分丢失的数据,发给slave node,默认backlog就是1MB
三、master就是根据slave发送的psync中的offset来从backlog获取数据的
复制代码
主从节点都会相互发送heartbeat信息
master默认每隔10秒发送一次heartbeat,slave node每隔一秒发送一个heartbeat
复制代码
master每次接受写命令的时候先将数据写进去,而后异步发给slave node
复制代码
嗯...高可用就是你的服务能够整年无休一直提供服务(服务不挂就OK)
问题来了redis怎么作到高可用呢(悄悄说下可使用哨兵模式,这个名词是否是很高大上) 下边开始研究下哨兵吧
sentinal,中文叫哨兵
哨兵呢是redis集群架构中一个很是重要的组件,主要功能有如下几点
一、集群监控,负责监控master 和slave是否在正常工做
二、消息通知,若是某个redis实例有故障了,哨兵负责发送消息通知管理员
三、故障转移,若是master node挂了,会自动选一个slave node 顶上去
四、配置中心,若是故障转移发生了,通知各个客户端新的master地址
复制代码
固然了哨兵做为监督的,若是监督的挂了怎么办,因此哨兵也须要集群
一、故障转移的时候,判断一个master node是宕机了,须要大部分哨兵赞成才能够,因此就有了分布式的
选举(感受跟一个小国家同样,要换带头人、要选举)
二、即便一个哨兵不行了,还有别的哨兵能干活,因此配置个哨兵集群多重要(总不能点背到几点,哨兵集体罢工吧)
目前redis采用的是sentinal2版本,是1的升级版。升级的目的就是为了让故障转移更健壮,和简单
复制代码
一、哨兵至少须要3个,来保证本身健壮
二、其实呢哨兵+主从架构也不能保证数据零丢失,只能保证redis集群的高可用
三、用这种复杂架构,多测试吧。若是崩盘就尴尬了
复制代码
看我辩解
若是哨兵集群仅仅部署了个2个哨兵实例,quorum=1
+----+ +----+
| M1 |---------| R1 |
| S1 | | S2 |
+----+ +----+
Configuration: quorum = 1
master宕机,s1和s2中只要有1个哨兵认为master宕机就能够还行切换,同时s1和s2中会选举出一个哨兵来执行故障转移
同时这个时候,须要majority,也就是大多数哨兵都是运行的,
2个哨兵的majority就是2(2的majority=2,3的majority=2,5的majority=3,4的majority=2),2个哨兵都运行着,就能够容许执行故障转移
可是若是整个M1和S1运行的机器宕机了,那么哨兵只有1个了,
此时就没有majority来容许执行故障转移,虽然另一台机器还
有一个R1,可是故障转移不会执行
复制代码
+----+
| M1 |
| S1 |
+----+
|
+----+ | +----+
| R2 |----+----| R3 |
| S2 | | S3 |
+----+ +----+
Configuration: quorum = 2,majority
若是M1所在机器宕机了,那么三个哨兵还剩下2个,S2和S3能够一致认为master宕机,而后选举出一个来执行故障转移
同时3个哨兵的majority是2,因此还剩下的2个哨兵运行着,就能够容许执行故障转移
复制代码
主备切换的时候,可能会有数据丢失
一、异步复制的时候数据丢失,就是master再给slave异步发数据,忽然master挂掉了,那么master内的数据就没了
二、脑裂丢失数据:假如你的网很差master所在的机器网络不正常了,跟其余slave不能链接了,可是master还在运行。
这个事被哨兵发现了,哨兵从新选了一个master,(这个时候就有两个master,就是所谓的脑裂)虽然选了一个master但
是还没把这个事给客户端说,客户端不知道还认为之前的master能用继续向他写数据
这个时候master上线了,由于有了一个master了他就被当作slave挂载到新的master了
本身之前的数据就清空了。再重新的master复制数据
复制代码
一、解决脑裂:
能够看下 这两个配置
min-slaves-to-write 1
min-slaves-max-lag 10
要求至少有1个slave,数据复制和同步的延迟不能超过10秒
若是说一旦全部的slave,数据复制和同步的延迟都超过了10秒钟,那么
这个时候,master就不会再接收任何请求了,因此就算丢数据也就最多损失10秒
二、解决异步复制
有了min-slaves-max-lag这个配置,就能够确保说,一旦slave复制数据
和ack延时太长,就认为可能master宕机后损失的数据太多了,那么就拒
绝写请求,这样能够把master宕机时因为部分数据未同步到slave致使的数据丢失下降的可控范围内
复制代码
sdown 是主关宕机,就一个哨兵以为master宕机了,就是主观宕机。
odown是客观宕机,就是多个哨兵以为master宕机了
sdown达成条件就是,若是一个哨兵ping
master,超过了is-master-down-after-milliseconds指定的毫秒数就是主观宕机
从sdown切换到odown就是一个哨兵在指定的时间里,收到了quorum指定数
量的其余哨兵也认为那个master宕机了,就是客观宕机了
复制代码
哨兵之间是相互发现的,是经过redis的pub/sub系统实现的,每一个哨兵都
会往——sentinel_:hello这个channel里发一个消息,这个时候其余哨兵都
能够消费这个信息,并感知其余哨兵的存在
每隔两秒钟,每隔哨兵都会往本身监控的某个master+alaves对应的——sentinel_:hello channel里
发送一个消息,消息内容就是本身的host、ip和runid还有就是对master的监控配置
每一个哨兵也会去监听本身监控的每一个master+slaves对应的_sentinel_:hell channel,而后去感知到一样在监听这个master+slaves
的其余哨兵存在。每一个哨兵还会跟其余哨兵交换对master的监控配置,互相进行监控配置的同步
复制代码
哨兵会负责自动纠正slave的一些配置,假如slave若是成为了master的候选人,哨兵会确保slave在复制现有master的数据,若是slave链接到了一个错误的master上,好比故障转移以后,那么哨兵会确保他们链接到正确的master上
复制代码
若是一个master呗认为odown了,并且majority邵冰冰都容许了主备切换,
那么某个哨兵就会执行主备切换操做,此时首先要选举一个slave来
选举 的时候会考虑slave的一些信息好比
一、跟master断开链接的时长
二、slave的优先级
三、复制offset
四、run id
若是一个slave跟master断开 链接已经超过了down-after-milliseconds的10倍,外加master宕机的时
长,那么这个slave就不适合了(断开这么长时间你的数据还完整吗)
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
接下来会对slave进行排序
(1)按照slave优先级进行排序,slave priority越低,优先级就越高
(2)若是slave priority相同,那么看replica offset,哪一个slave复制了越多的数据,offset越靠后,优先级就越高
(3)若是上面两个条件都相同,那么选择一个run id比较小的那个slave
复制代码
每次一个哨兵要作主备切换,首先要quorum数量的哨兵认为odown,而后选举一个哨兵来作切换,
这个哨兵还得获得majority哨兵的受权,才能正式执行切换
若是quorum < majority,好比5个哨兵,majority就是3,quorum设置为2,那么3个哨兵受权就可执行切换
可是若是quorum >= majority,那么quorum数量的哨兵都要受权,好比5个哨兵,quorum是5,那么必须是5个哨兵都赞成受权,才能执行切换
复制代码
哨兵会对一套 redis master+slave进行监控,有相应的监控的配置
执行切换的那个哨兵,会从要切换到的新master(salve -> master) 那里获得一个configuration epoch
,这就是一个version号,每次切换的version号就要惟一的
若是第一个哨兵选举出的哨兵切换失败了,那么其余哨兵,会等待failover-timeout时间,
而后继续执行切换,此时会从新获取一个新的configuration epoch,最为新的version号
复制代码
哨兵切换完成后,会在本身本地更新生成最新的master配置,而后同步给其余的哨兵,
同步的方式就是pub/sub消息机制
这个时候以前的version号就很重要了,由于各类消息都是经过一个channel去发布和监听的,
因此一个哨兵完成一次新的切换后,新的master配置
是跟着新的version号的
其余哨兵都是根据版本号的大小来更新本身的master配置的
复制代码