Redis主从同步、哨兵、集群

2021年11月23日 阅读数:3
这篇文章主要向大家介绍Redis主从同步、哨兵、集群,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

什么是主从同步(复制)

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

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

主从复制的做用

  1. 数据冗余:主从复制实现了数据的热备份,是持久化以外的一种数据冗余方式。
  2. 故障恢复:当主节点出现问题时,能够由从节点提供服务,实现快速的故障恢复;其实是一种服务的冗余。
  3. 负载均衡:在主从复制的基础上,配合读写分离,能够由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用链接主节点,读Redis数据时应用链接从节点),分担服务器负载;尤为是在写少读多的场景下,经过多个从节点分担读负载,能够大大提升Redis服务器的并发量。
  4. 读写分离:能够用于实现读写分离,主库写、从库读,读写分离不只能够提升服务器的负载能力,同时可根据需求的变化,改变从库的数量;
  5. 高可用基石:除了上述做用之外,主从复制仍是哨兵和集群可以实施的基础,所以说主从复制是Redis高可用的基础。

Redis之主从同步的实现原理

1.当从库和主库创建ms(master和slave)关系后,会向主库发送sync命令。redis

2.收到SYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区记录从如今开始执行的全部写命令。算法

3.当主服务器的BGSAVE命令执行完毕,主服务器将生成的RDB文件发送给从服务器,从服务器接收并加载这个RDB文件,将本身的数据库状态更新至主服务器执行BGSAVE命令时的数据库状态。shell

4.主服务器将记录在缓冲区里面的全部命令发送给从服务器,从服务器执行这些写命令,将本身的数据库状态更新至主服务器当前所处的状态。数据库

命令传播

在同步操做完毕后,主从服务器二者的数据库状态达到一致,可是若是客户端发送写命令给主服务器时,将致使主从服务器状态不一致。ruby

为了让主从服务器数据一致,主服务器须要对从服务器执行命令传播操做:主服务器会将本身执行的那条写命令,发送给从服务器执行,当从服务器执行了该写命令后,主从服务器将再次回到一致状态。服务器

主从同步配置

1.环境准备,运行3个redis数据库,达到 1主 2从的配置架构

主库  6379.conf 
	port 6379
	daemonize yes
	pidfile /data/6379/redis.pid
	loglevel notice
	logfile "/data/6379/redis.log"
	dbfilename dump.rdb
	dir /data/6379

从库 6380
	port 6380
	daemonize yes
	pidfile /data/6380/redis.pid
	loglevel notice
	logfile "/data/6380/redis.log"
	dbfilename dump.rdb
	dir /data/6380
	slaveof  127.0.0.1  6379  # 表示从库,主库为6379
	
从库 6381  
	port 6381
	daemonize yes
	pidfile /data/6381/redis.pid
	loglevel notice
	logfile "/data/6381/redis.log"
	dbfilename dump.rdb
	dir /data/6381
	slaveof  127.0.0.1  6379  # 将这个写入才行

2.开启主从复制功能并发

redis-cli info   #查看数据库信息
redis-cli info replication  # 查看redis的复制受权信息

在6380 和6381数据库上 ,配置主从信息,经过参数形式修改配置,临时生效,注意要写入配置文件 
redis-cli -p 6380 slaveof 127.0.0.1 6379
redis-cli -p 6381 slaveof 127.0.0.1 6379

此时检查6379的复制信息,以及6380 6381的复制信息
redis-cli -p 6380 info replication  # 查看redis的复制受权信息
redis-cli -p 6381 info replication  

主从复制是 读写分离的,master可写,  slave只读

3.模拟主从复制故障,手动切换master-slave身份,low

1.杀死6379进程 ,干掉主库 
	
2.手动切换 6381为新的主库,须要先关闭它的从库身份
redis-cli -p 6381  slaveof no one 

3.修改6380的新主库是 6381
redis-cli -p 6380 slaveof  127.0.0.1 6381

2.8版本后的复制功能

为了解决旧版的问题,Redis2.8之后引入了PSYNC代替SYNC命令执行复制时的同步操做。

PSYNC命令具备彻底同步和部分重同步功能。

彻底同步和旧版的同步是同样的。

部分重同步主要是用于断线后的重复制状况:当从服务器断开从新链接后,若是条件容许,主服务器将断开期间的写命令发给从服务器,从服务器执行断开期间的写命令完成同步,将数据库更新到和主服务器一致。

部分重同步的实现

部分重同步的必备条件

  • 主服务器的复制偏移量和从服务器的复制偏移量。
  • 主服务器的复制积压缓冲区(队列,默认1MB)。
  • 服务器的容许ID。

主服务器和从服务器都会维护一个复制偏移量,主要是用户对比复制的执行结果。例如主从服务器的复制偏移量均为1000,当主服务器完成了3个写命令后,主服务器偏移量为1003,这时候将3个命令给从服务器执行,从服务器执行完毕,复制偏移量也为1003。

若是主从服务器的数据是一致的,那么他们的偏移量也是一致的。

复制积压缓冲区,在主服务器将写命令给从服务器后,还会写入到复制积压缓冲区,若是执行到了偏移量为1003的时候,从服务器A断开,主服务器继续执行了7个写入命令,这时候主服务器的偏移量为1010,A服务器链接上,请求复制主服务器,这时候主服务器会分状况处理。

1)主服务器不是A从服务器以前复制的主服务器(根据服务器ID判断),执行彻底同步。

2)发现A从服务器以前复制的是本身。根据A从服务器的偏移量去复制积压缓冲区中看1004-1010命令是否依然存在,若是存在将1004-1010偏移量的命令返回给A从服务器执行。若是不存在,只能执行彻底同步恢复数据一致了。

Redis哨兵

哨兵的原理

哨兵(sentinel) 是一个分布式系统,你能够在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossipprotocols)来接收关于Master是否下线的信息,并使用投票协议(agreement protocols)来决定是否执行自动故障迁移,以及选择哪一个Slave做为新的Master.

每一个哨兵(sentinel) 会向其它哨兵(sentinel)、master、slave定时发送消息,以确认对方是否”活”着,若是发现对方在指定时间(可配置)内未回应,则暂时认为对方已挂(所谓的”主观认为宕机” Subjective Down,简称sdown)。

若“哨兵群”中的多数sentinel,都报告某一master没响应,系统才认为该master"完全死亡"(即:客观上的真正down机,Objective Down,简称odown),经过必定的vote算法,从剩下的slave节点中,选一台提高为master,而后自动修改相关配置.

虽然哨兵(sentinel) 释出为一个单独的可执行文件 redis-sentinel ,但实际上它只是一个运行在特殊模式下的 Redis 服务器,你能够在启动一个普通 Redis 服务器时经过给定 --sentinel 选项来启动哨兵(sentinel).

redis-sentinel主从复制高可用

环境准备

三个redis数据库实例 ,配置好 1主 2从的配置

	6379.conf
		port 6379
		daemonize yes
		logfile "6379.log"
		dbfilename "dump-6379.rdb"
		dir "/var/redis/data/"

	6380.conf 
		port 6380
		daemonize yes
		logfile "6380.log"
		dbfilename "dump-6380.rdb"
		dir "/var/redis/data/"
		slaveof 127.0.0.1 6379

	6381.conf 
		port 6381
		daemonize yes
		logfile "6381.log"
		dbfilename "dump-6381.rdb"
		dir "/var/redis/data/"
		slaveof 127.0.0.1 6379

三个redis哨兵进程,指定好检测着谁,这里只列出一个

# 对哨兵进行配置,每一个哨兵都要有一个配置
    port 26379   # 端口
	dir /var/redis/data/ # 日志存储位置
	logfile "26379.log"  # 日志文件

	# 当前Sentinel节点监控 192.168.182.130:6379 这个主节点
	# 2表明判断主节点失败至少须要2个Sentinel节点赞成
	# mymaster是主节点的别名
	sentinel monitor mymaster  0.0.0.0 6379 2

	# 每一个Sentinel节点都要按期PING命令来判断Redis数据节点和其他Sentinel节点是否可达,若是超过30000毫秒30s且没有回复,则断定不可达
	sentinel down-after-milliseconds mymaster  20000

	# 当Sentinel节点集合对主节点故障断定达成一致时,Sentinel领导者节点会作故障转移操做,选出新的主节点,原来的从节点会向新的主节点发起复制操做,限制每次向新的主节点发起复制操做的从节点个数为1
	sentinel parallel-syncs mymaster 1

	# 故障转移超时时间为180000毫秒
	sentinel failover-timeout mymaster 180000

分别启动 三个redis数据库, 以及三个 哨兵进程 ,注意 :哨兵第一次启动后,会修改配置文件,若是错了,得删除配置文件,从新写。

redis-server xxx.conf  # 启动数据库
redis-sentinel sentinel-26379.conf  # 启动哨兵

验证哨兵是否正常

redis-cli -p 26379 info sentinel # 验证哨兵是否正常
master0:name=s21ms,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3 # 正常

如今若是主库挂掉,会自动切换设置其余的从库为主库。

redis-cluster集群搭建

并发问题,数据量太大,单个redis内存不足,使用cluster进行分片存储。

redis集群采用P2P模式,是彻底去中心化的,不存在中心节点或者代理节点;

redis集群是没有统一的入口的,客户端(client)链接集群的时候链接集群中的任意节点(node)便可,集群内部的节点是相互通讯的(PING-PONG机制),每一个节点都是一个redis实例;

为了实现集群的高可用,即判断节点是否健康(可否正常使用),redis-cluster有这么一个投票容错机制:若是集群中超过半数的节点投票认为某个节点挂了,那么这个节点就挂了(fail)。这是判断节点是否挂了的方法; 那么如何判断集群是否挂了呢? -> 若是集群中任意一个节点挂了,并且该节点没有从节点(备份节点),那么这个集群就挂了。这是判断集群是否挂了的方法;

那么为何任意一个节点挂了(没有从节点)这个集群就挂了呢? -> 由于集群内置了16384个slot(哈希槽),而且把全部的物理节点映射到了这16384[0-16383]个slot上,或者说把这些slot均等的分配给了各个节点。当须要在Redis集群存放一个数据(key-value)时,redis会先对这个key进行crc16算法,而后获得一个结果。再把这个结果对16384进行求余,这个余数会对应[0-16383]其中一个槽,进而决定key-value存储到哪一个节点中。因此一旦某个节点挂了,该节点对应的slot就没法使用,那么就会致使集群没法正常工做。

由于集群至少有一半以上断定某个节点挂掉,因此节点数至少有三个。

1.经过配置,开启redis-cluster

# redis-7000.conf 
port 7000
daemonize yes
dir "/opt/redis/data"
logfile "7000.log"
dbfilename "dump-7000.rdb

cluster-enabled yes   # 开启集群模式
cluster-config-file nodes-7000.conf # 集群内部的配置文件
cluster-require-full-coverage no  	
	#redis cluster须要16384个slot都正常的时候才能对外提供服务,换句话说,只要任何一个slot异常那么整个cluster不对外提供服务。 所以生产环境通常为no
    
# 6个实例,三个是主节点,三个是从节点,数量为6个节点才能保证高可用的集群。

2.建立6个配置文件,即6各节点,仅仅是端口的区别,内容均如上

[root@yugo /opt/redis/config 17:12:30]#ls
redis-7000.conf  redis-7002.conf  redis-7004.conf
redis-7001.conf  redis-7003.conf  redis-7005.conf

3.启动6个节点,ps查看进程ps -ef|grep redis

 1855  2018-10-24 15:46:01 redis-server redis-7000.conf
 1856  2018-10-24 15:46:13 redis-server redis-7001.conf
 1857  2018-10-24 15:46:16 redis-server redis-7002.conf
 1858  2018-10-24 15:46:18 redis-server redis-7003.conf
 1859  2018-10-24 15:46:20 redis-server redis-7004.conf
 1860  2018-10-24 15:46:23 redis-server redis-7005.conf

4.分配redis slot 槽位

  • 手动写c语言 分配
  • 使用ruby大神 写的一个redis模块,自动分配

5.配置ruby脚本环境

1.yum安装最简单 
	yum install  ruby  

2.自动配置好 PATH环境变量
	ruby和gem的环境变量

3.下载ruby操做redis的模块
	wget http://rubygems.org/downloads/redis-3.3.0.gem   
	
4.用ruby的包管理工具 gem 安装这个模块
	gem install -l redis-3.3.0.gem
5.经过ruby一键分配redis-cluster集群的槽位
找到机器上的redis-trib.rb命令,用绝对命令建立,以下所示:

6.开启集群,分配槽位

/opt/redis-4.0.10/src/redis-trib.rb  create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005

# 1表示1个主库带1个从库

7.启动集群,链接集群节点,链接任意一个便可

redis-cli -p 7001 -c 

注意:必定要加上-c,否则节点之间是没法自动跳转的!

8.登陆redis并写入数据,发现槽位分配,且重定向以后,集群搭建成功

查看集群信息简单命令

1.查看当前集群信息

cluster info

# 集群主节点状态
redis-cli -p 7000 cluster nodes | grep master
# 集群从节点状态
redis-cli -p 7000 cluster nodes | grep slave

2.查看集群里有多少个节点

cluster nodes

redis-cli -p 7000 cluster nodes  # 等同于查看nodes-7000.conf文件节点信息

主从、哨兵、集群做用

redis主从:是备份关系, 咱们操做主库,数据也会同步到从库。 若是主库机器坏了,从库能够上。就比如你 D盘的片丢了,可是你移动硬盘里边备份有。

redis哨兵:哨兵保证的是HA,即保证特殊状况故障自动切换,哨兵盯着你的“redis主从集群”,若是主库死了,它会告诉你新的主库是谁。

redis集群:集群保证的是高并发,由于多了一些兄弟帮忙一块儿扛。同时集群会致使数据的分散,整个redis集群会分红一堆数据槽,即不一样的key会放到不不一样的槽中。

主从保证了数据备份,哨兵保证了HA 即故障时切换,集群保证了高并发性。

上一篇: redis锁操作