高可用Redis(九):Redis Sentinel

1.主从复制高可用的问题 主从复制高可用的作用 1.为master提供备份,当master宕机时,slave有完整的备份数据 2.对master实现分流,实现读写分离 但是主从架构有一个问题 1.如果master宕机,故障转移需要手动完成或者由别的工具来完成,从slave中选择一个slave做为新的master 写能力和存储能力受限 只能在一个节点是写入数据 所有数据只能保存在一个节点上 上图模拟了主从复制架构中一主两从情况下,master宕机,则slave从master同步数据也断开,此时client向master写入数据会失败,读写分离时读取数据正常,但不能更新数据 master出现故障之后,手动进行故障转移步骤 1.选择一个slave,执行slave no one命令使之成为一个master 2.对其余的slave执行slaveof new master命令,将这些slave指定为新的master的slave 3.client会对新的master进行写入数据,从slave中读取原来的数据 上面的操作过程需要手动完成,或者编写脚本,由脚本来执行这个过程,但是这个过程是有问题的: 怎么判断一个Redis节点是有问题的,怎么通知client对新master进行写入操作 怎么保证一个完整的事务实现过程 上面的过程就可以使用Redis Sentinel来实现 2.Redis Sentinel架构说明 Redis Sentinel的功能:对Redis节点进行监控,故障判断,故障转移,故障通知 对于Redis的主从架构,Redis Sentinel会运行几个sentinel进程 sentinel进程不操作数据,而是对Redis故障进行判断和转移 同时多个sentinel运行,即使一个sentinel进程运行异常,还有别的sentinel继续运行,可以保证对故障节点判断的准确性,同时保证Redis的高可用 对于redis-cli来说,Redis cli不会再记录Redis的IP和端口,而是从sentinel获取Redis信息,然后进行连接Redis节点,进行数据写入和读取操作 多个Redis Sentinel对所有的master和slave进行监控,会实时记录master和slave的地址信息 Redis Sentinel故障转移步骤: 1.当某个master发生故障,多个sentinel会监控到这个异常,这些sentinel会按照一定规则从多个slave中选中一个做为新的master,并通知别的slave从新的master中同步数据 2.当某个slave转换为新的master,sentinel会记录新的master的地址信息和slave的地址信息,通知Redis cli 3.Redis cli接收到新的master和slave的信息,就会向新的master写入数据,从slave中读取数据 4.等到原来的master重启之后,会变成新的master的slave,并从新的master同步数据 在上面的步骤里,sentinel实现了Redis的故障自动发现,自动转移和自动通知 说明:一套Redis sentinel集合可以通知master-name做为标识同时监控多套主从架构 3.Redis Sentinel安装配置 3.1 环境说明 实验在两台虚拟机上完成,IP地址分别为:192.168.81.100和192.168.81.101 在两台虚拟机上运行4个redis-server,其中 192.168.81.100的6379端口为master节点 192.168.81.100的6380端口为slave节点 192.168.81.101的6379端口和6380端口为slave节点 在192.168.81.101的26379,26380,26381端口开启三个sentinel进行监控 3.2 在192.168.81.100虚拟机上配置主从节点 [root@localhost ~]# cd /etc/ # 进入/etc目录 [root@localhost ~]# systemctl stop redis # 关闭系统中运行的redis [root@localhost etc]# cp redis.conf redis_6379.conf # 复制redis配置文件,以端口区分,方便后面进行配置 [root@localhost etc]# cp redis.conf redis_6380.conf # 复制redis配置文件,以端口区分,方便后面进行配置 [root@localhost etc]# vi redis_6379.conf # 编辑redis-server配置文件,修改下面几行 bind 0.0.0.0 # 修改bing选项,才能从系统外连接redis protected-mode yes # 开启保存模式 port 6379 # 指定redis运行的端口 daemonize yes # 以守护进程启动redis pidfile "/var/run/redis_6379.pid" # 指定redis运行时pid保存路径 logfile "/var/log/redis/redis_6379.log" # 指定redis运行时日志保存路径 dir /var/lib/redis_6379 # 指定redis运行时数据文件保存路径 [root@localhost etc]# vi redis_6380.conf # 修改redis-server,修改下面几行 bind 0.0.0.0 port 6380 # 指定redis运行的端口 daemonize yes pidfile "/var/run/redis_6380.pid" logfile "/var/log/redis/redis_6380.log" dir /var/lib/redis_6380 slaveof 192.168.81.100 6379 # 指定redis-server为192.168.81.100:6379的slave [root@localhost etc]# redis-server /etc/redis_6379.conf # 指定配置文件运行redis-server [root@localhost etc]# redis-server /etc/redis_6380.conf # 指定配置文件运行redis-server [root@localhost etc]# ps aux | grep redis-server # 查看redis-server是否运行 root 2548 0.3 1.7 155192 17720 ? Ssl 23:14 0:00 redis-server 0.0.0.0:6379 root 2562 1.3 1.7 155192 17596 ? Ssl 23:15 0:00 redis-server 0.0.0.0:6380 root 2567 0.0 0.0 112648 960 pts/3 R+ 23:15 0:00 grep --color=auto redis-server [root@localhost etc]# redis-cli -p 6380 info replication # 进入6380端口运行redis客户端,并执行'info replication'命令 # Replication role:slave # 角色为slave master_host:192.168.81.100 # master为192.168.81.100 master_port:6379 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_repl_offset:1919 slave_priority:100 slave_read_only:1 connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 3.3 在192.168.81.101虚拟机上配置从节点 [root@mysql ~]# cd /etc/ # 操作同192.168.81.100相同 [root@mysql ~]# systemctl stop redis [root@mysql etc]# cp redis.conf redis_6379.conf [root@mysql etc]# cp redis.conf redis_6380.conf [root@mysql etc]# vi redis_6379.conf bind 0.0.0.0 protected-mode yes port 6379 daemonize yes pidfile "/var/run/redis_6379.pid" logfile "/var/log/redis/redis_6379.log" dir /var/lib/redis_6379 slaveof 192.168.81.100 6379 # 指定redis-server为192.168.81.100:6379的slave [root@mysql etc]# vi redis_6380.conf bind 0.0.0.0 port 6380 daemonize yes pidfile "/var/run/redis_6380.pid" logfile "/var/log/redis/redis_6380.log" dir /var/lib/redis_6380 slaveof 192.168.81.100 6379 # 指定redis-server为192.168.81.100:6379的slave [root@mysql etc]# redis-server /etc/redis_6379.conf # 指定配置文件运行redis-server [root@mysql etc]# redis-server /etc/redis_6380.conf # 指定配置文件运行redis-server [root@mysql ~]# ps aux | grep redis-server # 查看redis-server是否运行 root 2178 0.2 0.8 155204 17728 ? Ssl 15:10 0:02 redis-server 0.0.0.0:6379 root 2184 0.2 0.8 155204 17724 ? Ssl 15:10 0:02 redis-server 0.0.0.0:6380 root 2411 0.0 0.0 112664 972 pts/2 R+ 15:29 0:00 grep --color=auto redis-server [root@mysql ~]# redis-cli -p 6379 info replication # Replication role:slave # 角色为slave master_host:192.168.81.100 # master为192.168.81.100 master_port:6379 master_link_status:up master_last_io_seconds_ago:6 master_sync_in_progress:0 slave_repl_offset:1961 slave_priority:100 slave_read_only:1 connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 [root@mysql ~]# redis-cli -p 6380 info replication # Replication role:slave # 角色为slave master_host:192.168.81.100 # master为192.168.81.100 master_port:6379 master_link_status:up master_last_io_seconds_ago:2 master_sync_in_progress:0 slave_repl_offset:1975 slave_priority:100 slave_read_only:1 connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 3.4 在192.168.81.101虚拟机上配置并运行sentinel [root@mysql etc]# cp redis-sentinel.conf sentinel_26379.conf # 复制sentinel配置文件,方便区分 [root@mysql etc]# cp redis-sentinel.conf sentinel_26380.conf # 复制sentinel配置文件,方便区分 [root@mysql etc]# cp redis-sentinel.conf sentinel_26381.conf # 复制sentinel配置文件,方便区分 [root@mysql etc]# vi sentinel_26379.conf # 修改sentinel配置文件,修改下面几行 daemonize yes # 以守护进程方式启动 port 26379 # 指定端口 protected-mode no # 关闭保护模式 sentinel monitor mymaster 192.168.81.100 6379 2 # 设置sentinel监控信息 logfile /var/log/redis/sentinel_26379.log # 设置日志文件保存路径 [root@mysql etc]# vi sentinel_26380.conf daemonize yes port 26380 protected-mode no sentinel monitor mymaster 192.168.81.100 6379 2 logfile /var/log/redis/sentinel_26380.log [root@mysql etc]# vi sentinel_26381.conf protected-mode no port 26381 daemonize yes sentinel monitor mymaster 192.168.81.100 6379 2 logfile /var/log/redis/sentinel_26381.log [root@mysql etc]# redis-sentinel /etc/sentinel_26379.conf # 指定配置文件,启动Redis Sentinel [root@mysql etc]# redis-sentinel /etc/sentinel_26380.conf # 指定配置文件,启动Redis Sentinel [root@mysql etc]# redis-sentinel /etc/sentinel_26381.conf # 指定配置文件,启动Redis Sentinel [root@mysql etc]# ps aux | grep sentinel # 查看Redis Sentinel是否运行 root 2709 0.9 0.2 142916 5464 ? Ssl 15:49 0:00 redis-sentinel *:26379 [sentinel] root 2713 1.1 0.2 142916 5472 ? Ssl 15:49 0:00 redis-sentinel *:26380 [sentinel] root 2717 2.0 0.2 142916 5476 ? Rsl 15:49 0:00 redis-sentinel *:26381 [sentinel] root 2721 0.0 0.0 112664 964 pts/2 R+ 15:49 0:00 grep --color=auto sentinel [root@mysql ~]# redis-cli -p 26379 127.0.0.1:26379> ping # 执行ping操作 PONG 127.0.0.1:26379> info sentinel # 查看所有sentinel的信息 # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=192.168.81.100:6379,slaves=3,sentinels=3 # 被监控的Redis主从架构命名为mymaster,被监控Redis节点的master为192.168.81.100L6379,有三个slave,同时有3个sentinel运行 127.0.0.1:26379> exit [root@mysql ~]# grep -v '^#' /etc/sentinel_26379.conf | grep -v '^$' #查看sentinel_26379配置文件,去除注释和空行,Redis Sentinel向配置文件中添加了几行内容 port 26379 # sentinel运行的端口 dir "/tmp" sentinel myid 9611958fc3e8b7c2be43385e44be88f87d725a77 sentinel monitor mymaster 192.168.81.100 6379 2 # sentinel监控的Redis节点名为mymaster,master地址为192.168.81.100:6379,quorem设置为2 sentinel config-epoch mymaster 0 sentinel leader-epoch mymaster 0 logfile "/var/log/redis/sentinel_26379.log" daemonize yes sentinel known-slave mymaster 192.168.81.101 6379 # sentinel探测到的slave sentinel known-slave mymaster 192.168.81.100 6380 # sentinel探测到的slave sentinel known-slave mymaster 192.168.81.101 6380 # sentinel探测到的slave sentinel known-sentinel mymaster 192.168.81.101 26380 17ca0cb82becb58bd24e5a87ee3b6e8e9a49caf1 # Redis Sentinel深测到的别的运行的sentinel sentinel known-sentinel mymaster 127.0.0.1 26381 fb9342f3007e2abff165f5c33de1d48cf089f062 # Redis Sentinel深测到的别的运行的sentinel sentinel current-epoch 0 [root@mysql ~]# grep -v '^#' /etc/sentinel_26380.conf | grep -v '^$' port 26380 dir "/tmp" sentinel myid 17ca0cb82becb58bd24e5a87ee3b6e8e9a49caf1 sentinel monitor mymaster 192.168.81.100 6379 2 sentinel config-epoch mymaster 0 sentinel leader-epoch mymaster 0 logfile "/var/log/redis/sentinel_26380.log" daemonize yes sentinel known-slave mymaster 192.168.81.101 6379 sentinel known-slave mymaster 192.168.81.101 6380 sentinel known-slave mymaster 192.168.81.100 6380 sentinel known-sentinel mymaster 127.0.0.1 26381 fb9342f3007e2abff165f5c33de1d48cf089f062 sentinel known-sentinel mymaster 192.168.81.101 26379 9611958fc3e8b7c2be43385e44be88f87d725a77 sentinel current-epoch 0 [root@mysql ~]# grep -v '^#' /etc/sentinel_26381.conf | grep -v '^$' port 26381 daemonize yes dir "/tmp" sentinel myid fb9342f3007e2abff165f5c33de1d48cf089f062 sentinel monitor mymaster 127.0.0.1 6379 2 sentinel config-epoch mymaster 0 sentinel leader-epoch mymaster 0 logfile "/var/log/redis/sentinel_26381.log" sentinel known-sentinel mymaster 127.0.0.1 26380 17ca0cb82becb58bd24e5a87ee3b6e8e9a49caf1 sentinel known-sentinel mymaster 192.168.81.101 26379 9611958fc3e8b7c2be43385e44be88f87d725a77 sentinel current-epoch 0 至此,3个sentinel已经正常运行了 3.5 python客户端持续通过sentinel向Redis写入数据,读取数据 import random import time from redis.sentinel import Sentinel sentinel = Sentinel([ ('192.168.81.101',26379), ('192.168.81.101',26380), ('192.168.81.101',26381), ],socket_timeout=0.1) # 传入Redis Sentinel集合 while True: try: master = sentinel.discover_master('mymaster') print('current master IP:',master) # 打印当前master的IP地址和端口 val = random.randint(0,10000) # 获取10000以内随机整数 key = 'k%d' % val m = sentinel.master_for('mymaster', socket_timeout=0.5) m.set(key,'val%d' % val) # 通过sentinel向master节点写入数据 v = m.get(key) # 通过sentinel读取数据 print('{0} value is {1}'.format(key,v)) time.sleep(1) except Exception as e: print("get no val:",e) 运行上面的代码: current master IP: ('192.168.81.100', 6379) k6081 value is b'val6081' current master IP: ('192.168.81.100', 6379) k1778 value is b'val1778' current master IP: ('192.168.81.100', 6379) k4927 value is b'val4927' current master IP: ('192.168.81.100', 6379) k4074 value is b'val4074' current master IP: ('192.168.81.100', 6379) k1138 value is b'val1138' current master IP: ('192.168.81.100', 6379) k862 value is b'val862' current master IP: ('192.168.81.100', 6379) k4854 value is b'val4854' current master IP: ('192.168.81.100', 6379) k9233 value is b'val9233' current master IP: ('192.168.81.100', 6379) k6844 value is b'val6844' current master IP: ('192.168.81.100', 6379) k8089 value is b'val8089' 3.6 在192.168.81.100虚拟机上模拟master故障 [root@localhost etc]# redis-cli -p 6379 # 连接6379端口连接redis-server 127.0.0.1:6379> info server # 执行命令查看当前redis-server的进程ID # Server redis_version:3.2.10 redis_git_sha1:00000000 redis_git_dirty:0 redis_build_id:c8b45a0ec7dc67c6 redis_mode:standalone os:Linux 3.10.0-514.el7.x86_64 x86_64 arch_bits:64 multiplexing_api:epoll gcc_version:4.8.5 process_id:2548 # 192.168.81.100:6379这个master节点的进程ID为2548 run_id:8ae71ba92660697d52bfb74b99fb15ee82a7cf84 tcp_port:6379 uptime_in_seconds:6552 uptime_in_days:0 hz:10 lru_clock:12896355 executable:/etc/redis-server config_file:/etc/redis_6379.conf 127.0.0.1:6379> exit [root@localhost etc]# kill -9 2548 # 在系统中kill掉2548这个进程 [root@localhost etc]#
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信