当前位置: 首页 > article >正文

2024.11.7- Redis的主从复制集群

7.1 Redis的主从复制

7.1.1 简介

主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。

默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。

主从复制的作用主要包括:

数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。

7.1.2 搭建步驟

1)说明
1. 如果有密碼策略,那麽从节点需要主节点的密码,如果想要启动哨兵机制,也需要密码策略
2. 正常情况下,master和slave应该分布在不同的机器上。
​
三台机器:
      192.168.100.101     youcai01       6379     master
      192.168.100.102     youcai02       6379     slave
      192.168.100.103     youcai03       6379     slave
​
3. 使用持久化混合模式
4. 防火墙一定要关闭
​
# 如果只有一台机器,可以使用不同的配置文件和port以及不同的持久化的位置即可。
​
2)搭建步骤

步骤1: 修改youcai01、youcai02、youcai03的配置文件redis.conf(可以使用克隆的方式)

[root@youcai01 ~]# vim /usr/local/redis/bin/redis.conf
​
​
#注释 只能本地连接
#bind 127.0.0.1
#端口号
port 6379
#设置后台启动
daemonize yes
#3 默认开启保护模式,如果没有设置密码或者没有 bind 配置,我只允许在本机连接我,其它机器无法连接。
protected-mode no
​
#密码策略
requirepass 123456
#连接master的密码, 在两个slave上配置  master宕机后,slave--》master
masterauth  123456
​
​
#pid文件的位置: 进程id保存的位置
pidfile "/var/run/redis_6379.pid"
​
#启动服务的日志级别: DEBUG,INFO....
loglevel notice
#启动服务器的日志文件位置:   空字符串是STDOUT,默认打印到屏幕上
logfile "/var/log/redis.log"
​
​
#========  RDB全量持久化设置
save 3600 1 300 100 60 10000
# 文件名
dbfilename dump.rdb
# rdb持久化的位置
dir "/usr/local/redis/mydata"
​
​
#========  AOF增量持久化设置
appendonly yes
appendfilename "appendonly.aof"
​
#RDB和AOF两个持久化混合使用, 默认就是这个设置
aof-use-rdb-preamble yes

步骤2)启动三个服务

提前写了一个启动或关闭的服务脚本: 注意,关闭的IP要对应上自己的IP,

[root@youcai03 ~]#  vim /usr/local/redis/bin/myRedisServer.sh
​
#!/bin/bash
​
PATH=/usr/local/redis/bin
​
case $1 in
start)
  $PATH/redis-server $PATH/redis.conf
  echo "---redis服务已经启动---"
;;
stop)
  $PATH/redis-cli -h 192.168.100.103 -a 123456 shutdown
  echo "---redis服务已经关闭---"
;;
esac
在三台机器上运行:
[root@youcai01 ~]#  myRedisServer.sh start
[root@youcai02 ~]#  myRedisServer.sh start
[root@youcai03 ~]#  myRedisServer.sh start

最好是查看一下进程:
ps -ef | grep redis

步骤3)连接三台服务

[root@youcai01 ~]# redis-cli -h youcai01 -a 123456 -p 6379
[root@youcai02 ~]# redis-cli -h youcai02 -a 123456 -p 6379
[root@youcai03 ~]# redis-cli -h youcai03 -a 123456 -p 6379

步骤4)查看各个服务的状态

info replication
​
正常情况下:看到的都是master

步骤5)配从不配主

在slave机器上,配置,语法如下:

slaveof/replicaof master-host master-port   #  replicaof/slaveof   这两个命令二选一即可,功能一样

临时配置:在客户端里使用如下指令

102机器上配置:slaveof youcai01 6379         
103机器上配置:slaveof youcai01 6379

永久配置:配置文件里配置

530 #    network partition replicas automatically try to reconnect to masters
531 #    and resynchronize with them.
532 #   replicaof/slaveof   这两个命令二选一即可,功能一样
533 replicaof youcai01 6379

步骤6)测试

slave上只能读,不能写,写的话要在master进行,当然master也可以进行读操作

缺点:

一旦master宕机,slave并不能自动选出一个代表作为master,需要人工干预,很麻烦。

断开关系

slaveof no one   表示我切断与master的关系。

7.1.3 主从复制的原理

首先进行全量同步(全量复制)

当我们配置好主从同步的时候,由于之前没有进行过任何同步,所以首先会进行一次全量数据同步到从库。

  • 建立连接

Slave从库会主动和Master主库进行通信,发送psync 命令,该命令会捎带两个参数过去给Master,第一个参数是主库ID(runID),redis 在启动的时候,都会为自己生成一个ID,第二个是Slave复制Maser数据的偏移量offset。
​
Slave第一次和Master进行通信,由于一开始不知道Master的ID,所以传递了 ?;
由于是第一次复制,offset 传递 -1 表示第一次要进行全量复制。
​
接着Master接收到了Slave传递过来的命令以及相应的参数,一看是? 和 -1 ,那么就知道这个Slave要进行全量的复制,Master会给Slave 发送一个 fullresync 命令,告诉Slave接下来要开始全量复制,并带上自己的 ID,Slave 接收到这两个参数后会保存起来。
​
  • 全量复制

master节点收到sync命令后会执行bgsave, fork 子进程开始保存快照(即RDB持久化,主从复制会触发RDB),同时收集所有接收到的用于修改数据集命令缓存起来,master节点执行RDB持久化后,master将rdb快照文件和缓存的命令发送到所有slave,来进行一次完全同步
而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中(slave自己原有的数据会提前清空),从而完成复制初始化
  • 心跳持续,保持通信

repl-ping-replica-period 10
master发出PING包的周期,默认是10秒

进入平稳,增量复制

master 继续将新的所有收集到的修改命令自动一次传给slave,完成同步

从机下线,重连续传

master 会检查backlog里面的offset,master和slave都会保存一个复制的offset并带有一个masterId(runID)
offset 是保存在backlog 中的。master只会把已经复制的offset后面的数据赋值给slave,类似断点续传

缺点

  1. 由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。

  2. master宕机,slave不能自动切换成master,需要手动

7.2 哨兵模式

哨兵的四个功能

主从监控:监控主从redis库运行是否正常
消息通知:哨兵可以将故障转移的结果发送到客户端,客户端通过连接哨兵来获得当前Redis服务的主节点地址
故障转移:如果master异常,则会进行主从切换,将其中一个slave作为新master
使用建议
  • 哨兵节点的数量应为多个,哨兵本身应该集群,保证高可用

  • 哨兵节点的数量应该是奇数个

  • 各个哨兵节点的配置应该一致

  • 如果哨兵节点部署在Docker等容器里,要注意端口的正确映射

  • 哨兵集群+主从复制,并不能保证数据零丢失

说明)

搭建三个哨兵
       192.168.100.101     
       192.168.100.102
       192.168.100.103

步骤1)拷贝一份哨兵配置文件到bin目录下

[root@youcai01 redis]# cp ./sentinel.conf ./bin/
[root@youcai01 redis]# cd bin/
[root@youcai01 bin]# ll
-rw-r--r--. 1 root root    14700 11月  4 13:48 sentinel.conf

步骤2)修改配置文件

[root@youcai01 ~]# vim /usr/local/redis/bin/sentinel.conf
protected-mode no
port 26379
#设置后台启动,   想要查看信息,可以去日志文件中查看
daemonize yes
pidfile /var/run/redis-sentinel.pid
# 如果设置了具体的日志路径,那么前台进程的滚动信息都在日志文件中,  可以设置成后台进程,来解放命令行
logfile "/var/log/sentinel.log"
dir /usr/local/redis/tmp
#设置要监控的redis master,2表示最少有几个哨兵认可客观下线,同意故障迁移的法定票数
sentinel monitor mymaster 192.168.100.101 6379 2
#sentinel访问master密码
sentinel auth-pass mymaster 123456

步骤3)剩下的两台机器,也是这样的配置

[root@youcai01 bin]# scp /usr/local/redis/bin/sentinel.conf youcai02:/usr/local/redis/bin/
[root@youcai01 bin]# scp /usr/local/redis/bin/sentinel.conf youcai03:/usr/local/redis/bin/

步骤4)启动哨兵

注意,主从机器的配置中也要添加

masterauth  123456

先恢复主从机器,使用info replication查看是否正确

myRedisServer.sh start
myRedisServer.sh start
myRedisServer.sh start

然后启动哨兵,演示自动切换吧,

[root@youcai01 bin]# redis-sentinel /usr/local/redis/bin/sentinel.conf
[root@youcai02 bin]# redis-sentinel /usr/local/redis/bin/sentinel.conf
[root@youcai03 bin]# redis-sentinel /usr/local/redis/bin/sentinel.conf

演示故障转移

将master杀死, 稍等片刻,查看哨兵日志,应该会发现某一个slave变成了master.

哨兵的工作方式

Sentinel的工作方式:
​
1):每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令。
​
2):如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。 
​
3):如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。 
​
4):当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线 。
​
5):在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令 。
​
6):当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次 。
​
7):若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。 
​
若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。

选举原理

1. 先看优先级,谁高谁当master(数字越小,优先级越高)
    736 # By default the priority is 100.
     737 replica-priority 100
2. 优先级一样的话,就看偏移量offset,谁的数据最新,谁就当master
3. offset一样的话,runid,谁的最小,谁当master

客观下线时:选举哨兵中的一个领导者,并由该领导者节点进行去通知slave进行failover(故障迁移)

7.3 Redis的集群

7.3.1 简介

1. Redis的集群模式,指的是有多个Master,注意:Master可以有0到多个slave。
2. 集群节点之间的通信机制:ping-pong通信
3. 客户端在连接集群时,如果是写操作,只需要连接上任意一个master即可,如果是读操作,只需要连接集群上的任意一个节点即可(slave或者master)
4. 数据存在集群中的槽中,槽的数量是固定的,16384个。槽是有编号的:0-16383,数据调用key与16384取余,余数就是槽号。
   HASH_SLOT = CRC16(key) mod 16384
​
5. 集群的不可用情况:
    -- 半数以上的master宕机,集群不可用
    -- master和对应的slave都宕机了,集群不可用
    
    
    3-master  
    3-slave
    
注意:
    --槽的编号之间不能断开。
    --槽的计算会将数据保存的很平均,不会产生一个槽满一个槽空的情况。
​
生产环境中,每个master至少要有一个slave。

7.3.2 集群搭建

1)说明
1. redis在搭建集群时,版本不同所需要的环境不同。
2. redis3.0版本,对ruby版本环境没要求   
    redis4.x版本,需要ruby环境高于2.2.2      # ruby -v  查询ruby的版本
   redis5.x版本,内置了ruby,不需要操作ruby环境
   
基于上述情况:我们用redis7.2.6来演示redis集群的搭建, 
​
192.168.100.101  master 7001  slave 7002
192.168.100.102  master 7001  slave 7002
192.168.100.103  master 7001  slave 7002
2)搭建步骤

步骤1)上传、解压、编译、安装维护六个实例的目录

[root@youcai01 ~]# tar -zxvf redis-7.2.6.tar.gz -C /usr/local/
[root@youcai01 ~]# cd /usr/local/redis-7.2.6
[root@youcai01 ~]# ln -s  /usr/local/redis-7.2.6  /usr/local/redis
[root@youcai01 ~]# cd /usr/local/redis/
[root@youcai01 redis]# make && make install PREFIX=/usr/local/redis
[root@youcai01 redis]# cp redis.conf ./bin/redis7001.conf 
[root@youcai01 redis]# cp redis.conf ./bin/redis7002.conf 
[root@youcai01 redis]# 

步骤2)修改配置文件redis7001.conf……..

先拷贝一个配置文件,修改下面的参数
[root@youcai01 redis]# vim ./bin/redis7001.conf 
#启动后台进程
daemonize yes  
#修改pid文件的位置
pidfile /var/run/redis_7001.pid
​
logfile "/var/log/redis7001.log"
#端口号
port 7001
#持久化的位置
dir "/usr/local/redis/mydata"
# 开启aof
appendonly yes
# 密码策略
requirepass 123456
masterauth 123456
​
#解开注释,启用集群模式
cluster-enabled yes
 #集群的配置文件
cluster-config-file nodes-7001.conf
 #集群的连接超时时间
cluster-node-timeout 5000

再复制修改

[root@youcai01 bin]# cp redis7001.conf redis7002.conf
[root@youcai01 bin]# vim redis7002.conf <======= 修改了四个地方 与端口号有关的地方

[root@youcai01 bin]# scp redis700* youcai02:$PWD
[root@youcai01 bin]# scp redis700* youcai03:$PWD

步骤3)启动六个实例,默认都是master状态,还不是集群

[root@youcai01 bin]# /usr/local/redis/bin/redis-server  /usr/local/redis/bin/redis7001.conf

#检查进程
[root@youcai01 bin]# ps -ef| grep redis
root      44546      1  0 15:27 ?        00:00:00 /usr/local/redis/bin/redis-server *:7001 [cluster]
root      44606      1  0 15:27 ?        00:00:00 /usr/local/redis/bin/redis-server *:7002 [cluster]

步骤4)创建集群:

#   --cluster-replicas 1 表示为每个master创建一个slave节点
​
[root@youcai01 mydata]# redis-cli -a 123456 --cluster create --cluster-replicas 1 192.168.100.101:7001 192.168.100.102:7001 192.168.100.103:7001 192.168.100.101:7002 192.168.100.102:7002 192.168.100.103:7002
​

-------------------到此为止,安装成功,愉快的玩耍吧----------------------

连接集群客户端操作:

redis-cli -c  -p 7001     注释:-c 表示连接集群中的某一个节点
​
​
#查看节点信息
cluster nodes
#查看集群信息
cluster info
#查看当前节点主从关系
info replication
​
#查看指定key所在的slot
cluster keyslot name1

如果安装过程中出错了,怎么办

1. 找到配置的位置,修改相应的错误地方
2. 关闭或杀死各个实例
3. 删除各个实例里的持久化文件(dump.rdb,appendonly.aof)和集群配置文件(nodes-700x.conf)
4. 重启各个实例的服务器
5. 再次创建关联。

7.2.3 代码演示

package com.qf.redis.day01
​
import java.util
​
import redis.clients.jedis.{HostAndPort, JedisCluster}
​
​
object _08ClusterConnectDemo {
    def main(args: Array[String]): Unit = {
        //创建一个集群,存储集群的实例
        val sets = new util.HashSet[HostAndPort]()
        sets.add(new HostAndPort("qianfeng01",7001))
        sets.add(new HostAndPort("qianfeng01",7002))
        sets.add(new HostAndPort("qianfeng01",7003))
        //创建JedisCluster对象, 就是一个客户端
        val cluster = new JedisCluster(sets)
        //设置kv对象
        cluster.set("user1","zhangdasan")
        cluster.hset("user2","username","zhangxiaosan")
        cluster.lpush("scores","10","20","30")
        cluster.sadd("names","xiaozhang","xiaohei","xiaohong")
​
        cluster.close()
    }
}

http://www.kler.cn/a/391683.html

相关文章:

  • 2411C++,C++26反射示例
  • Spring Cloud Contract快速入门Demo
  • 10款翻译工具实践体验感受与解析!!!!!
  • 「数据要素」行业简报|2024.11.上刊
  • Vite初始化Vue3+Typescrpt项目
  • 红帽认证和华为认证哪个好?看完这4点你就明白了
  • LayUI组件国际化多国语言版本脚本-下篇根据语种替换
  • idea的mapper.xml文件里写sql语句出现Tag name expected错误提示
  • hadoop健康舆情研究-计算机毕业设计源码05954
  • 【计网】实现reactor反应堆模型 --- 处理数据发回问题 ,异常处理问题
  • TTL电平是什么?
  • PCL 点云分割 分割多个平面
  • 【软考】系统分析师第二版 新增章节 第20章微服务系统分析与设计
  • HTTP的诞生:它解决了哪些网络通信难题?
  • 如何下载西瓜视频没有水印
  • 2024年Postman 下载安装的详细图文教程
  • 【SpringMVC】——Cookie和Session机制
  • 【面试分享】xshell连接Linux服务器22端口执行命令top期间的技术细节和底层逻辑
  • CV图像处理小工具——语义分割json生成检测框json
  • Windows 安装和配置虚拟机
  • python爬虫(二)爬取国家博物馆的信息
  • 使用nossl模式连接MySQL数据库详解
  • 2024 年 10 款替代 Postman 的工具,有免费有开源
  • 我来讲一下-Service Mesh.
  • 【Linux】网络编程3
  • 计算机网络之会话层