搭建Redis主从分离/集群/哨兵
主从分离
- 复制一份主,一份从
- 修改配置redis.windows.conf,linux修改redis.conf,主的端口,6379(默认),从的端口6372
- 启动主运行,redis-server,启动从
配置从服务器
- 启动主 ./redis-server redis.conf
- 启动主 ./redis-server salve.conf
- 在配置从
- replicaof 127.0.0.1 6379 # master的ip,port
- masterauth 123456 # master的密码
- replica-serve-stale-data no # 如果slave无法与master同步,设置成slave不可读,方便监控脚本发现问题
php代码
<?php
$redis = new \Redis();
//连接主redis
$redis->connect('127.0.0.1',6379);
//从主服务写数据
$redis->auth('123');
$master_key = [
'name'=>"测试",
'cate'=>"测试分类",
];
$redis->set('master_key',json_encode($master_key));
print_r($redis->get('master_key'));
//从服务器
$redis->connect('127.0.0.1',6371);
$redis->auth('123');
print_r($redis->get('master_key'));
此时主和从服务器打印出来的数据是一样
优点:
- master能自动将数据同步到slave,可以进行读写分离,分担master的读压力
- master、slave之间的同步是以非阻塞的方式进行的,同步期间,客户端仍然可以提交查询或更新请求
缺点:
- 不具备自动容错与恢复功能,master或slave的宕机都可能导致客户端请求失败,需要等待机器重启或手动切换客户端IP才能恢复
- master宕机,如果宕机前数据没有同步完,则切换IP后会存在数据不一致的问题
- 难以支持在线扩容,Redis的容量受限于单机配置
哨兵
-
主要功能:监控master、slave是否正常运行,当master出现故障时,能自动将一个slave转换为master(大哥挂了,选一个小弟上位),多个哨兵可以监控同一个Redis,哨兵之间也会自动监控
-
具体工作机制:定期(一般10s一次,当master被标记为主观下线时,改为1s一次)向master和slave发送INFO命令,定期向master和slave的sentinel:hello频道发送自己的信息,定期(1s一次)向master、slave和其他哨兵发送PING命令
-
sentinel monitor mymaster 127.0.0.1 6379 1 # mymaster定义一个master数据库的名称,后面是master的ip, port,1表示至少需要一个Sentinel进程同意才能将master判断为失效,如果不满足这个条件,则自动故障转移(failover)不会执行
-
sentinel auth-pass mymaster 123456 # master的密码
-
sentinel down-after-milliseconds mymaster 5000 # 5s未回复PING,则认为master主观下线,默认为30s
-
sentinel parallel-syncs mymaster 2 # 指定在执行故障转移时,最多可以有多少个slave实例在同步新的master实例,在slave实例较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长
-
sentinel failover-timeout mymaster 300000 # 如果在该时间(ms)内未能完成故障转移操作,则认为故障转移失败,生产环境需要根据数据量设置该值
启动 redis-server sentinel.conf --sentinel
,端口:6373
<?php
$redis = new \Redis();
//连接主redis
$redis->connect('127.0.0.1',6379);
//从主服务写数据
$redis->auth('123');
print_r($redis->info('replication'));
此时:6379:[role] => master
此时:6371:[role] => slave
此时:6372:[role] => slave (按照上面方式多增加一台从服务器)
- 查看端口进程 nestat -anp |grep 6379
- 此时Kill主服务器6379,此时从6372变为主服务器了
Array
(
[role] => master
[connected_slaves] => 1
[slave0] => ip=127.0.0.1,port=6371,state=online,offset=9038,lag=1
[master_failover_state] => no-failover
[master_replid] => 1890c1a2b71bb0fb48a7576f7a36d44c4205025d
[master_replid2] => f66ff82bd8eac44e449f5b5c565160a00205ffa3
[master_repl_offset] => 9038
[second_repl_offset] => 8620
[repl_backlog_active] => 1
[repl_backlog_size] => 1048576
[repl_backlog_first_byte_offset] => 1
[repl_backlog_histlen] => 9038
)
- 所有在线的slave中选择优先级最高的,优先级可以通过slave-priority配置
- 如果有多个最高优先级的slave,则选取复制偏移量最大(即复制越完整)的当选
- 如果以上条件都一样,选取id最小的slave
优点:
- 哨兵模式基于主从复制模式,所以主从复制模式有的优点,哨兵模式也有
- 哨兵模式下,master挂掉可以自动进行切换,系统可用性更高
缺点: - 同样也继承了主从模式难以在线扩容的缺点,Redis的容量受限于单机配置
- 需要额外的资源来启动sentinel进程,实现相对复杂一点,同时slave节点作为备份节点不提供服务
集群 Cluster模式
- 哨兵模式解决了主从复制不能自动故障转移,达不到高可用的问题,但还是存在难以在线扩容,Redis容量受限于单机配置的问题。Cluster模式实现了Redis的分布式存储,即每台节点存储不同的内容,来解决在线扩容的问题。
工作机制:Redis的每个节点上,都有一个插槽(slot),取值范围为0-16383 - 当我们存取key的时候,Redis会根据CRC16的算法得出一个结果,然后把结果对16384求余数,这样每个key都会对应一个编号在0-16383之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作
- 为了保证高可用,Cluster模式也引入主从复制模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点
- 当其它主节点ping一个主节点A时,如果半数以上的主节点与A通信超时,那么认为主节点A宕机了。如果主节点A和它的从节点都宕机了,那么该集群就无法再提供服务了
- Cluster模式集群节点最小配置6个节点(3主3从,因为需要半数以上),其中主节点提供读写操作,从节点作为备用节点,不提供请求,只作为故障转移使用。
- 端口7100,7200,7300,7400,7500,7600
- 6个实例组成一个3主节点3从节点的集群
- redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7100 127.0.0.1:7200 127.0.0.1:7300 127.0.0.1:7400 127.0.0.1:7500 127.0.0.1:7600 -a PTbWxknSFhj4fLhM
配置如下: - cluster-enabled yes #开启集群
- cluster-config-file #集群文件
查看集群:
cluster nodes
优点 - 可线性扩展到1000多个节点,节点可动态添加或删除
- 无中心架构,数据按照slot分布在多个节点。
- 可线性扩展到1000多个节点,节点可动态添加或删除
- 集群中的每个节点都是平等的关系,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。
- 能够实现自动故障转移,节点之间通过gossip协议交换状态信息,用投票机制完成slave到master的角色转换
缺点:
- 客户端实现复杂,驱动要求实现Smart Client,缓存slots mapping信息并及时更新,提高了开发难度。目前仅JedisCluster相对成熟,异常处理还不完善,比如常见的“max redirect exception
- 节点会因为某些原因发生阻塞(阻塞时间大于 cluster-node-timeout)被判断下线,这种failover是没有必要的
- 数据通过异步复制,不保证数据的强一致性
- slave充当“冷备”,不能缓解读压力
- 批量操作限制,目前只支持具有相同slot值的key执行批量操作,对mset、mget、sunion等操作支持不友好
- key事务操作支持有线,只支持多key在同一节点的事务操作,多key分布不同节点时无法使用事务功能
- 不支持多数据库空间,单机redis可以支持16个db,集群模式下只能使用一个,即db 0 Redis Cluster模式不建议使用pipeline和multi-keys操作,减少max redirect产生的场景。