Spring Cloud分布式缓存

news2024/11/27 5:24:18

目录

单点Redis

Redis数据持久化

RDB持久化

bgsave细节

RDB的缺点

AOF持久化

AOF的问题

RDB与AOF对比

搭建Redis主从架构

数据同步原理

全量同步

增量同步

主从同步优化

Redis哨兵

集群检测

选举主节点

故障转移

搭建哨兵集群

RedisTemplate的哨兵模式


单点Redis

单点Redis存在如下问题:

  • Redis是内存存储,服务重启可能会造成数据丢失。
  • 并发问题,虽然是内存存储,并发能力很强,但在单节点下,不适用于高并发的场景。
  • 故障恢复问题,Redis服务宕机,导致某些服务不可用。需要一种自动恢复的手段。
  • 存储能力问题,Redis基于内存,单节点的存储数量难以满足海量数据需求。

对应的解决方案:

  • 数据丢失问题:实现Redis数据持久化
  • 并发能力问题:搭建主从集群,实现读写分离
  • 故障恢复问题:利用Redis哨兵,实现健康和自动恢复
  • 存储能力问题:搭建分片集群,利用插槽机制实现动态扩容

Redis数据持久化

一共有两种持久化方式:RDB与AOF

RDB持久化

简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。快照文件成为RDB文件,默认保存在当前运行目录。

执行命令为

save

该命令由Redis主进程去执行,但由于Redis是单线程的,因此在持久化期间,其他所有命令都会被阻塞。一般不推荐这种方式。而推荐下面这个命令

bgsave

开启子进程执行RDB,不影响主进程。

Redis在主动停机前,会自动执行一次RDB。

但是在Redis内部数据比较多的时候,RDB时间可能会很久,在save期间,如果服务宕机,仍然可能导致数据丢失。因此我们可以在配置文件中修改RDB触发机制。

需要注意的是,以上save实际上都是bgsave,如果是 save "",则代表禁用RDB。

其他配置如下

修改RDB触发条件为5秒内至少有一个key被修改后,重启Redis服务,再进行一个添加操作观察redis服务器,会自动进行RDB。

bgsave细节

bgsave是开启一个子进程去对数据进行持久化操作,虽然实现了异步持久化,但是在fork主进程得到子进程期间是一个阻塞式的操作,为了减少阻塞时间,fork底层实现如下。

主进程是无法直接对物理内存进行操作的,开启主进程时,操作系统会对主进程分配一个虚拟内存,并维护页表,而页表中记录了虚拟内存与物理内存的映射关系,主进程开启子进程过程中仅仅是拷贝了一个页表,并不是拷贝了内存中的数据给子进程去做持久化。因此,主进程和子进程实际上共享同一个内存。

共享同一个内存也存在一个缺点,就是在RDB过程中,主进程需要对数据进行修改。这样就造成了读写冲突。为此,fork底层采用了copy-on-write技术:

  • 当主进程执行读操作时,访问共享内存
  • 当主进程执行写操作时,则会拷贝一份数据,执行写操作。

修改数据前,将原有数据拷贝一份后再进行写操作,同时将主进程中的页表映射关系进行修改。

RDB的缺点

  1. RDB执行间隔时间长,两次RDB之间写入数据有丢失风险。
  2. fork子进程,压缩,写出RDB文件都比较耗时。

AOF持久化

Redis处理的每一个写命令都会记录在AOF文件中,可以看做命令日志文件

当服务重启后,会从AOF文件中将所有命令再执行一边。而AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF

三种刷盘机制对比 

配置项

刷盘时机

优点

缺点

Always

同步

可靠性高,几乎不丢失数据

性能影响较大

everysec

每秒刷盘

性能适中

最多丢失1秒数据

no

操作系统控制

性能最好

可靠性较差,可能丢失大量数据

开启AOF功能后,执行一次写操作,观察AOF文件

重启Redis服务,会进行一次DB加载

AOF的问题

AOF会记录所有的写操作,但是对于同一个key,记录多次set操作是无意义的,只需要最后一次的set值就满足了,如果执行了delete操作,那么之前的set操作也无意义。因此可以通过执行bgrewriteaof命令,对AOF文件进行重写。可以通过修改配置文件来控制重写时机

RDB与AOF对比

RDB

AOF

持久化方式

定时对整个内存做快照

记录每一次执行的命令

数据完整性

不完整,两次备份之间会丢失

相对完整,取决于刷盘策略

文件大小

会有压缩,文件体积小

记录命令,文件体积很大

宕机恢复速度

很快

数据恢复优先级

低,因为数据完整性不如AOF

高,因为数据完整性更高

系统资源占用

高,大量CPU和内存消耗

低,主要是磁盘IO资源

但AOF重写时会占用大量CPU和内存资源

使用场景

可以容忍数分钟的数据丢失,追求更快的启动速度

对数据安全性要求较高常见

搭建Redis主从架构

Reids搭建集群主要是为了实现读写分离,由于大多数使用Redis做缓存,因此是读多写少,也就是说,主节点去实现写操作,从节点去实现读操作。

接下来我们在同一台虚拟机上创建3个Redis实例,实现主从集群

#创建3个目录,分别存放不同启动端口的Redis实例
cd /tmp
mkdir 7001 7002 7003
#将redis中的redis.conf文件拷贝到这三个文件当中
# 方式一:逐个拷贝
cp redis-6.2.4/redis.conf 7001
cp redis-6.2.4/redis.conf 7002
cp redis-6.2.4/redis.conf 7003
# 方式二:管道组合命令,一键拷贝
echo 7001 7002 7003 | xargs -t -n 1 cp redis-6.2.4/redis.conf

# 修改配置文件中的启动端口以及文件保存位置
sed -i -e 's/6379/7001/g' -e 's/dir .\//dir \/tmp\/7001\//g' 7001/redis.conf
sed -i -e 's/6379/7002/g' -e 's/dir .\//dir \/tmp\/7002\//g' 7002/redis.conf
sed -i -e 's/6379/7003/g' -e 's/dir .\//dir \/tmp\/7003\//g' 7003/redis.conf

#修改每个实例的声明IP
# 逐一执行
sed -i '1a replica-announce-ip 192.168.150.101' 7001/redis.conf
sed -i '1a replica-announce-ip 192.168.150.101' 7002/redis.conf
sed -i '1a replica-announce-ip 192.168.150.101' 7003/redis.conf
# 或者一键修改
printf '%s\n' 7001 7002 7003 | xargs -I{} -t sed -i '1a replica-announce-ip 192.168.150.101' {}/redis.conf

#启动
redis-server 7001/redis.conf 
redis-server 7002/redis.conf 
redis-server 7003/redis.conf 

接下来搭建主从关系:

临时方式(重启失效)

客户短连接redis服务后,执行slaveof方法

slaveof 主节点ip 主节点端口

永久方式:修改配置文件添加如下配置

slaveof 主节点ip 主节点端口

连接后主节点会打印节点同步信息。将7002、7003将7001作为主节点后,输入如下命令查看集群信息

info replication

测试是否可以同步信息,在7001加入数据,在7002查询数据(在从节点无法写入数据)

数据同步原理

全量同步

主从第一次同步也叫全量同步,具体流程如下

解释:当从节点发起数据同步请求时,主节点会判断该节点是否是第一次进行数据同步,如果是第一次,主节点会返回自己数据的版本信息给从节点保存,同时执行一个bgsave操作,去生成RDB文件后发送给从节点,在生成RDB文件期间会将所有的写操作保存在repl_baklog命令缓冲区。从节点接收到RDB文件后,会清空自身数据后加载RDB文件,加载完成后,主节点会将缓冲区的所有命令发送给从节点去执行,从而保证主从信息保持一致。

master如何判断slave是不是第一次同步数据?

Replication Id:简称replid,是数据集的标记,id一致说明是同一数据集,每一个master都存在唯一的replid,而slave会继承master的id用来识别主从节点属于同一数据集。

offset:偏移量。随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset,如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。

slave做数据同步时,必须向master声明自己的replication id(用来判断是否使用同一个数据集)和offset(用来判断同一个数据集下的同步进度),master才会知道有哪些数据需要同步。

因此第一阶段就变成如下流程

查看Redis服务器打印信息

增量同步

当slave宕机重启后,再次与主节点连接时,进行的是增量同步(局部同步)

解释:slave发送自己的数据集id和偏移量信息给主节点,主节点判断不是第一次连接后,就进行增量同步。将repl_baklog命令缓冲区获取自身偏移量与主节点记录的偏移量之间的数据。

由于repl_baklog的文件大小固定,当写满后,会覆盖最早的数据(可以理解为环形数组)。如果slave断开过久,导致未备份的数据被覆盖,则无法基于repl_baklog做增量同步,只能进行全量同步。

主从同步优化

由于全量同步耗时比较久,因此我们要尽可能的减少Redis进行全量同步的次数

  • 在主节点的配置文件中配置repl-dishless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。简单来说就是在写RDB文件时,不写入磁盘,而是通过网络IO流直接写给从节点(适用于网络带宽快的场景)
  • Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO(数据少,那么IO流传输数据就少)
  • 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
  • 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力

Redis哨兵

Redis哨兵(Sentinel)机制来实现主从集群的自动故障恢复,结构如下:

Redis哨兵作用如下:

  • 监控:Sentinel会不断检查master和slave是否按预期工作。
  • 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主
  • 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端

集群检测

Redis哨兵通常集群搭建,基于心跳检测来监控所有节点的状态,每隔一秒向集群每个节点发送ping,如果超过时间没有接收到响应,则认定为主观下线,如果Redis哨兵集群超过指定数量(建议是节点数量的一半)的节点都没有接收到响应,则认定为客观下线(真的下线了),移除下线节点,如果是主节点宕机,需要及时选举新的主节点。其次就是通知java客户端,告知客户端去访问哪个节点。

选举主节点

当主节点宕机后,需要在slave中选举一个主节点,选举依据:

  • 首先会判断slave结点与master结点断开时间长短,如果超过指定值(down-after-milliseconds),直接排除该slave结点(与主节点断开时间过长,缺失数据过多,不适合选举主节点)
  • 判断slave节点的slave-priority值(配置文件中配置。默认一样),越小优先级越高,如果为0则不参加选举
  • 如果slave-priority一样,则判断slave结点的offset值,越大说明数据越新,优先级越高
  • 最后判断运行id(启动顺序),越小优先级越高

故障转移

当主节点(7001)宕机后,选举slave(7002)为主节点后,故障转移的步骤如下:

  • sentinel给备选节点发送slaveof no one命令,让该节点成为新的master
  • sentinel给其他slave节点发送slaveof 新的主节点ip 新的主节点端口 命令,让其他slave节点成为新的主节点的从节点,开始从新的主节点上同步数据。
  • 将原来的主节点标记为slave(实际上是在配置文件中添加了slaveof命令),再重启后自动成为新的主节点的从节点

搭建哨兵集群

我们还是在同一台虚拟机上去搭建哨兵集群。具体命令如下

# 进入/tmp目录
cd /tmp
# 创建目录
mkdir s1 s2 s3

# 添加配置文件
vi s1/sentinel.conf

配置如下信息

port 27001 #端口后面两个设置为27002 27003
sentinel announce-ip 192.168.150.101 # 声明Sentinel的IP地址
sentinel monitor 集群名称(自定义) 192.168.150.101 7001 2 # 监控主节点的地址 2代表指定的数量来决定节点主观下线
sentinel down-after-milliseconds 集群名称 5000 # 指定slave与master断开超过时间失去选举权
sentinel failover-timeout mymaster 60000 # slave故障恢复的时间
dir "/tmp/s1" # 工作目录

接着配置s2、s3目录下的配置文件

# 方式一:逐个拷贝
cp s1/sentinel.conf s2
cp s1/sentinel.conf s3
# 方式二:管道组合命令,一键拷贝
echo s2 s3 | xargs -t -n 1 cp s1/sentinel.conf

# 修改s2、s3两个文件夹内的配置文件,将端口分别修改为27002、27003
sed -i -e 's/27001/27002/g' -e 's/s1/s2/g' s2/sentinel.conf
sed -i -e 's/27001/27003/g' -e 's/s1/s3/g' s3/sentinel.conf

启动

# 第1个
redis-sentinel s1/sentinel.conf
# 第2个
redis-sentinel s2/sentinel.conf
# 第3个
redis-sentinel s3/sentinel.conf

接下来主动断开7001的服务,模拟主节点宕机。观察哨兵集群打印的消息

去查看7003的打印信息

接着查看sentinel信息

观察7002节点信息

重启7001节点,观察主节点信息

RedisTemplate的哨兵模式

将资料中的redis-demo文件使用IDEA打开

在pom文件中引入redis的starter依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

在配置文件中application.yml中指定sentinel相关信息

spring:
  redis:
    sentinel:
      master: mymaster #指定集群名称
      nodes: # 配置sentinel集群信息
        - 192.168.116.131:27001
        - 192.168.116.131:27002
        - 192.168.116.131:27003

配置读写分离

@Bean
public LettuceClientConfigurationBuilderCustomizer configurationBuilderCustomizer(){
    return configBuilder ->configBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}

这里的ReadFrom是配置Redis的读取策略,是一个枚举类,包括如下选择:

  • MASTER:从主节点读取
  • MASTER_PREFERRED:优先从master节点读取,master不可用才读取replica
  • REPLICA:从slave节点读取
  • REPLICA_PREFERRED:优先从slave节点读取,所有的slave都不可用时才读取master

确保redis集群中存在数据后,启动并访问get/{key}(key为redis中的key名称),并观察控制台

接着执行一次set操作,访问/set/{key}/{value}接口

接下来测试故障转移,将7003宕机,观察sentinel控制台

可以看到又将7001作为主节点了。接下来看到Java客户端又输出很多打印信息

可以看到,Java客户端只需要连接哨兵集群,就可以动态的获取到主节点信息与从节点信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1175137.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Leetcode】【每日一题】【中等】187. 重复的DNA序列 官方题解待更新

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/repeated-dna-sequences/descrip…

C++ AVL树 c语言版本

引入平衡树 假设我们有两个节点&#xff1a;当我们插入第三个节点&#xff0c;就失衡了&#xff1a;此刻我们就要把它平衡一下。 为什么要变平衡 为什么说它失衡了呢&#xff0c;又为什么要把它变平衡&#xff1f; 如图a&#xff0c;假设我们要查找30这个节点就要查3次才能…

耳机,耳麦,傻傻分不清,难怪麦克风没有声音

有时候会发现为什么同一根耳机线&#xff0c;插到笔记本上可以同时说话和收音&#xff0c;但是插到台式机就不行呢&#xff1f; 因为在以前&#xff0c;耳机和麦克风的接口都是独立的&#xff08;如上图&#xff09;。现在笔记本为了方便&#xff0c;就普遍使用了二合一接口&a…

正点原子嵌入式linux驱动开发——Linux 网络设备驱动

网络驱动是linux里面驱动三巨头之一&#xff0c;linux下的网络功能非常强大&#xff0c;嵌入式linux中也常常用到网络功能。前面已经讲过了字符设备驱动和块设备驱动&#xff0c;本章就来学习一下linux里面的网络设备驱动。 嵌入式网络简介 嵌入式下的网络硬件接口 本次笔记…

是时候放弃 Java 序列化了

基本概念 Java 序列化和反序列化三连问&#xff1a; 什么是 Java 序列化和反序列化&#xff1f;为什么需要 Java 序列化和反序列化&#xff1f;如何实现 Java 序列化和反序列化&#xff1f; 是什么 一句话就能够说明白什么是 Java 序列化和反序列化&#xff1f;Java 序列化…

【探索Linux】—— 强大的命令行工具 P.13(文件系统 | 软硬链接 | 动态库和静态库)

阅读导航 引言一、文件系统1. 磁盘文件系统2. 磁盘结构&#xff08;1&#xff09;物理结构&#xff08;2&#xff09;存储结构 3. stat 命令4. Linux ext2文件系统 二、软硬链接1. 软连接2. 硬链接 三、动态库和静态库1. 动态库&#xff08;1&#xff09;动态库文件扩展名&…

计算虚拟化1——CPU虚拟化

目录 vCPU的概念 vCPU和CPU的关系 CPU的Ring级别 CPU虚拟化技术 软件辅助全虚拟化 半虚拟化 硬件辅助虚拟化 计算资源的虚拟化可以分为CPU虚拟化、内存虚拟化、I/O虚拟化三个方面 CPU虚拟化&#xff1a;多个虚拟机共享CPU资源&#xff0c;对虚拟机中的敏感指令进行截获…

【JavaSE】基础笔记 - 类和对象(上)

目录 1、面向对象的初步认知 1.1、什么是面向对象 1.2、面向对象与面向过程 2. 类定义和使用 2.1、简单认识类 2.2、类的定义格式 2.3、自定义类举例说明 2.3.1、定义一个狗类 2.3.2、定义一个学生类 3、类的实例化 3.1、什么是实例化 3.2、类和对象的说明 1、面向…

MySQL性能优化的最佳20条经验

概述 关于数据库的性能&#xff0c;这并不只是DBA才需要担心的事。当我们去设计数据库表结构&#xff0c;对操作数据库时(尤其是查表时的SQL语句)&#xff0c;我们都需要注意数据操作的性能。下面讲下MySQL性能优化的一些点。 1. 为查询缓存优化你的查询 大多数的MySQL服务器…

Python基础入门例程47-NP47 牛牛的绩点(条件语句)

最近的博文&#xff1a; Python基础入门例程46-NP46 菜品的价格&#xff08;条件语句&#xff09;-CSDN博客 Python基础入门例程45-NP45 禁止重复注册&#xff08;条件语句&#xff09;-CSDN博客 Python基础入门例程44-NP44 判断列表是否为空&#xff08;条件语句&#xff0…

ElasticSearch 实现 全文检索 支持(PDF、TXT、Word、HTML等文件)通过 ingest-attachment 插件实现 文档的检索

一、Attachment 介绍 Attachment 插件是 Elasticsearch 中的一种插件&#xff0c;允许将各种二进制文件&#xff08;如PDF、Word文档等&#xff09;以及它们的内容索引到 Elasticsearch 中。插件使用 Apache Tika 库来解析和提取二进制文件的内容。通过使用 Attachment 插件&a…

redis数据库缓存服务器(基础命令)

redis比mysql访问数据快 非关系型数据库以键值对的方式存储数据 作用&#xff1a;加快访问速度&#xff0c;缓解数据库压力 redis最新版本7 特点 丰富的数据结构 list,set,hash等数据结构的存储 支持持久化 支持事务 “一个完整的动作&#xff0c;要么全部执行&#xff0…

数据结构:AVL树讲解(C++)

AVL树 1.AVL树的概念2.平衡因子3.节点的定义4.插入操作5.旋转操作&#xff08;重点&#xff09;5.1左单旋5.2右单旋5.3左右双旋5.4右左双旋 6.一些简单的测试接口7.完整代码 1.AVL树的概念 普通二叉搜索树&#xff1a;二叉搜索树 二叉搜索树虽可以缩短查找的效率&#xff0c;但…

D-Link监控账号密码信息泄露

访问漏洞的 url 为 /config/getuser?index0其中泄露了账号密码 使用泄露的账号密码登陆系统 文笔生疏&#xff0c;措辞浅薄&#xff0c;望各位大佬不吝赐教&#xff0c;万分感谢。 免责声明&#xff1a;由于传播或利用此文所提供的信息、技术或方法而造成的任何直接或间接的…

CCF-CSP真题《202309-3 梯度求解》思路+python,c++满分题解

想查看其他题的真题及题解的同学可以前往查看&#xff1a;CCF-CSP真题附题解大全 试题编号&#xff1a;202309-3试题名称&#xff1a;梯度求解时间限制&#xff1a;1.0s内存限制&#xff1a;512.0MB问题描述&#xff1a; 背景 西西艾弗岛运营公司近期在大力推广智能化市政管理系…

文本生成评估指标简单介绍BLEU+ROUGE+Perplexity+Meteor 代码实现

以下指标主要针对两种&#xff1a;机器翻译和文本生成&#xff08;文章生成&#xff09;&#xff0c;这里的文本生成并非是总结摘要那类文本生成&#xff0c;仅仅是针对生成句子/词的评价。 首先介绍BLEU&#xff0c;ROUGE, 以及BLEU的改进版本METEOR&#xff1b;后半部分介绍P…

volatile-禁重排案例详解

在每一个volatile写操作前面插入一个StoreStore屏障--->StoreStore屏障可以保证在volatile写之前&#xff0c;其前面所有的普通写操作都已经刷新到主内存中。 在每一个volatile写操作后面插入一个StoreLoad屏障--->StoreLoad屏障的作用是避免volatile写与后面可能有的vo…

【Qt之QtXlsx模块】安装及使用

1. 安装Perl&#xff0c;编译QtXlsx源码用 可以通过命令行进行查看是否已安装Perl。 下载及安装传送门&#xff1a;链接: https://blog.csdn.net/MrHHHHHH/article/details/134233707?spm1001.2014.3001.5502 1.1 未安装 命令&#xff1a;perl --version 显示以上是未安装…

测试面试题集-UI自动化测试

1、列举web自动化中常见的元素定位方式&#xff1f; id&#xff1a;根据id来获取元素&#xff0c;返回单个元素&#xff0c;id值一般是唯一的&#xff1b;name&#xff1a;根据元素的name属性定位&#xff1b;tagName&#xff1a;根据元素的标签名定位&#xff1b;className&a…

基于国产仪器的某海上平台SPM振动监测系统

摘要:使用分布式采集仪和云智慧监测系统&#xff0c;实现海上浮式储油轮的单点SPM&#xff08;水上水下有轴承的钢结构&#xff09;振动监测&#xff0c;经受住了湿度高、气温变化大等多变的气候环境的考验。 关键词:石油平台&#xff0c;振动监测&#xff0c;环境 某海上浮式…