Redis哨兵简介

前言

Redis Sentinel是Redis官方建议的高可用(HA)解决方案,在我们搭建Redis集群时,Redis本身并未集成主备切换功能,sentinel本身是独立运行的,能够监控多个Redis集群,发现master宕机后能够自动切换,选举一个slave成为新的master,当原master恢复之后,sentinel会自动将其作为slave加入到集群中,整个过程不需要人工参与,完全自动化。

主要介绍

  1. sentinel主要功能

    • 定期监控Redis服务是否运行正常
    • 定期监控其他sentinel服务是否正常
    • 能够自动切换master节点
    • sentinel节点不存储数据
  2. sentinel集群

    这个不难理解,如果我们用一个非高可用的sentinel去实现Redis的高可用,明显是不科学的,当这一台sentinel宕机之后,Redis显然无法继续保持它的高可用,所以我们在部署sentinel的时候也会采用集群的方式

    优势:

    ​ 即使有sentinel服务宕机,只要还有一台sentinel运行正常,就可以使Redis继续保持高可用

  3. sentinel版本问题

    sentinel在Redis2.6版本中引入的,当时是sentinel 1,貌似有蛮多问题,毕竟初版

    在Redis2.8版本中升级到sentinel 2,之后就非常稳定了

    不过现在Redis已经发展了很久,版本也越来越高,sentinel已经非常值得信赖了

  4. sentinel中的定时任务

    • 每隔10秒向各个Redis服务器(master和slave节点)发送INFO命令,根据回应获取master和slave信息,通过master的回复可以获取到新增的slave节点
    • 每隔02秒向Redis的master服务器发送命令(hello消息),用于发现和监视其他sentinel,sentinel之间的监控不在额外创建订阅
    • 每隔01秒向Redis和sentinel所有服务发送PING消息(sentinel本身的ip、端口、id等内容),通过回复PONG判断服务是否在线
  5. 下线判断

    • 主观下线:当前sentinel断定master下线
    • 客观下线:满足sentinel配置文件中quorum数量的sentinel均断定master下线
  6. 配置文件解读

    # sentinel运行的端口,默认为26379
    port 26377      
    
    dir "/private/tmp"
    
    logfile "/var/log/redis/sentinel_26377.log"
    
    # 以守护进程执行
    daemonize yes
    
    # 守护进程运行的pid保存文件
    pidfile "/var/run/redis-sentinel.pid"
    
    # 格式:sentinel monitor    
    # 该行的意思是::自定义
    #		:master主机的IP
    #		:master的端口
    #		:表示在sentinel集群中,使master由主观下线变为客观下线的sentinel数量。
    sentinel monitor cc_master 127.0.0.1 6379 2  
    
    # 格式:sentinel down-after-milliseconds  
    # sentinel会向master发送心跳PING来确认master是否存活,如果master在时间内回应的不是PONG,那么这个sentinel会主观地认为这个master下线了。的单位是毫秒,默认30秒。
    sentinel down-after-milliseconds cc_master 15000
    
    # 格式:sentinel failover-timeout  
    # failover过期时间,当failover开始后,在此时间内仍然没有触发任何failover操作,当前sentinel将会认为此次failoer失败。默认180秒,即3分钟。
    sentinel failover-timeout cc_master 60000
    
    # sentinel parallel-syncs  
    # 在发生failover主备切换时,这个选项指定了最多可以有多少个slave同时对新的master进行同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越多的slave因为replication而不可用。可以通过将这个值设为1来保证每次只有一个slave处于不能处理命令请求的状态。
    sentinel parallel-syncs cc_master 1
    
    # 格式:sentinel auth-pass  
    # sentinel连接的master节点的登录密码
    sentinel auth-pass cc_master redis
    
  7. 故障转移

    • sentinel使用Raft投票选举出一个leader去执行故障转移
      • 每一个将master标记为主观下线的sentinel节点发起投票
      • 其他sentinel节点收到投票后,若尚未参与投票(也就是尚未投票给其他sentinel),则同意,否则拒绝
      • 最终收到过半同意的sentinel节点作为leader
      • 若有两个sentinel收到了过半投票,那么就再重新选举
    • 选举新的master节点
      • 选择replica-priority配置数字最高的slave节点为master,默认为100
      • 若replica-priority相同,则选择偏移量最大的slave节点,偏移量是指slave从master同步的进度,偏移量越大说明数据越完整,可以通过Redis的info命令查看(slave_repl_offset)当前slave的偏移量
      • 若偏移量相同,则选择最先启动的slave作为master
      • 更改master后,通知其他slave节点同步为新的master节点的slave节点
      • 原master节点恢复之后自动加入到集群中,成为新master的slave节点

实战

在本机上启动3个Redis实例,采用1主2从的模式,以下只记录redis.conf和sentinel.conf中关键内容

  1. redis.conf

    • redis-master.conf配置

      # 默认端口
      port 6379
      
    • redis-slave1.conf配置

      # 端口
      port 63791
      
      # 格式:replicaof  
      # 从节点归属的master节点
      replicaof 127.0.0.1 6379
      
    • redis-slave2.conf配置

      # 端口
      port 63792
      
      # 格式:replicaof  
      # 从节点归属的master节点
      replicaof 127.0.0.1 6379
      
  2. sentinel.conf

    • sentinel0.conf

      # 端口
      port 26379
      
      sentinel myid 842c9102c48eb0cedeb06fe55e7d2258595ac267
      
      # 监控master
      sentinel monitor cc_master 127.0.0.1 6379 2
      
    • sentinel1.conf

      # 端口
      port 26378
      
      sentinel myid 842c9102c48eb0cedeb06fe55e7d2258595ac266
      
      # 监控master
      sentinel monitor cc_master 127.0.0.1 6379 2
      
    • sentinel2.conf

      # 端口
      port 26377
      
      sentinel myid 842c9102c48eb0cedeb06fe55e7d2258595ac265
      
      # 监控master
      sentinel monitor cc_master 127.0.0.1 6379 2
      
  3. 启动

    1. 启动sentinel

      redis-sentinel ~/Documents/develop_tools/tools/redis-5.0.5/sentinel0.conf
      
      redis-sentinel ~/Documents/develop_tools/tools/redis-5.0.5/sentinel1.conf
      
      redis-sentinel ~/Documents/develop_tools/tools/redis-5.0.5/sentinel2.conf
      
    2. 启动Redis

      redis-server ~/Documents/develop_tools/tools/redis-5.0.5/redis-master.conf
      
      redis-server ~/Documents/develop_tools/tools/redis-5.0.5/redis-slave1.conf
      
      redis-server ~/Documents/develop_tools/tools/redis-5.0.5/redis-slave2.conf
      

Redis通过info查看信息

127.0.0.1:6379>info all

# Server服务器信息
redis_version:5.0.5		# Redis 服务器版本
redis_git_sha1:00000000 # Git SHA1
redis_git_dirty:0		# Git dirty flag
redis_build_id:6c6e38af7cea0726	# Redis构建ID
redis_mode:standalone			# Redis运行模式
os:Darwin 19.3.0 x86_64		# 运行环境操作系统版本
arch_bits:64			# 架构(32 或 64 位)
multiplexing_api:kqueue		# Redis 所使用的事件处理机制
atomicvar_api:atomic-builtin
gcc_version:4.2.1		# 编译的GCC版本
process_id:61985		# 服务器进程的 PID
run_id:433b78ec513c8b782f3a46ba6b4ade1f12439aca		# Redis 服务器的随机标识符(用于Sentinel和集群)
tcp_port:6379		# Redis端口
uptime_in_seconds:108		# Redis运行时长,秒
uptime_in_days:0		# Redis运行市场,天
hz:10
configured_hz:10
lru_clock:8363059		# 以分钟为单位进行自增的时钟,用于 LRU 管理
executable:/Users/chuan/redis-server		# 运行命令
config_file:			# 启动使用的配置文件

# Clients
connected_clients:7		# 已连接客户端的数量
client_recent_max_input_buffer:2		# 当前连接的客户端当中,最长的输出列表
client_recent_max_output_buffer:0		# 当前连接的客户端当中,最大输入缓存
blocked_clients:0			# 正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客户端的数量

# Memory (太多了,不做解释了)
used_memory:2235920				# 由 Redis 分配器分配的内存总量,以字节(byte)为单位
used_memory_human:2.13M		# 以可读的格式返回 Redis 分配的内存总量
used_memory_rss:3153920		# 从操作系统的角度,返回 Redis 已分配的内存总量(俗称常驻集大小)。这个值和top 、 ps 等命令的输出一致。
used_memory_rss_human:3.01M # 以可读的格式返回rss
used_memory_peak:2317840		# Redis 的内存消耗峰值(以字节为单位)
used_memory_peak_human:2.21M
used_memory_peak_perc:96.47%
used_memory_overhead:2221526
used_memory_startup:987776
used_memory_dataset:14394
used_memory_dataset_perc:1.15%
allocator_allocated:2271808
allocator_active:3116032
allocator_resident:3116032
total_system_memory:17179869184
total_system_memory_human:16.00G
used_memory_lua:37888
used_memory_lua_human:37.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.37
allocator_frag_bytes:844224
allocator_rss_ratio:1.00
allocator_rss_bytes:0
rss_overhead_ratio:1.01
rss_overhead_bytes:37888
mem_fragmentation_ratio:1.39
mem_fragmentation_bytes:882112
mem_not_counted_for_evict:0
mem_replication_backlog:1048576
mem_clients_slaves:33844
mem_clients_normal:151226
mem_aof_buffer:0
mem_allocator:libc
active_defrag_running:0
lazyfree_pending_objects:0

# Persistence
loading:0		# 服务器是否正在载入持久化文件
rdb_changes_since_last_save:1		# 距离最后一次成功创建持久化文件之后,改变了多少个键值
rdb_bgsave_in_progress:0		# 服务器是否正在创建RDB文件
rdb_last_save_time:1585421263		# 最近一次成功创建RDB文件的UNIX时间
rdb_last_bgsave_status:ok		# 最后一次创建RDB文件的结果是成功还是失败
rdb_last_bgsave_time_sec:0		# 最后一次创建RDB文件耗费的秒数
rdb_current_bgsave_time_sec:-1	# 记录当前创建RDB操作已经耗费了多长时间(单位为秒)
rdb_last_cow_size:0
aof_enabled:0		# AOF是否处于打开状态
aof_rewrite_in_progress:0		# 服务器是否正在创建AOF文件
aof_rewrite_scheduled:0		# 是否需要执行预约的AOF重写操作
aof_last_rewrite_time_sec:-1	# 最后一次重启AOF的秒数
aof_current_rewrite_time_sec:-1		# 记录当前正在重写AOF的秒数
aof_last_bgrewrite_status:ok		# 最后一次重写AOF文件的结果
aof_last_write_status:ok		# 最后一次写入结果
aof_last_cow_size:0

# Stats	(可以不做了解)
total_connections_received:9
total_commands_processed:720
instantaneous_ops_per_sec:6
total_net_input_bytes:34197
total_net_output_bytes:229238
instantaneous_input_kbps:0.34
instantaneous_output_kbps:1.19
rejected_connections:0
sync_full:2		# 主从完全同步成功次数
sync_partial_ok:0		# 主从部分同步成功次数
sync_partial_err:0	# 主从部分同步失败次数
expired_keys:0			# 运行以来过期的key的数量
expired_stale_perc:0.00		# 过期的比率
expired_time_cap_reached_count:0		# 过期计数
evicted_keys:0
keyspace_hits:1
keyspace_misses:1
pubsub_channels:1
pubsub_patterns:0
latest_fork_usec:278
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0

# Replication(master节点)
role:master		# 角色 master和slave
connected_slaves:2	# slave节点数
slave0:ip=127.0.0.1,port=63791,state=online,offset=20163,lag=1	# 从节点1
slave1:ip=127.0.0.1,port=63792,state=online,offset=20163,lag=0	# 从节点2
master_replid:895f219aa1e7ed5ecda50dcb1f77eea9f1ef9c3d		# 主实例启动随机字符串
master_replid2:0000000000000000000000000000000000000000		# 主实例启动随机字符串2
master_repl_offset:20163		# 主从同步偏移量,此值如果和上面的offset相同说明主从一致没延迟,与master_replid可被用来标识主实例复制流中的位置。
second_repl_offset:-1				# 主从同步偏移量2,此值如果和上面的offset相同说明主从一致没延迟
repl_backlog_active:1				# 复制积压缓冲区是否开启
repl_backlog_size:1048576		# 复制积压缓冲大小
repl_backlog_first_byte_offset:1	# 复制缓冲区里偏移量的大小
repl_backlog_histlen:20163	# 此值等于 master_repl_offset - repl_backlog_first_byte_offset,该值不会超过repl_backlog_size的大小

# Replication(slave节点)
role:slave		# 角色 master和slave
master_host:127.0.0.1		# master节点IP
master_port:6379				# master节点端口
master_link_status:up		# master通信
master_last_io_seconds_ago:1		# 主库多少秒未发送数据到从库
master_sync_in_progress:0			# 从服务器是否在与主服务器进行同步
slave_repl_offset:42262		# slave复制偏移量
slave_priority:100		# slave优先级
slave_read_only:1			# 从库是否设置只读
connected_slaves:0		# 连接的slave实例个数
master_replid:895f219aa1e7ed5ecda50dcb1f77eea9f1ef9c3d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:42262		# master偏移量,与slave_repl_offset相同则表示同步完整
second_repl_offset:-1
repl_backlog_active:1		# 复制积压缓冲区是否开启
repl_backlog_size:1048576			# 复制积压缓冲大小
repl_backlog_first_byte_offset:1		# 复制缓冲区里偏移量的大小
repl_backlog_histlen:42262		# 此值等于 master_repl_offset - repl_backlog_first_byte_offset,该值不会超过repl_backlog_size的大小

# CPU
used_cpu_sys:0.104404		# 将所有redis主进程在核心态所占用的CPU时求和累计起来
used_cpu_user:0.079472	# 将所有redis主进程在用户态所占用的CPU时求和累计起来
used_cpu_sys_children:0.002037	# 将后台进程在核心态所占用的CPU时求和累计起来
used_cpu_user_children:0.000648	# 将后台进程在用户态所占用的CPU时求和累计起来

# Cluster
cluster_enabled:0	# 实例是否启用集群模式

# Keyspace
db0:keys=1,expires=0,avg_ttl=0	# db0的key的数量,以及带有生存期的key的数,平均存活时间

你可能感兴趣的:(Redis,redis,分布式)