Linux——redis主从复制、集群模式、哨兵模式

4 篇文章 0 订阅
  1. 主从复制

    1. 部署至少两个redis的实例     // 提供数据冗余和备份
      • 两个独立服务器
      • 两个虚拟机
      • 两个容器
    2. 一个redis的master 节点可以有多个redis的replica 从节点, 而从节点也可以成为其他从节点的主节点     // 方便对于主复制架构进行扩展
    3. 提供数据灾备,当redis 的主节点宕机的情况下,尽快恢复数据  // 可以进行故障转移
    4. 不支持自动的故障转移    // 缺陷
  2. 集群模式

    1. 一种特殊的redis实例运行方式,在这种方式下,处于同一个redis集群中的实例,将通过集群端口互相交换状态,以维持集群的高可用和数据完整
    2. hash slot将数据分散到集群中的每一个节点
    3. 集群模式支持为数据存储的节点设置数据副本,这样在主节点出现故障的情况下,从节点将自动切换为主节点;
    4. 集群模式下,架构的维护也很方便,加入新的主节点时,需要从原有的主节点中划分一些hash slot给新的节点,保证新的主节点能够在集群中完成数据保存和协议;如果是一个从节点,那么就只需要指定从节点的主节点即可 
    5. 集群模式提供了相对完整高可用以及自动故障转移的机制
  3. 哨兵模式

    1. 一般搭配主从复制机制一起部署
    2. 功能:
      • 监控:监控redis 主从架构下,所有的redis实例是否正常
      • 发送提示信息:在发现异常情况后,向系统管理员或者API 发送提示信息
      • 自动故障转移:在发现master 异常后,哨兵将从所有的从节点中选择一个成为新的主节点,然后通过所有的从节点新的主节点信息,而无需手动干预,在主节点排除异常之后,哨兵进程将原来的主节点作为从节点计入所监控的主从架构
      • 配置更新:哨兵还可以更新所监控redis实例的配置

哨兵模式的工作机制:

比如说目前使用一个哨兵集群监控一个由三个redis实例构成的主从复制架构

哨兵集群:哨兵1 哨兵2 哨兵3

主从架构: master1  replica1 replica2

判断主节点异常时,分为主观宕机和客观宕机:

主观宕机: 哨兵发送的状态监测没有收到主节点的响应,此时哨兵认为主节点异常,此时的异常,并不会触发自动故障转移机制,会有哨兵集群进行仲裁来判断主节点是否真的不可用。

客观宕机:如果某一个哨兵进程判断主节点主观宕机,那么在哨兵集群内发起仲裁,必须是超过指定数量的哨兵同意主节点宕机,才会开始故障转移的过程,此时认为主节点客观宕机。

哨兵1 发现 master1 宕机,则通知剩下哨兵实例,判断master1 是不是真的宕机,假设仲裁数为2,那么只要哨兵2 或者 哨兵3 任意一个同意 master1 宕机,那么就认为master 客观宕机,开始故障转移。

故障转移: 在判定主节点客观宕机之后,哨兵进行故障转移,但是为了避免哨兵集群中各个实例在新的主节点选择上可能出现的不同选择,所以先在哨兵集群内选择(Raft算法)一个节点作为故障转移的仲裁者和执行者。选举出来的哨兵在剩余的从节点中选择一个从节点,成为新的主节点,并且将主节点的信息同步给剩下的从节点。

哨兵集群内开始投票,哪一个实例应该成为下一步的执行实例,所有的哨兵给其他实例,发送投票信息,一个哨兵实例只能投一票,且这一票只能投给它收到的第一个投票信息的发送方。

哨兵最小的部署数量为3个实例或者3个不同的节点;哨兵和redis 数据实例分别部署到不同的节点;哨兵模式也不能完全保证数据没有任何的丢失,完全保证高可用。

sentinel monitor mymaster 127.0.0.1 6379 2 

//monitor配置主节点监控sentinel monitor 自定义的master 名称 主节点ip  主节点端口 仲裁数 (关于客观宕机的最低数量)

sentinel down-after-milliseconds mymaster 60000

// 主节点宕机或者异常的超时时间

sentinel failover-timeout mymaster 180000

// 故障转移的超时时间

sentinel parallel-syncs mymaster 1

//是否会进行并发同步   后面设置的是,可以进行并发同步的从节点的数量,

实验环境下部署一主二从+3哨兵

5000 - 5002 端口对应 哨兵

6379 端口对应redis 主节点

6380 6381 端口对应redis 从节点

为了加快实验进度,只监听本地环回

实验过程

先设置主从复制:

[root@redis-servers ~]# ls -d /redis-cluster/
/redis-cluster/
[root@redis-servers ~]# cd /redis-cluster/
[root@redis-servers redis-cluster]# mkdir 5000 5001 5002 6379 6380 6381
[root@redis-servers redis-cluster]# mv 5000 5000-s 
[root@redis-servers redis-cluster]# mv 5001 5001-s 
[root@redis-servers redis-cluster]# mv 5002 5002-s 
[root@redis-servers redis-cluster]# vim 6379/redis.conf
[root@redis-servers 6379]# cat redis.conf 
port 6379
bind 127.0.0.1
dbfilename "6379.rdb"
dir "/redis-cluster/6379"
save 3600 1
appendonly yes
appendfilename "6379.aof"
logfile "/redis-cluster/6379/6379.log"
daemonize yes
pidfile "/redis-cluster/6379/6379.pid"

[root@redis-servers redis-cluster]# cp 6379/redis.conf 6380/redis.conf
[root@redis-servers redis-cluster]# cp 6379/redis.conf 6381/redis.conf
[root@redis-servers redis-cluster]# sed -i 's/6379/6380/g' /redis-cluster/6380/redis.conf 
[root@redis-servers redis-cluster]# sed -i 's/6379/6381/g' /redis-cluster/6381/redis.conf 
[root@redis-servers redis-cluster]# systemctl stop redis.service 
# 启动6379
[root@redis-servers 6379]# redis-server redis.conf 
[root@redis-servers 6379]# ss -anput | grep redis
tcp   LISTEN 0      511                 127.0.0.1:6379          0.0.0.0:*    users:(("redis-server",pid=3614,fd=6))                                         
[root@redis-servers 6379]# cd ../6380

# 从节点修改配置文件

[root@redis-servers 6380]# vim redis.conf 
port 6380
bind 127.0.0.1
dir "/redis-cluster/6380"
dbfilename "6380.rdb"
save 3600 1
appendonly yes
appendfilename "6380.aof"
logfile "/redis-cluster/6380/6380.log"
daemonize yes
pidfile "/redis-cluster/6380/6380.pid"
replicaof 127.0.0.1 6379
[root@redis-servers 6380]# redis-server redis.conf 
[root@redis-servers 6380]# ss -anput | grep redis
tcp   LISTEN 0      511                 127.0.0.1:6379          0.0.0.0:*     users:(("redis-server",pid=3614,fd=6))                                         
tcp   LISTEN 0      511                 127.0.0.1:6380          0.0.0.0:*     users:(("redis-server",pid=3635,fd=6))                                         
tcp   ESTAB  0      0                   127.0.0.1:6379        127.0.0.1:40937 users:(("redis-server",pid=3614,fd=8))                                         
tcp   ESTAB  0      0                   127.0.0.1:40937       127.0.0.1:6379  users:(("redis-server",pid=3635,fd=8))                                         
[root@redis-servers 6380]# sed -i 's/6380/6381/g' /redis-cluster/6381/redis.conf 
[root@redis-servers 6380]# cd ../6381
[root@redis-servers 6381]# redis-server redis.conf 
port 6381
bind 127.0.0.1
dir "/redis-cluster/6381"
dbfilename "6381.rdb"
save 3600 1
appendonly yes
appendfilename "6381.aof"
logfile "/redis-cluster/6381/6381.log"
daemonize yes
pidfile "/redis-cluster/6381/6381.pid"
replicaof 127.0.0.1 6379

[root@redis-servers 6381]# ss -anput | grep redis
tcp   LISTEN 0      511                 127.0.0.1:6379          0.0.0.0:*     users:(("redis-server",pid=3614,fd=6))                                         
tcp   LISTEN 0      511                 127.0.0.1:6381          0.0.0.0:*     users:(("redis-server",pid=3668,fd=6))                                         
tcp   LISTEN 0      511                 127.0.0.1:6380          0.0.0.0:*     users:(("redis-server",pid=3635,fd=6))                                         
tcp   ESTAB  0      0                   127.0.0.1:6379        127.0.0.1:40937 users:(("redis-server",pid=3614,fd=8))                                         
tcp   ESTAB  0      0                   127.0.0.1:6379        127.0.0.1:44615 users:(("redis-server",pid=3614,fd=9))                                         
tcp   ESTAB  0      0                   127.0.0.1:40937       127.0.0.1:6379  users:(("redis-server",pid=3635,fd=8))                                         
tcp   ESTAB  0      0                   127.0.0.1:44615       127.0.0.1:6379  users:(("redis-server",pid=3668,fd=8))                                         
[root@redis-servers 6381]# redis-cli -p 6379
127.0.0.1:6379> info 

。。。。。

# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=210,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=210,lag=1
master_failover_state:no-failover
master_replid:e094b62e7f1f29b7d0449755c8627eb6e17f438d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:210
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:210

……
127.0.0.1:6379> set testa test 
OK
127.0.0.1:6379> get testa
"test"
127.0.0.1:6379> exit
[root@redis-servers 6381]# redis-cli -p 6380
127.0.0.1:6380> get testa
"test"
127.0.0.1:6380> info 

……
# Replication
role:slave			///
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:2
master_sync_in_progress:0
slave_read_repl_offset:435
slave_repl_offset:435
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:e094b62e7f1f29b7d0449755c8627eb6e17f438d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:435
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:435

……
127.0.0.1:6380> exit
[root@redis-servers 6381]# redis-cli -p 6381
127.0.0.1:6381> info 

……
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_read_repl_offset:477
slave_repl_offset:477
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:e094b62e7f1f29b7d0449755c8627eb6e17f438d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:477
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:113
repl_backlog_histlen:365

……
127.0.0.1:6381> exit

//主从架构完毕,启动哨兵集群

[root@redis-servers 6381]# cd ../5000-s/
[root@redis-servers 5000-s]# vim sentinel.conf
port 5000
sentinel monitor mymaster 127.0.0.1 6380 2
sentinel down-after-milliseconds mymaster 5001
sentinel failover-timeout mymaster 10000
sentinel parallel-syncs mymaster 3
daemonize yes
pidfile "/redis-cluster/5000-s/5000.pid"
logfile "/redis-cluster/5000-s/5000.log"

[root@redis-servers 5000-s]# cp sentinel.conf ../5001-s/sentinel.conf 
[root@redis-servers 5000-s]# cp sentinel.conf ../5002-s/sentinel.conf 
[root@redis-servers 5000-s]# sed -i 's/5000/5001/g' /redis-cluster/5001-s/sentinel.conf 
[root@redis-servers 5000-s]# sed -i 's/5000/5002/g' /redis-cluster/5002-s/sentinel.conf 
[root@redis-servers 5000-s]# redis-sentinel sentinel.conf 
[root@redis-servers 5000-s]# ss -anput | grep 5000
tcp   LISTEN 0      511                   0.0.0.0:5000          0.0.0.0:*     users:(("redis-sentinel",pid=3795,fd=6))                                          
tcp   LISTEN 0      511                      [::]:5000             [::]:*     users:(("redis-sentinel",pid=3795,fd=7))                                          
[root@redis-servers 5000-s]# cd ../5001-s/
[root@redis-servers 5001-s]# redis-sentinel sentinel.conf 
[root@redis-servers 5001-s]# cd ../5002-s/
[root@redis-servers 5002-s]# redis-sentinel sentinel.conf 
[root@redis-servers 5002-s]# ss -anput | grep 5000
tcp   LISTEN 0      511                   0.0.0.0:5000          0.0.0.0:*     users:(("redis-sentinel",pid=3795,fd=6))                                          
tcp   ESTAB  0      0                   127.0.0.1:5000        127.0.0.1:42422 users:(("redis-sentinel",pid=3795,fd=16))                                         
tcp   ESTAB  0      0                   127.0.0.1:39696       127.0.0.1:5000  users:(("redis-sentinel",pid=3806,fd=14))                                         
tcp   ESTAB  0      0                   127.0.0.1:42422       127.0.0.1:5000  users:(("redis-sentinel",pid=3814,fd=14))                                         
tcp   ESTAB  0      0                   127.0.0.1:5000        127.0.0.1:39696 users:(("redis-sentinel",pid=3795,fd=14))                                         
tcp   LISTEN 0      511                      [::]:5000             [::]:*     users:(("redis-sentinel",pid=3795,fd=7))                                          
[root@redis-servers 5002-s]# ss -anput | grep 5001
tcp   LISTEN 0      511                   0.0.0.0:5001          0.0.0.0:*     users:(("redis-sentinel",pid=3806,fd=6))                                          
tcp   ESTAB  0      0                   127.0.0.1:58430       127.0.0.1:5001  users:(("redis-sentinel",pid=3795,fd=15))                                         
tcp   ESTAB  0      0                   127.0.0.1:47264       127.0.0.1:5001  users:(("redis-sentinel",pid=3814,fd=15))                                         
tcp   ESTAB  0      0                   127.0.0.1:5001        127.0.0.1:58430 users:(("redis-sentinel",pid=3806,fd=15))                                         
tcp   ESTAB  0      0                   127.0.0.1:5001        127.0.0.1:47264 users:(("redis-sentinel",pid=3806,fd=16))                                         
tcp   LISTEN 0      511                      [::]:5001             [::]:*     users:(("redis-sentinel",pid=3806,fd=7))                                          
[root@redis-servers 5002-s]# ss -anput | grep 5002
tcp   LISTEN 0      511                   0.0.0.0:5002          0.0.0.0:*     users:(("redis-sentinel",pid=3814,fd=6))                                          
tcp   ESTAB  0      0                   127.0.0.1:5002        127.0.0.1:60252 users:(("redis-sentinel",pid=3814,fd=16))                                         
tcp   ESTAB  0      0                   127.0.0.1:60252       127.0.0.1:5002  users:(("redis-sentinel",pid=3806,fd=17))                                         
tcp   ESTAB  0      0                   127.0.0.1:60254       127.0.0.1:5002  users:(("redis-sentinel",pid=3795,fd=17))                                         
tcp   ESTAB  0      0                   127.0.0.1:5002        127.0.0.1:60254 users:(("redis-sentinel",pid=3814,fd=17))                                         
tcp   LISTEN 0      511                      [::]:5002             [::]:*     users:(("redis-sentinel",pid=3814,fd=7))                                          
[root@redis-servers 5002-s]# cat sentinel.conf 
port 5002
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5001
sentinel failover-timeout mymaster 10000
sentinel parallel-syncs mymaster 3
daemonize yes
pidfile "/redis-cluster/5002-s/5002.pid"
logfile "/redis-cluster/5002-s/5002.log"
# Generated by CONFIG REWRITE
protected-mode no
user default on nopass ~* &* +@all
dir "/redis-cluster/5002-s"
sentinel myid b90766a4d52b2d5b7a61b0813778fc69ca4b2624
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
sentinel current-epoch 0
sentinel known-replica mymaster 127.0.0.1 6381
sentinel known-replica mymaster 127.0.0.1 6380
sentinel known-sentinel mymaster 127.0.0.1 5001 8af5123cd008d359e03094f7c64ef841e4e698be
sentinel known-sentinel mymaster 127.0.0.1 5000 3b84754839534a86f071df092bc630ba51ba01c5
[root@redis-servers ~]# redis-cli -p 6379 debug sleep 60    // 打开新终端,暂停6379 主节点
OK

// 所有的哨兵日志中将出现主从架构变更过程,同时变更完成的架构将同步给每一个哨兵和redis数据实例

随便查看任何配置文件

redis数据实例配置文件变化

6379:

6380:

6381:

redis 缓存可能面临问题:

  1. 缓存穿透     在redis缓存没有找到对应的数据,去数据库查询数据,如果查询的是本来数据库就没有的数据,那么就会频发触发数据库的全表扫描,如果同一时间出现大量缓存穿透,那么就会增加数据库的压力。

解决方案:

  1. 设置空键,在数据库中查询无数据后,在redis设立空键,下次查询的时候直接返回控制,不会触发数据库查询。如果有大量的缓存穿透发生,那么空键数量增加,浪费redis存储空间,一般会设置空键的过期时间
  2. 利用一些编程手段规避

  1. 缓存击穿     有大量的空查询发生,比如说热点数据没有提前缓存,那么同时会有大量用户访问热点数据,导致数据库压力增加。

解决方案:

  1. 预热数据(提前缓存数据)
  2. 通过互斥锁,只有第一次查询连接数据库,其他查询进入队列,后续查询则会从redis

3、缓存雪崩    会造成比较严重的生产事故,大量热点数据同时过期,同时用户访问量较高,一般频发在秒杀活动等场景。

解决方案:

  1. 使用随机数设置键值过期时间
  2. 结合缓存击穿的策略进一步优化

补充阅读:

https://github.com/CoderLeixiaoshuai/java-eight-part/blob/master/docs/redis/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值