Redis管道、主从架构、哨兵架构

Redis主从架构

主库数据更新后,根据配置和策略,自动同步到从库(备份机),这就master/slaver机制,master主库写为主;slaver从库以读为主。
在这里插入图片描述

作用

1)读写分离:master以写为主,slave以读为主。
2)容灾恢复:由于slaves的数据是master的副本,无论是master还是slaves宕机了都能让数据得到有效的回复。

redis主从架构搭建

  1. 配置从节点步骤
1、复制一份redis.conf文件

2、将相关配置修改为如下值:
port 6380
pidfile /var/run/redis_6380.pid  # 把pid进程号写入pidfile配置的文件
logfile "6380.log"
dir /usr/local/redis-5.0.3/data/6380  # 指定数据存放目录
# 需要注释掉bind
# bind 127.0.0.1(bind绑定的是自己机器网卡的ip,如果有多块网卡可以配多个ip,代表允许客户端通过机器的哪些网卡ip去访问,内网一般可以不配置bind,注释掉即可)

3、配置主从复制
replicaof 192.168.0.60 6379   # 从本机6379的redis实例复制数据,Redis 5.0之前使用slaveof
replica-read-only yes  # 配置从节点只读

4、启动从节点
redis-server redis.conf

5、连接从节点
redis-cli -p 6380

6、测试在6379实例上写数据,6380实例是否能及时同步新修改数据

7、可以自己再配置一个6381的从节点

Redis主从工作原理

如果master配置了一个slave,不管是否是第一次连接上Master,他都会发送一个PSYNC命令给master请求复制数据。
master收到PSYNC命令后,会在后台持久化通过bgsave生成那一时刻的数据快照RDB文件,同时会接收新的请求,它会把这些可能修改数据集的请求缓存在内存汇总。当master持久化结束后,会把RDB文件通过网络Socket发送给slave,slave会把接收到的数据持久化生成RDB,然后再加载到内存中,然后,master再将缓存在内存中的命令发送给slave;

如果master由于某些原因和slave断开,slave能自动重连Master,如果master收到slave并发连接请求,他只会持久化一次,而不是一个连接一次,然后再把这一份持久化的RDB数据发给多个并发连接的slave;

全量复制

主从复制(全量复制)流程图:
在这里插入图片描述
注意:master进行bgsave生成RDB文件,这个过程我们并不需要去开启RDB持久化方式、既不用在配置文件中将RDB的配置启动,这是redis内部代码写死了的。

数据部分复制(增量复制)

当slave 挂了之后,与master重连,redis支持部分数据复制的命令PSYNC去master同步数据,slave与master能够在网络连接断开重连后,只进行部分数据复制(断点续传);
master会在其内存里创建一个复制数据用的缓存队列,缓存最近一段时间执行的命令,master和他所有的slave都维护了复制数据的下标offset和master的进程ID,因此当网络连接断开后,salve会请求master继续进行未完成的数据进行复制,从所记录的数据下标开始。
在这里插入图片描述
注意:

  • 由于master的缓存命令空间不大,就只有1M,如果主机一直写命令进缓冲区中,直到写满了。而从机slave挂太久了,而主机把缓冲区写满,又将老的写命令会刷掉,这样从机可能就找不到挂之前的位置。就算找到了,这个位置未必就是挂之前的位置。因此会进行一次全量复制。

  • 或者master进程的ID发生变化(master也挂了,重启的进程就不一样了),也只能进行一次全量复制。

  • 问题:从库80和81是原地待命等待与主库重新连接还是从库咸鱼翻身由从变主?

  • 答案:主机宕机后,从机原地待命,从库和主库的连接状态为down,等待与主库的重连.

主从复制之薪火相传

在这里插入图片描述
80作为79的slave,并拥有79的数据副本,同时80也是81的master,81拥有80的数据副本(也是79的副本),数据从79传输到80,又由80传输到81,脉脉相传。80即作为master,同时也是slave。

  • 80是79的从机,是81的主机,那80的身份?
  • info replication
    -

一主多从架构优化

如果master有太多的slave结点,如果多个从节点同时复制主节点的数据、那么master就需要将RDB数据发送到各个从节点,这样就会导致主从复制风暴,master压力太大,大部分时间都用去发送数据给slave结点。

解决方法:可以让部分从节点与从节点同步数据;
在这里插入图片描述

哨兵模式

  • 哨兵不提供读写服务,主要用来监控redis实例接地那。
  • 哨兵模式下,client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问redis主节点。
  • 当redis主节点发生变化,哨兵第一时间感知到,并且将新的redis主节点通知给client端(这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)
  • 哨兵模式能够在后台监控主库如果出现故障,根据投票自动从从库中推选一个主库,并且其他从库以新的主库为master。

redis哨兵架构搭建步骤

1、复制一份sentinel.conf文件
cp sentinel.conf sentinel-26379.conf

2、将相关配置修改为如下值:
port 26379
daemonize yes
pidfile "/var/run/redis-sentinel-26379.pid"
logfile "26379.log"
dir "/usr/local/redis-5.0.3/data"
# sentinel monitor <master-redis-name> <master-redis-ip> <master-redis-port> <quorum>
# quorum是一个数字,指明当有多少个sentinel认为一个master失效时(值一般为:sentinel总数/2 + 1),master才算真正失效
sentinel monitor mymaster 192.168.0.60 6379 2  
 # mymaster这个名字随便取,客户端访问时会用到

3、启动sentinel哨兵实例
src/redis-sentinel sentinel-26379.conf

4、查看sentinel的info信息
src/redis-cli -p 26379
127.0.0.1:26379>info
可以看到Sentinel的info里已经识别出了redis的主从

5、可以自己再配置两个sentinel,端口26380和26381,注意上述配置文件里的对应数字都要修改

sentinel集群都启动完毕后,会将哨兵集群的元数据信息写入所有sentinel的配置文件里去(追加在文件的最下面),我们查看下如下配置文件sentinel-26379.conf,如下所示:

sentinel known-replica mymaster 192.168.0.60 6380 #代表redis主节点的从节点信息
sentinel known-replica mymaster 192.168.0.60 6381 #代表redis主节点的从节点信息
sentinel known-sentinel mymaster 192.168.0.60 26380 52d0a5d70c1f90475b4fc03b6ce7c3c56935760f  #代表感知到的其它哨兵节点
sentinel known-sentinel mymaster 192.168.0.60 26381 e9f530d3882f8043f76ebb8e1686438ba8bd5ca6  #代表感知到的其它哨兵节点

当redis主节点如果挂了,哨兵集群会重新选举出新的redis主节点,同时会修改所有sentinel节点配置文件的集群元数据信息,比如6379的redis如果挂了,假设选举出的新主节点是6380,则sentinel文件里的集群元数据信息会变成如下所示:

sentinel known-replica mymaster 192.168.0.60 6379 #代表主节点的从节点信息
sentinel known-replica mymaster 192.168.0.60 6381 #代表主节点的从节点信息
sentinel known-sentinel mymaster 192.168.0.60 26380 52d0a5d70c1f90475b4fc03b6ce7c3c56935760f  #代表感知到的其它哨兵节点
sentinel known-sentinel mymaster 192.168.0.60 26381 e9f530d3882f8043f76ebb8e1686438ba8bd5ca6  #代表感知到的其它哨兵节点

同时还会修改sentinel文件里之前配置的mymaster对应的6379端口,改为6380

sentinel monitor mymaster 192.168.0.60 6380 2

在我们Java项目中,哨兵模式下,master挂了,这时候客户端发送请求,这时候会报错,无法执行请求,因为哨兵通过选举算法选举出master的过程需要耗费一点时间。

不开启持久化的主Redis存在的问题

  1. 设置节点A为主服务器,关闭持久化,节点B和C从节点A复制数据。
    这时出现了一个崩溃,但Redis具有自动重启系统,重启了进程,因为关闭了持久化,节点重启后只有一个空的数据集。
  2. 节点B和C从节点A进行复制,现在节点A是空的,所以节点B和C上的复制数据也会被删除。
  3. 当在高可用系统中使用Redis Sentinel,关闭了主服务器的持久化,并且允许自动重启,这种情况是很危险的。
  4. 比如主服务器可能在很短的时间就完成了重启,以至于Sentinel都无法检测到这次失败,那么上面说的这种失败的情况就发生了。

注意:如果数据比较重要,并且在使用主从复制时关闭了主服务器持久化功能的场景中,都应该禁止实例自动重启。

StringRedisTemplate与RedisTemplate详解

spring 封装了 RedisTemplate 对象来进行对redis的各种操作,它支持所有的 redis 原生的 api。在RedisTemplate中提供了几个常用的接口方法的使用,分别是:

private ValueOperations<K, V> valueOps;
private HashOperations<K, V> hashOps;
private ListOperations<K, V> listOps;
private SetOperations<K, V> setOps;
private ZSetOperations<K, V> zSetOps;

RedisTemplate中定义了对5种数据结构操作

redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForHash();//操作hash
redisTemplate.opsForList();//操作list
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set
  • StringRedisTemplate继承自RedisTemplate,也一样拥有上面这些操作。
  • StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。
  • RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。

管道(Pipeline)

  • 客户端可以一次性发送多个请求而不用等待服务器的响应,待所有命令都发送完后再一次性读取服务的响应,这样可以极大的降低多条命令执行的网络传输开销,管道执行多条命令的网络开销实际上只相当于一次命令执行的网络开销。
  • 需要注意到是用pipeline方式打包命令发送,redis必须在处理完所有命令前先缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多。所以并不是打包的命令越多越好。
  • pipeline中发送的每个command都会被server立即执行,如果执行失败,将会在此后的响应中得到信息;也就是pipeline并不是表达“所有command都一起成功”的语义,管道中前面命令失败,后面命令不会有影响,继续执行。
  • 没有保证原子性

Redis Lua脚本

  1. 减少网络开销:本来5次网络请求的操作,可以用一个请求完成,原先5次请求的逻辑放在redis服务器上完成。使用脚本,减少了网络往返时延。这点跟管道类似。
  2. 原子操作:Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。管道不是原子的,不过redis的批量操作命令(类似mset)是原子的。
  3. 替代redis的事务功能:redis自带的事务功能很鸡肋,而redis的lua脚本几乎实现了常规的事务功能,官方推荐如果要使用redis的事务功能可以用redis lua替代。

不要在Lua脚本中出现死循环和耗时的运算,否则redis会阻塞,将不接受其他的命令, 所以使用时要注意不能出现死循环、耗时的运算。redis是单进程、单线程执行脚本。管道不会阻塞redis。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值