分布式系统的单点问题
1.可用性问题,如果这个机器挂了,意味着服务就中断了
2.性能/支持的并发量也是比较有限的
引入分布式系统,主要也就是未来解决上述的单点问题
在分布式系统中,使用多个服务器进行部署redis服务,从而构成一个redis集群。此时就可以让这个集群给整个分布式系统提供更稳定/更高效的数据存储功能
Redis的部署方式
在分布式系统中,使用多个服务器部署redis的方式
1.主从模式
2.主从+哨兵模式
3.集群模式
1.主从模式
在redis的若干个节点中,有的是"主"节点,有的是"从"节点。
从节点的数据随主节点的变化而变化,从节点的数据与主节点保持一致。
在redis主从模式中,从节点上的数据,不允许修改,只允许读取
主从模式,主要是针对"读操作"进行并发量&可用性的提高,而写操作还是依赖与主节点,并且主节点不能搞多个
如果从节点挂了并没有什么影响,如果主节点挂了,还是有一定影响的
配置Redis主从结构
配置Redis主从结构,首先需要启动多个redis服务
使用一台服务器配置多个redis服务,需要运行多个redis-server进程
本来redis默认的端口号是6379,运行多个redis进程就需要修改redis的端口号
如何执行redis-server的端口号?
1.可以在启动程序的时候,通过命令行来指定端口号,--port选项
2.也可以直接在配置文件中,来设定端口
此处搞一个主节点,两个从节点,采用修改配置文件的方式
首先使用cp命令复制两份配置文件

然后修改端口号port为6380,和6381,并且确认daemonize 为yes

使用redis-server ./slave1.conf (配置文件的路径)启动服务
当前这三个节点并没有构成主从结构,下面进行主从结构的配置

采用第一种方式,在redis配置文件的最下面加上

修改配置文件以后,需要重启服务才能生效
使用redis-server命令启动的服务,使用kill -9 进程 的方式关闭
使用service redis-server start这种方式启动,就必须使用service redis-server stop这个命令停止,使用kill会触发redis的保护进程


从节点只能读取数据,不能修改数据
使用info replication命令查看当前redis服务的主从结构


断开主从结构
在客户端执行 slaveof no one 就可以断开连接
原有的数据不会进行删除,但是后续如果主节点针对数据进行了修改,从节点就无法感受到了
与其他节点建立连接
slaveof host post 认其他节点为主节点
这里的slaveof都是临时性的,重新启动redis服务器还是会按照配置文件的主从结构
传输延迟
主节点与从节点间通过网络来传输(TCP)
TCP内部支持了nagle算法(默认开启的)针对小的tcp数据报,进行合并,减少了包的个数
开启了,就会增加tcp的传输延迟 节省了网络带宽
关闭了,就会减少tcp的传输延迟 增加了网络带宽
repl-disable-tcp-nodelay 这个选项可以用于主从通信过程中,关闭tcp的nagle算法~~
从节点更快速的和主节点进行同步
拓扑结构
一主一从结构
拓扑结构:若干个节点之间,按照啥样的方式来进行组织连接

如果写数据请求过多,主节点压力就会过大
可以通过关闭主节点AOF来降低主节点的压力
但是,这种方法一旦主节点挂了,不能让它自动重启(如果重启,主节点上的数据就会没了,主从复制,从节点上的数据也会跟着没了)
改进办法,主节点挂了之后,需要让主节点从从节点这里获取AOF的文件之后再重启
一主多从结构

随着从节点的增加,同一条数据就需要传输多次
树形主从结构

主节点就不需要那么高的网络带宽了
一旦数据进行了修改,同步的延迟是要比刚才更长的
主从复制原理

redis提供psync命令,完成数据同步的过程
psync不需要手动执行,redis服务器会在建立好主从同步关系之后,自动执行psync
从节点负责执行psync,从节点从主节点这边拉取数据
psync replicationid offset
replication id 是主节点启动的时候就会生成,从节点晋升成主节点的时候,也会生成(同一个节点重启后replication id也是不相同的)
从节点与主节点建立复制关系之后,就会从主节点这边获取replicationid
info replicationid获取当前的replicationid

replid就是replicationid
replid2一般用不上,从节点与主节点建立连接之后,从节点会记录主节点的replicationid,如果发生网络抖动,从节点与主节点断开连接,自己成为主节点,会生成自己的replicationid,但从节点会用replid2保存原来主节点replicationid,以便根据replid2重新回到原来主节点的怀抱
replicationid和offset共同描述了一个数据集合,如果两台机器,如果applicationid和offset都一样就可以认为这两台机器的redis数据也一样
offset偏移量
主节点和从节点都会维护偏移量(整数)
主节点的偏移量:主节点上对于收到的修改操作的命令,这些命令都会占用几个字节,主节点讲这些字节进行累加
从节点的偏移量:描述了数据同步的进度
从节点每秒会上报自身的复制偏移量给主节点
psync数据复制
psync这里可以进行全量复制也可以获取一部分数据
主要看offset的进度
offset写作-1,就是获取全量数据
offset写具体的正整数,则是从当前偏移量位置来进行获取
获取所有数据最稳妥,但是最为低效,如果从节点之前已经从主节点这里复制过一部分数据了,就只需要把新的之前没复制过的数据传过来即可,但是并不是从节点想复制部分就复制部分,主节点会自行判断方不方便给,如果不方便给,就只能进行全量复制

全量复制

1)从节点发送psync命令给主节点进行数据同步,由于是第一次进行复制,从节点没有主节点的运行ID和复制偏移量,所以发送psync ? -1.
2)主节点根据命令,解析出要进行全量复制,回复+FULLRESYNC响应
3)从节点接受主节点的运行信息进行保存
4)主节点执行bgsave进行RDB文件的持久化(rdb是二进制文件比较节省空间,不能使用已有的rdb文件,而是必须重新生成一下,已有的和当前最新的数据存在较大差异)
5)主节点发送RDB文件给从节点,从节点保存RDB数据到本地硬盘
6)主节点从生成RDB到接收完成期间执行的写命令, 写入缓冲区中,等从节点保存完RDB文件后,主节点再将缓冲区内的数据补发给从节点,补发的数据仍然按照rdb的二进制格式追加写到收到的rdb文件中,保持主从的一致性
7)从节点清空自身原有的旧数据
8)从节点加载RDB文件得到与主节点一致的数据
9)如果从节点加载RDB完成之后,并且开启了AOF的持久化功能,它会进行bgrewrite操作,得到最近的AOF文件
主节点进行全量复制的时候也支持"无硬盘模式"(diskless)
主节点生成的rdb二进制文件,不是直接保存到文件中了,而是直接进行网络传输(省去了一系列的读写硬盘的操作)
从节点之前是先把收到的rdb数据写入硬盘,然后再加载,现在可以省去这个过程,直接把收到的数据进行加载
即使引入了无硬盘模式,仍然整个操作是重量级的,比较耗时,网络传输是没法省的
部分复制
如果在全量复制的时候出现网络抖动,主节点这边最近修改的数据可能无法及时同步过来了,从节点也可能因为感受不到主节点自己成为主节点了。
网络抖动一般是暂时的,过一会就恢复,此时从节点就可以和主节点重新建立联系
当从节点和主节点重新建立连接之后,就需要进行数据的同步
psync带有具体的replid和offset的值
主节点就会根据psync的值进行判定,是全量复制还是部分复制

1)当主从节点之间出现网络中断的时,如果超过repl-timeout时间,主节点会认为从节点故障并中断复制连接。
2)主从连接中断期间主节点依然响应命令,但这些复制命令都因网络中断无法同步给从节点,所以暂时将这些命令滞留在复制积压缓冲区中。
3)当主从节点网络恢复后,从节点再次连上主节点。
4)从节点将之前保存的replicationid和复制偏移量作为psync的参数发送给主节点,请求进行部分复制。
5)主节点接到psync请求后,进行必要的验证,随后根据offset去复制积压缓冲区查找合适的数据,并响应+CONTINUE给从节点。
6)主节点将需要从节点同步的数据发给从节点,最终完成一致性。
info replication命令可以查看消息缓冲区的参数

消息缓冲区就是内存中的简单队列,会记录最近一段时间修改的数据,总量有限,随着时间的推移,就会把之前的旧数据逐渐删掉
对于从节点重连之后发送的psync命令,主节点会根据replicationid判断这个从节点以前是不是与自己相连,然后判断从节点发送的offset是否在消息缓冲区之内,如果在消息缓冲区之内,就进行部分复制,如果不在,就只能进行全量复制了。
实时复制
主从节点建立复制连接以后,主节点会将自己收到的修改操作,通过tcp长连接的方式,源源不断的传输给从节点,从节点就会根据这些请求来同时修改自身的数据,从而保证主从节点的数据一致性
这里的tcp长连接通过心跳包的方式来维护连接状态(应用层自己实现的心跳包机制,而不是TCP自带的)
1)主节点默认每隔10秒对从节点发送ping命令,从节点响应pong,(默认通信延迟超过repl-timeout)配置的值(默认60秒),则判定从节点下线,断开复制客户端的连接。
2)从节点默认每隔1秒向主节点发送replconfack{offset}命令,给主节点上报自身的复制偏移量