1.主从复制问题
1.手动故障转移(主节点宕机)
选择客户端,执行slaveof no one
其余slave 执行slaveof new master
通过脚本避免手动配置:监控master,出现问题,选择新mster,老的slave 选择新master(进行复制),迁移所有的客户端
2.写能力和存储能力有限
2.Redis Sentinel 基本架构
sentinel:实现上述脚本功能,首先一组redis sentinel 结点,想象成redis 进程,作用是对redis 故障判断,故障转移,通知客户端。
客户端从sentinel 获取redis 信息。(通过sentinel 知道谁是master).
具体流程:
1)多个sentinel 发现并确认master 有问题
2)选举出一个sentinal 作为领导
3)选择一个slave 作为master
4)通知其余slave 成为新的master 的slave
5)通知客户端主从变化
6)等到老的master复活成为新master的slave
1.安装配置
1.配置开启主从结点
2.配置开启sentinel 监控主节点(sentinel 是特殊的redis)
3.实际应该是多机器
redis 主结点
port 7000
daemonize yes
pidfile /var/run/redis-7000.pid
logfile "7000.log"
datafile "7000.rdb"
dir "opt/soft/redis/data"
redis 从节点
port 7001
daemonize yes
pidfile /var/run/redis-7001.pid
logfile "7001.log"
datafile "7001.rdb"
dir "opt/soft/redis/data"
**salveof 127.0.0.1 7000**
sentinel
port {port}
dir "/opt/soft/redis/data/"
logfile "{port}.log"
#监控主节点名字 IP 端口号 配置多少个sentinel发现mster故障才故障进行转移
sentinel monitor mymaster 127.0.0.1 7000 2
#30ms ping 不同,代表master出现故障
sentinel down-after-milliseconds mymaster 30000
#发生故障时候每次只复制一个
sentinel parallel-syncs mymaster 1
#故障转移时间
sentinel failover-timeout mymaster 180000
redis-cli -p 7000 info replication #查看主从复制关系
#启动 通过上述命令可以知道主节点的从节点
redis-sentinel redis-sentinel-23679.conf
#通过客户端连接sentinel
redis-cli 127.0.0.1 26387
redis-cli -p 26387 info sentinel #查看sentinel 信息
2.客户端
1.实现服务端高可用和客户端的高可用。
1).获取所有sentinel 结点集合 msterName
2).get-master-addr-by-name-mastername
3).返回master 结点
通过发布订阅模式,客户端订阅sentinel 某一个频道,从而得到新的master.
故客户端接入流程:
1.sentinel 地址集合
2.mastername
3.不是代理模式
2.通过Jedis实现sentinel 的连接
//内部连接还是mster
JedisSentinelPool sentinelPool = new JedisSentinelPool(mastername,sentinelSet,poolConfig,timeout);
Jedis jedis = null;
try{
jedis = redisSentinelPool.getResourse();
}catch(Exception e){
logger.error(e.getMessage(),e);
}finally{
if(jedis !=null)
jedis.close();//归还动作
}
3.故障转移实验
public class RedisSentinelFailoverTest{
private static Logger logger = LoggerFactory.getLogger(RedisSentinelFailoverTest.calss);
public static void main(String[] args){
String mastername = "myMaster";
set<String> sentinels = new HashSet();
sentinels.add("127.0.0.1:26389");
...
JedisSentinelPool jedisSentinelpool = new JedisSentinelPool(mastername,sentinels);
int counter=0;
while(true){
count++;
Jedis jedis =null;
try{
jedis = jedisSentinelPool.getResource();
int index = new Random().nextInt(10000);
String key = "k-"+index;
String value = "V-"+index;
jedis.set(key,value);
if(count%100==0)
logger.info("{}value is {}",key,jedis.get(key);
TimeUnit.MILLISSECONDS.sleep(10);
}catch(Exception e){
logger.error(e.getMessage(),e);
}finally{
if(jedis !=null)
jedis.close();//归还动作
}
}
通过日志会发现,master 宕机以后 客户端报错后会继续连接。
服务端日志分析:
从结点日志
tail -200 7001.log
1.用户希望该slave 成为主节点
2.该slave 配置重写
3.7002 请求复制新的mster
4.做bgsave …
sentinel 日志 #完成故障转移
1.mster 下线
2.尝试做领导者
3.其他sentinel 投票给他
4.选择合适slave ,给其发送slaveof no one
5.让7002slave 复制新master
6.旧的master 的监控
3三个定时任务
对于主节点,从节点,其余sentinel 节点的监控。
1.每10s 每个sentinel 对master 和 slave 执行info
发现slave节点
确认主从节点
2.每2s 每个sentinel 通过master 节点的channenl 交换信息(pub/sub)(每个sentinel 发布一些信息,然后其他sentinel 会接受这些信息(对master ,slave节点的判断))
-master节点上channel: sentinel:hello 频道交互。
-交互对节点的”看法“ 和自身信息
3.每1s每个sentinel 对其他sentinel和redis 执行ping 操作
- 心跳检测
4.主观下线和客观下线
配置一:sentinel monitor
sentinel monitor mymaster 127.0.0.1 6379 2
配置二:sentinel down-after-milliseconds
sentinel down-after-millseconds mymaster 30000#对slave同样
主观下线:每个sentinel 节点对redis 节点失败的偏见
客观下线:所有的sentinel 节点对redis节点失败”达成共识“
sentinel is-master-down-by-addr (节点数/2+1)
5.领导人选举
原因:只有一个sentinel 节点完成故障转移
选举:通过sentinel is-master-down by addr 命令都希望成为领导者(节点故障判定,和领导人选举)
- 每个主观下线的sentinel 节点对其他sentinel 节点发送命令,要求将它设置成领导者
- 收到命令的sentinel 节点如果没有同意通过其他sentinel 节点发送的命令,那么将同意该请求,否则拒绝
- 如果该sentinel节点发现自己的票数已经超过半数/quorum,成为领导者
6.故障转移
1.从slave 节点中选择一个合适的节点作为新的mster
- 选择slave-priority (slave节点优先级)最高的slave 节点,存在返回,不存在则继续。
- 选择扶植偏移量最大的slave节点,存在返回,不存在继续
- 选择runId 最小的节点
2.对上面的slave节点执行slaveof no one 让其成为master
3.对剩余节点发送命令,让他们成为新的master 节点的slave 节点,复制规则和parallel-syncs 参数相关(同时发送多分rdb 文件)
4.更新原来mster节点配置为slave,并保持关注,恢复后令它复制新mster.