1、shishenm?
通过持久化功能,redis保证即使在服务器重启的情况下也不会损失(或损失少量)数据。但是由于数据是存储在一台服务器上的,如果这台服务器出现硬盘故障等问题,也会导致数据丢失。为了避免单点故障,通常的做法是将数据库复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现故障,其他服务器依然可以提供服务。为此,redis提供了复制功能,可以实现当一台数据库中的数据更新后,自动将数据同步到其他数据库上。
主机数据更新后,根据配置和策略,自动同步到备机的Master/Slave机制。简单来说就是主机如果宕机,迅速将指针指向从机继续使用。Master以写为主,Slave以读为主。默认情况下,从数据库是只读的,如果直接修改从数据库的数据会出现错误。可以通过设置从数据库的配置文件中的slave-read-only为no以使从数据库可以写,但是因为对从数据库的任何改变都不会同步给任何其他数据库,并且一旦主数据库更新了对应的数据就会覆盖从数据库中的改动,所以通常情况下不应该设置从数据库可以写,以免导致易被忽略的潜在应用逻辑错误。
除了通过配置文件或命令行参数设置slaveof参数,还可以在运行时使用slaveof命令修改。如果该数据库已经是其他主数据库的从数据库了,slaveof命令会停止和原来数据库的同步转而和新数据库同步。此外对于从数据库还可以使用slaveof no one命令来使得当前数据库停止接收其他数据库的同步并转换成为主数据库。
2、作用:读写分离、容灾恢复
3、缺点:由于所有的写操作都是在master上操作,然后同步更新到slave上,所以这个过程有一定的延迟。当系统很繁忙的时候,延迟问题会更加严重,slave机器数量的增加也会使得这个问题更加严重。
4、常用三招
(1)、一主二仆:
(2)、薪火相传:去中心化减少主机负载,但是产生复制延时。中途变更转向:会清除之前的数据,重新建立拷贝最新的,以保证数据的完整一致有效性。
(3)、反客为主:主机宕机从机上位。Slaveof no one(从机上位的渠道),其他从机执行命令连接刚上位的主机。
5、常见问题
(1)、只有主机可以写数据(一主二仆)
(2)、主机宕机,从机原地待命;主机恢复,主从复制体系照旧(一主二仆)
(3)、从机宕机,需要重新连接,除非配置redis.conf文件(一主二仆)
(4)、中间机器的身份:从机(薪火相传)
(5)、主机恢复之后:与新建立的主从体系无关(反客为主)
6、复制原理(基于乐观复制):
当一个从数据库启动之后,会向主数据库发送sync命令。同时主数据接收到sync命令之后会开始在后台保存快照(rdb),并将快照期间接受到的命令缓存起来,当快照完成之后,redis
会将快照文件和所有缓存的命令发送给从数据库。从数据库收到之后,会载入快照文件同时执行收到的缓存命令。以上过程成为复制初始化。复制初始化完成之后,主数据每当收到写命令就会将命令同步给从数据库,从而保证主从数据库数据一致。
当主从数据库之间的连接断开重连之后,redis2.6以及之前的版本会重新进行复制初始化,即使从数据库可以仅有几条命令没有收到,主数据库也必须将数据库里所有数据重新传送给从数据库。这使得主从数据库断线重连后的数据恢复过程效率很低下,redis2.8的重要改进就是断线重连能够支持有条件的增量数据传输。
复制初始化阶段结束之后,主数据执行的任何会导致数据变化的命令都会异步地传送给从数据库,这一过程为复制同步阶段。复制同步阶段会贯穿整个主从同步过程的始终,直到主从关系终止为止。
7、从数据库的持久化
为了提高性能,可以通过复制功能建立一个或者多个从数据库,并在从数据库中开启持久化,同时在主数据中禁用持久化。当从数据库崩溃的时候主数据会自动地将数据同步过来,所以无需担心数据会丢失。
然而当数据库崩溃时,手工通过从数据库数据恢复主数据库的数据时,必须严格按照以下两歩执行:
(1)在从数据库中使用slaveof no one命令将从数据库提升为主数据库继续提高服务。
(2)启动之前崩溃的主数据,然后使用slaveof命令将其设置成新的主数据库的从数据库,即可将数据同步回来。
手工维护从数据库或者主数据库的重启以及数据恢复都相对于比较麻烦,好在redis提供了一种自动化方案哨兵来实现这一个过程。
8、增量复制
增量复制基于以下三点实现:
(1)从数据库会存储主数据库的运行ID。每个redis实例均会拥有一个唯一的运行ID,每当实例重启后就会生成一个新的运行ID。
(2)在复制同步阶段,主数据库每将一个命令传送给从数据库时,都会同时把该命令存放在一个积压队列中,并记录下当前积压队列中存放的命令的偏移量范围。
(3)同时从数据库接收到主数据库传送过来的命令之后,会记录下该命令的偏移量。
2.8版本之前,当主从连接准备就绪后,从数据库会发送一条sync命令来告诉主数据库可以开始把所有数据同步过来了,而redis2.8版本之后,不在发送sync命令,取而代之的是发送psync命令,格式为“psync 主数据库的运行ID 断开前最新的命令偏移量”。主数据库收到psync命令后,会执行以下判断来决定是否可以进行增量复制
(1)首先主数据库会判断从数据库传过来的运行ID是否和自己的ID相同。这一步骤的意义在于确保从数据库之前确实是和自己进行同步的。
(2)然后从数据库最后同步成功的命令的偏移量是否在积压队列中,如果在则可以进行增量复制,并将积压队列中相应的命令发送给从数据库。如果此次重连不满足增量复制的条件,主数据库会进行一次全部同步。
积压队列本质上就是一个固定长度的循环队列,默认情况下积压队列的大小为1mb,可以通过配置修改大小。积压队列越大,则允许主从数据库断线的时间就越长。因为积压队列存储的是命令本身,所以估算积压队列的大小只需要估算主从数据库断线的时间中主数据库执行的命令大小即可。
与积压队列相关的另外一个配置是repl-backlog-ttl,即当所有从数据库与主数据库断开之后,经过多久时间释放积压队列的内存空间。默认时间是1小时。
9、哨兵模式(简单来说就是反客为主的自动版)redis2.8
也就是说有个monitor在监控,主机宕机,根据投票数自动将从机转成主机
10、作用
(1)监控主数据库和从数据库是否正常运行。
(2)主数据库出现故障时自动的将从数据库转换为主数据库。
11、实现原理
一个哨兵进程启动时会读取配置文件的内容找出需要监控的主数据库,一个哨兵节点可以同时监控多个redis注从系统,同时多个哨兵节点也可以监控一个redis主从系统,从而形成网状结构。
哨兵启动后,会与要监控的主数据库建立两条连接,这两条连接与普通的redis客户端相同。
其中一条连接用来订阅主数据库的_sentinel_:hello频道以获取其他同样监控该数据库的哨兵节点的信息,另外哨兵也需要定期向主数据库发送info等命令获取主数据库本身的信息。
和主数据库建立连接之后,哨兵会定时执行下面三个操作(贯穿哨兵进程的整个生命周期):
(2)每过10秒向主数据库发送info命令
(2)每过2秒哨兵回向主数据库和从数据库的_sentinel_:hello发送自己的信息
(3)每过1秒哨兵会向主数据库从数据库和其他哨兵节点发送ping命令
当超过指定的时间如果ping的数据库或者节点,仍没有进行回复,则哨兵任务其主观下线。如果这个节点是主数据库,则哨兵会进一步判断是否需要对其进行故障恢复:哨兵会发送SENTINEL is-master-down-by-addr命令询问其他节点是否也认为该主数据库主观下线,如果达到指定数量,哨兵会认为其客观下线,并选举领头哨兵节点对主从系统进行故障恢复。
选举领头哨兵:
(1)发现主数据库客观下线的哨兵节点(A)向每个哨兵节点发送命令,要求对方选举自己成为领头哨兵。
(2)如果目标哨兵节点没有选举其他人,则同意将A设置为领头哨兵
(3)如果A发现有超过半数且超过quorum参数值的哨兵节点同意自己成为领头哨兵,则A成功成为领头哨兵
(4)当有多个哨兵节点同时参选领头哨兵,则会出现没有任何节点当选的可能,此时每个参选节点等待一个随机事件重新发起参选请求,进行下一轮的选举,直到选举成功。
选举从数据库充当新的主数据库:
(1)所以在线的从数据库中,选择优先级最高的从数据库。优先级可以通过slave-priority配置
(2)如果有多个优先级相同,则复制的命令偏移量越大越有优先级
(3)如果以上条件都一样,则选择运行ID较小的从数据库