Redis-sentinel(哨兵)及集群案例

redis   docker   sentinel  

redis sentinel(哨兵) 管理多个 Redis 服务器

主要作用:

  • 监控: sentinel 会不断的检测主服务器与从服务器是否运作正常
  • 提醒: 当被监控的某个Redis服务出现问题,sentinel 可以通过API想管理员或者其他应用程序发送通知
  • 自动故障迁移: 当主服务器不能正常工作时,sentinel会开始一次自动故障迁移操作,将失效的主服务器下其中的一个从服务器升级为新的主服务器,其他的从服务器同时也更改刚升级的主服务器.当客户端连接时,会将新的主服务器地址返回,使得集群可以使用新主服务器代替失效的服务器

sentinel有两种启动方式

  • 对于redis-sentinel程序
  1. redis-sentinel /config/sentinel1.conf
  • 对于redis-server程序
  1. redis-server /config/sentinel1.conf

常用命令

  • 查看redis的主从信息和详情,偏移量等
    1. # 进入redis操作界面
    2. redis-cli
    3. # 查看redis详情
    4. info replication
  • 查看sentinel(哨兵)信息的一些操作
    1. # 利用redis-cli -p 指定哨兵端口 进入 sentinel 命令行
    2. redis-cli -p 26379
    3. # 相关指令 :
    4. info # 查看sentinel的状态
    5. sentinel masters # 获取sentinel中监控的所有master的节点
    6. sentinel master <哨兵名称> # 获取master-name节点redis的状态信息
    7. sentinel slaves # 获取master-name节点下所有的slaves的状态信息
    8. SENTINEL get-master-addr-by-name # 通过sentinel中的节点名获取其ip地址

配置

  • 在/etc/redis-sentinel.conf的文件中修改
  1. # 监控mymaster(可自定义)的主服务器,IP为127.0.0.1,端口6379,至少需要两个哨兵同意(这里的具体数量根据配置的哨兵数量定义[哨兵数量/2 + 1],一般哨兵配置为奇数,分布在不同服务器上)
  2. sentinel monitor mymaster 127.0.0.1 6379 2
  3. # 执行了哨兵认为mymaster主服务器断线所需要的毫秒数,在给定的时间内无返回或者返回错误,则被认为主观下线.主观下线不一定会自动故障迁移.需要多个sentinel(哨兵)一致认为主观下线后才会标记为客观下线,这时候会自动故障迁移.
  4. sentinel down-after-milliseconds mymaster 60000
  5. # 故障转移的超时时间,默认是180s
  6. sentinel failover-timeout mymaster 180000
  7. # 指定执行故障转移时,最多有1个服务器同时对新主服务器进行同步.可根据服务器配置决定,配置高的可以多个同时进行同步
  8. sentinel parallel-syncs mymaster 1

搭建简易的Redis1主3从加3sentinel 集群案例

容器名称 容器IP地址 映射端口(宿主机:容器) 服务运行模式(名称)
redis-master 172.10.0.2 6380:6379 Master(主)
redis-slave1 172.10.0.3 6381:6379 Slave(从1)
redis-slave2 172.10.0.4 6382:6379 Slave(从2)
redis-slave3 172.10.0.5 6383:6379 Slave(从3)
redis-sentinel1 172.10.0.11 26381:26379 Sentinel(哨兵1)
redis-sentinel2 172.10.0.12 26382:26379 Sentinel(哨兵2)
redis-sentinel3 172.10.0.13 26383:26379 Sentinel(哨兵3)
  1. # 同样在宿主机的 /usr/local/docker/redis/config 配置相应的配置文件
  2. # 创建运行3个Redis容器 1主3从
  3. docker run -itd --name redis-master --net ownnetwork -p 6380:6379 --ip 172.10.0.2 -v /usr/local/docker/redis/config:/config redis
  4. docker run -itd --name redis-slave1 --net ownnetwork -p 6381:6379 --ip 172.10.0.3 -v /usr/local/docker/redis/config:/config redis
  5. docker run -itd --name redis-slave2 --net ownnetwork -p 6382:6379 --ip 172.10.0.4 -v /usr/local/docker/redis/config:/config redis
  6. docker run -itd --name redis-slave3 --net ownnetwork -p 6383:6379 --ip 172.10.0.5 -v /usr/local/docker/redis/config:/config redis
  7. # 创建运行3个sentinel 3个哨兵
  8. docker run -itd --name redis-sentinel1 --net ownnetwork -p 26381:26379 --ip 172.10.0.11 -v /usr/local/docker/redis/config:/config redis
  9. docker run -itd --name redis-sentinel2 --net ownnetwork -p 26382:26379 --ip 172.10.0.12 -v /usr/local/docker/redis/config:/config redis
  10. docker run -itd --name redis-sentinel3 --net ownnetwork -p 26383:26379 --ip 172.10.0.13 -v /usr/local/docker/redis/config:/config redis
  11. # 进入对应的容器,启动 启动配置文件可使用对应/config
  12. # sentinel(哨兵)的配置文件会被自动接管,所以再重启后需要核对配置文件
  13. # 启动顺序 Redis 主 -> Redis 从 -> sentinel(哨兵)

利用轮询算法模拟客户端进访问,获取数据 直接看代码

  1. <?php
  2. /**
  3. * 简易轮询类
  4. * Class Round
  5. */
  6. class Round
  7. {
  8. static $lastIndex = 0; //指针计数
  9. /**
  10. * @param $list 需要轮询的数组
  11. * @return mixed
  12. */
  13. public function select($list)
  14. {
  15. $currentIndex = self::$lastIndex; //当前的index
  16. $value = $list[$currentIndex]; //获取对应数据
  17. if ($currentIndex + 1 > count($list) - 1) {
  18. //记录,如果指针+1 的数量大于 总数 - 1 则 指针重置
  19. self::$lastIndex = 0;
  20. } else {
  21. //否则++
  22. self::$lastIndex++;
  23. }
  24. return $value;
  25. }
  26. }
  27. //所有哨兵ip和端口 这里由于是通过本机测试,所以该ip能访问
  28. $sentinelConf = [
  29. ['ip' => '127.0.0.1', 'port' => 26381],
  30. ['ip' => '127.0.0.1', 'port' => 26382],
  31. ['ip' => '127.0.0.1', 'port' => 26383]
  32. ];
  33. //随机访问 获取一个哨兵的地址
  34. $sentinelInfo = $sentinelConf[array_rand($sentinelConf)];
  35. $redis = new Redis();
  36. $redis->connect($sentinelInfo['ip'], $sentinelInfo['port']);
  37. //获取哨兵返回的所有在线的从服务器信息
  38. $slavesInfo = $redis->rawCommand('SENTINEL', 'slaves', 'mymaster');
  39. $slaves = [];
  40. //进行组装
  41. foreach ($slavesInfo as $val) {
  42. $slaves[] = ['ip' => $val[3], 'port' => $val[5]];
  43. }
  44. //加载到缓存当中,可以记录这次访问的时间跟上次的访问时间
  45. //模拟客户端访问 1
  46. while (true) {
  47. //轮训
  48. $slave = (new Round())->select($slaves);
  49. try {
  50. $redis = new Redis();
  51. $redis->connect($slave['ip'], $slave['port']);
  52. var_dump($slave, $redis->get('dream'));
  53. } catch (\RedisException $e) {
  54. var_dump("出错了!", $e->getMessage());
  55. }
  56. sleep(3);
  57. }
  58. ////模拟客户端访问 2 使用swoole 自带定时器
  59. //swoole_timer_tick(600,function () use($slaves) {
  60. // //轮训
  61. // $slave=(new Round())->select($slaves);
  62. // try{
  63. // $redis=new Redis();
  64. // $redis->connect($slave['ip'],$slave['port']);
  65. // var_dump($slave,$redis->get('peter'));
  66. // }catch (\RedisException $e){
  67. // var_dump($e->getMessage());
  68. // }
  69. //
  70. //});

最后执行该文件,会看到,轮询redis从服务器的相关信息

  1. string(4) "five"
  2. array(2) {
  3. ["ip"]=>
  4. string(10) "172.10.0.5"
  5. ["port"]=>
  6. string(4) "6379"
  7. }
  8. string(4) "five"
  9. array(2) {
  10. ["ip"]=>
  11. string(10) "172.10.0.4"
  12. ["port"]=>
  13. string(4) "6379"
  14. }
  15. string(4) "five"
  16. array(2) {
  17. ["ip"]=>
  18. string(10) "172.10.0.3"
  19. ["port"]=>
  20. string(4) "6379"
  21. }
  22. string(4) "five"


评论 0

发表评论

Top