1.redis分布式结构
1.1结构的缺点
使用分布式集群时,任何进程,软件,服务器,都有故障的可能,集群越庞大,出现故障的可能性就越高.
1.2解决思路
对于每个节点来讲,实现数据的增删查改,重新定义规划集群结构,使得其中某一些节点宕机故障不可用时,数据仍然保证一个有效的整体使用.
什么叫做高可用: 集群节点故障宕机(down),要想不影响集群的使用,需要实现高可用结构,高可用的思路就是顶替,顶替的前提就是数据的备份
只要涉及到数据的高可用,必定基础是复制备份,实现方式就是转移替换;
2.REDIS实现主从复制
2.1redis的主从介绍
redis是支持主从复制的,把正常提供读写的功能的节点叫做master,把备份数据的节点,master宕机之后顶替的节点叫做slave.redis支持一主多从的复制,支持多级主从的复制.
- 一主多从
- 多级主从
虽然redis支持多级主从,主从结构越复杂,造成同步数据时效率越缓慢,根据企业经验,最多一级主从,一主6从,在多就影响使用效率
2.2实现redis的主从结构
使用redis搭建一个简单地一主二从结构。
- 准备三个独立的redis进程。
- 登录到其中的节点
- 127.0.0.1:6379>info replication
最终发现,当前3个节点默认启动,都认为自己是一个主从中的主。可以在配置文件中,修改从节点身份。
- 127.0.0.1:6380>slaveof masterIp masterPort
要人为定义 6379 6380 6381中哪个是从节点 6379主 6380 6381从。
slaveof 允许我们修改临时内存配置,将一个节点看成是他人节点的从节点。
127.0.0.1:6380> slaveof 192.168.184.130 6379
这个命令叫做从节点挂接主节点。
127.0.0.1:6381> slaveof 192.168.184.130 6379
2.4主从测试
- 同步数据
6379写入数据,6380 6381查看是否同步
6379>set name haha
6380/6381>keys *
- 在从节点写入数据
redis默认配置,对于slave从节点是只读配置,不允许写数据,在多级主从时可以关闭只读使得从节点作为第二级的主节点也可以写入数据.只读是常用配置
- 是否主从具备顶替的能力
将6379宕机,观察6380和6381的role角色是否发生变化.
6380:没有发生角色变动还是slave
结论:redis的主从能够实现数据的复制备份,对于高可用的功能,仅仅提供的就是数据备份,不能实现主节点宕机,从节点顶替的能力.
redis提供了命令,我们可以手动实现故障转义。
- 人为的从剩余的两个从节点选择一个为新的主节点(6381)
- slaveof no one #先让这个节点成为主节点角色
- 将另一个从节点重新挂接
- slaveof 新masterip 新masterport
- 宕机的主节点回复
- slaveof 新masterip 新masterport
人为维护这个关系肯定是不效率的。所以redis提供了一个sentinel哨兵机制。
3.哨兵(sentinel)集群
3.1介绍
redis中存在一个高可用结构的重要进程,sentinel哨兵,可以实现监听主从控制主从,完成主从复制基础之上的故障替换转移,主节点宕机,从节点顶替.哨兵也是redis-server进程,比较特殊,不处理数据增删查改,只负责监听主从
3.2运行原理
- 结构
在主从结构之上,需要引入哨兵行程集群
3.3启动哨兵进程
- 编写配置文件
模板文件sentinel.conf
自定义一个哨兵进程启动的配置文件。
port:哨兵运行端口
daemonize:后台运行
logfile:日志文件名字
dir:日志文件所在位置(如果不存在必须提前创建)
protected-mode no:保护模式
sentinel monitor first-ms 0.0.0.0 6379 1
sentinel monitor:关键字,表示配置哨兵监听
first-ms:自定义名字,代表一个主从结构
0.0.0.0 6379:主节点的ip地址和端口号
1:表示最少的哨兵进程个数(主观下限票数)
一个哨兵集群可以通过sentinel monitor监听多个主从
- 通过加载配置文件运行哨兵
#redis-sentinel my-sentinel01.conf
- 哨兵执行逻辑
- 哨兵启动会连接主节点
- 调用info replication 获取到主从集群的所有从节点信息
- 开启每秒钟的心跳检测(rpc远程通信协议),判断节点是否存活
- 通过投票判断节点是否真的死了。
- 从节点宕机,哨兵进程只会做记录 down
- 主节点宕机,哨兵开始发起投票选举,在多个从节点中选择其中一个顶替成为新的主节点,其他从节点哨兵重新挂接到新的主节点
- 顶替投票需要过半机制.
- 如果3个哨兵进程,2个以上选择同一个从节点,这个从节点才能顶替原有主节点提供功能
- 不过半的投票结果是作废的,将会隔一段时间重新投票
- 通过观察日志文件,查看详细信息
tail -f /home/software/redis-6.2.1/logs/sentinel.log
tail:查看尾部
-f:动态查看
- 宕机一个从节点 登录进去shutdown 也可以直接查看pid kill
redis-cli -p 6380 shutdown
+sdown 添加一个事件,事件名字sdown,记录6380宕机
- 这时如果将6380恢复
redis-server 6380/redis.conf
添加事件 reboot重启 记录6380重启
将sdown事件 删除记录
- 在将主节点6379宕机
redis-cli shutdown
添加一个宕机事件,记录6379宕机
发起集群主节点宕机投票事件,目前总票数一票。
当前哨兵发起投票 vote,当前哨兵选择6380成为新的主节点
由于没有其他哨兵,最终结果一定是6380是新主
将主节点6379替换成6380,并且将6379 6381转化为6380的从节点
但是79是宕机状态,无法直接转化,所以记录宕机,等待79恢复后执行挂接
6379原始状态是master 但是哨兵强行将其转化为从,挂接到新的6380主
- 如果想要运行一个集群哨兵监听结构
可以执行脚本
start-sentinel.sh 三个哨兵监听一主二从的结构
stop-sentinel.sh 停止这结构。
4.哨兵代码客户端
客户端在主从高可用结构中不能直接连接主节点实现读写操作,必须通过连接哨兵集群获取主从的主节点信息拿到连接资源从而操作高可用集群.
/* 主节点宕机后,客户端代码不发生任何变动直接能操作新的主节点 */ @Test public void test07(){ //连接哨兵集群 哨兵是个集群,使用可连接的第一个哨兵获取信息 Set<String> sentinels=new HashSet<>(); sentinels.add("10.9.118.11:26379"); sentinels.add("10.9.118.11:26380"); sentinels.add("10.9.118.11:26381"); //通过信息获取一个哨兵连接池 JedisSentinelPool pool=new JedisSentinelPool("mymaster",sentinels); //从连接池获取的资源就是当前master连接jedis System.out.println("当前master是:"+pool.getCurrentHostMaster()); Jedis jedis = pool.getResource();//master jedis.set("name","王老师"); System.out.println(jedis.get("name")); } |
5.哨兵实现分布式
5.1哨兵的分布式结构
如果哨兵管理监听的是一个主从,只能实现一个数据分片的高可用,没有分布式结构,如果想要哨兵实现分布式结构的所有数据分片高可用.
5.2客户端代码难以实现分布式计算
一致性hash很难解决对于这个结构的分布式计算逻辑.
初始化为了实现分布式一致性hash
获取到了3个主节点ip:port 计算一致性hash
一旦某一个分片中的从节点顶替完成,这个分片ip:port发生了变化
原有映射到主节点的key值们,未必同样会映射到新的主节点,造成了数据单调性破坏
解决思路:
计算一致性hash时,不在使用某个节点的ip:port作为信息,使用一个主从结构整体代码,mymaster1 mymaster2 mymaster3
高可用分布式哨兵集群中,一致性hash算法有缺点
5.3KEY迁移
如果分片计算方法是一致性hash,不能实现key值的自由迁移.
原因:分片计算方法,将key和分片做强耦合绑定.
目前市面上,哨兵集群依然被使用,在redis-cluster出现之前,为了使集群成为高可用和分布式的结构,redis-cluster出现之后,哨兵结构只被使用为高可用.如果需要结构既有高可用又有分布式,需要学习最终结构redis-cluster;
单机结构:测试
高可用哨兵集群:做高可靠性维护,不能支持高并发
redis-cluster:既有高可用,又有高并发分布式。
三个节点分布式集群:纯粹的测试结构,没人这么用