Redis高可用和持久化

一、Redis高可用

 在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。
但是在Redis语境中,高可用的含义似乎要宽泛一些,除了保证提供正常服务(如主从分离、快速容灾技术),还需要考虑数据容量的扩展、数据安全不会丢失等。

在Redis中,实现高可用的技术主要包括持久化、主从复制、哨兵和 Cluster集群,,作用如下:

持久化:持久化是最简单的高可用方法(有时甚至不被归为高可用的手段),主要作用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失。
主从复制:主从复制是高可用Redis的基础,哨兵和集群都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。缺陷:故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的限制。
哨兵:在主从复制的基础上,哨兵实现了自动化的故障恢复。缺陷:写操作无法负载均衡;存储能力受到单机的限制。
Cluster集群:通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。

二、持久化

持久化是redis当中一个非常重要的功能,因为redis是一个基于内存的数据库,如果没有持久化,一旦关机或者重启,之前所有的数据都会丢失,这对一个数据库来说是非常致命的,持久化就是为解决这个问题而诞生了

1.redis持久化方式

1.1 RDB(Redis DataBase)方式

RDB 是 Redis 默认的持久化方式,通过定期将内存中的数据以二进制的形式保存到磁盘上的RDB文件中,实现数据的持久化。这个过程可以通过Redis服务器自动触发(例如通过save配置指令设置触发条件),也可以手动执行(通过bgrewriteaof命令)。

RDB 文件是经过压缩的二进制文件,便于备份和恢复,同时加载速度快,但可能会丢失最后一次触发快照后到Redis宕机之间这段时间的数据。

1.2 AOF (Append Only File) 持久化

AOF 持久化则是将每一次对Redis服务器的写操作以Redis协议的格式追加到一个单独的日志文件(也就是AOF文件)中。相比RDB,AOF提供了更高的数据安全性,因为它的持久化粒度更细,理论上可以达到每一笔写操作都不会丢失的程度。

AOF 文件随着时间推移会不断增大,Redis 提供了AOF重写机制(bgrewriteaof命令触发),用来压缩AOF文件,去掉无效的命令和合并连续的写操作。

AOF模式可以配置不同的同步策略,包括“每条命令都同步”、“每秒同步一次”和“在写入后至少等待指定数量的写操作再同步”。

2.持久化过程

AOF 持久化则是将每一次对Redis服务器的写操作以Redis协议的格式追加到一个单独的日志文件(也就是AOF文件)中。相比RDB,AOF提供了更高的数据安全性,因为它的持久化粒度更细,理论上可以达到每一笔写操作都不会丢失的程度。

AOF 文件随着时间推移会不断增大,Redis 提供了AOF重写机制(bgrewriteaof命令触发),用来压缩AOF文件,去掉无效的命令和合并连续的写操作。

AOF模式可以配置不同的同步策略,包括“每条命令都同步”、“每秒同步一次”和“在写入后至少等待指定数量的写操作再同步”。
 

1.RDB持久化过程

1.1 触发RDB持久化

RDB持久化可以通过配置文件中的save指令自动触发,例如当满足一定条件(如过去5分钟内有10个key发生变化)时,Redis会自动执行一次快照操作。也可以通过手动执行SAVE或BGSAVE命令触发。SAVE命令会阻塞Redis服务器直到RDB文件创建完成,而BGSAVE命令会在后台异步执行持久化操作。

1. 2 父进程fork子进程

触发RDB持久化后,父进程会fork一个子进程,这个过程中父进程是阻塞的,不能接受其它的客户端命令

1.3 fork子进程完成

子进程负责将内存中的数据以二进制格式写入到RDB文件中,而主进程继续处理客户端请求。

1.4 子进程生成RDB文件

子进程将数据库中的数据转换为一系列序列化格式的键值对,然后写入磁盘文件。写入完成后,原来的RDB文件(如果存在)会被新的RDB文件替换。

1.5 子进程向父进程发送信号

子进程发送信号给父进程表示完成,父进程更新统计信息
 

2.AOF持久化过程


AOF持久化过程主要包括三个方面,命令追加、文件写入与文件同步、文件重写。

2.1 命令追加

每次客户端发送的写命令在Redis服务器中执行完成后,都会被以Redis协议格式追加到AOF缓冲区,而后统一写入到磁盘当中。主要是为了防止每次写命令都直接继续如磁盘,导致磁盘IO负载过高。造成瓶颈

2.2 文件写入与文件同步

启用AOF持久化后,Redis会将所有的写命令追加到AOF文件的末尾,可以配置不同的同步策略(always、everysec、no)来平衡数据安全性和性能。根据配置的同步策略,Redis会在命令执行完成后立即(always)、每秒(ecerysec)或在操作系统缓冲区满时(no)将命令刷入磁盘。

appendfsync always

设置为 always 表示每次Redis接收到写命令后,都会调用操作系统提供的 fsync() 或类似函数强制将AOF缓冲区的内容同步到磁盘中。这种方式能够确保每个写命令都立即被持久化,因此在Redis服务器崩溃的情况下,数据丢失的可能性最小。但是,频繁的同步操作会显著降低Redis的性能,因为它涉及到磁盘I/O操作,而磁盘I/O通常比内存操作要慢得多。

appendfsync everysec

这是Redis AOF的默认设置。在这种模式下,Redis会在每一秒结束时(大约每秒)将AOF缓冲区的内容同步到磁盘。这意味着在最坏情况下,如果Redis在同步后立即崩溃,可能会丢失这一秒内的写操作数据。然而,这种策略在保证数据相对安全的同时,也能保持较好的性能表现。

appendfsync no

当设置为 no 时,Redis不会主动调用同步操作,而是依赖操作系统的缓存策略来决定何时将AOF缓冲区内容刷到磁盘。这种配置下,Redis的写性能将会是最高的,因为它减少了与磁盘交互的频率。然而,这也意味着在服务器突然断电或无预警关机的情况下,可能丢失大量未写入磁盘的数据,因此数据安全性极低。

总结来说,appendfsync 的不同设置允许用户在数据安全性和性能之间进行权衡选择。在实际应用中,大多数场景推荐使用 appendfsync everysec 来达到较好的折衷效果。对于极度关注数据安全的应用,可以选择 appendfsync always,但在牺牲性能的前提下;而对于对性能要求极高且能接受一定数据丢失风险的应用,则可考虑 appendfsync no。

2.AOF重写

① 随着AOF文件的持续增长,Redis提供了AOF重写功能(可通过bgrewriteaof命令触发)来压缩AOF文件。

②Redis父进程首先判断当前是否存在正在执行bgsave/bgrewriteaof的子进程,如果存在则bgrewriteaof命令直接返回,如果存在 bgsave命令则等bgsave执行完成后再执行。父进程执行fork操作创建子进程,这个过程中父进程是阻塞的。

③父进程fork后,bgrewriteaof命令返回信息并不再阻塞父进程。而后将所有的命令写入缓冲区,而后根据同步方式追加到AOF文件的末尾,同时命令也进入重写缓冲区

④ 子进程首先生成新的AOF文件,而后向父进程发送信号,更新统计信息

⑤重写缓冲区会遍历内存中的数据构建最小化且有效的命令集合,将这些命令写入新的AOF文件。

新的AOF文件创建完成后,Redis会原子地用新的AOF文件替换旧文件。

重写的作用

将过期的数据不再写入文件,最后一条错误语句不写入

无效的命令不在写入,比如创建set  key value,在后面又执行了del key。这样创建又删除的操作将自动被忽略

将多条命令合并,比如将sadd key_set value1, sadd key_set value2, saddkey_set value3,合并成sadd key_set value1 value2 value3

三、开启持久化

1.开启RDB持久化

需要修改/etc/redis/6379.conf配置文件

#通过配置设置触发
save m n
#自动触发最常见的情况是在配置文件中通过save m n,指定当m秒内发生n次变化时,会触发bgsave。
vim /etc/redis/6379.conf
 
-----219行--以下三个save条件满足任意一个时,都会引起bgsave的调用
save 900 1 :当时间到900秒时,如果redis数据发生了至少1次变化,则执行bgsave
save 300 10 :当时间到300秒时, 如果redis数据发生了至少10次变化,则执行bgsave
save 60 10000 :当时间到60秒时,如果redis数据发生了至少10000次变化, 则执行bgsave
 
-----242行--是否开启RDB文件压缩
rdbcompression yes
 
-----254行--指定RDB文件名
dbfilename dump.rdb
 
-----264行--指定RDB文件和AOF文件所在目录
dir /var/lib/redis/6379

2.开启AOF持久化

Redis服务器默认开启RDB,关闭AOF;要开启AOF,需要在配置文件中配置:

vim /etc/redis/6379.conf
--700行--修改,开启AOF
appendonly yes
--704行--指定A0F文件名称
appendfilename "appendonly.aof"
--796行--是否忽略最后一条可能存在问题的指令
aof-load-truncated yes
 
/etc/init.d/redis_6379 restart   重启服务

重启服务并查看端口是否开启

四、RDB与AOF的优缺点

1.RDB持久化方式的优点与缺点


1.1 优点

性能优异:RDB持久化在生成快照时会对主线程进行fork操作创建一个子进程,子进程完成数据持久化工作,不会阻塞主线程处理客户端请求,故对Redis服务性能影响较小。

数据恢复快:RDB文件是二进制格式的,紧凑且易于加载,Redis在重启时可以直接读取RDB文件恢复数据,速度较快。

易于备份与迁移:RDB文件可以方便地用于备份或迁移到其他Redis服务器,而且由于文件体积相对较小,传输和存储成本较低。

1.2 缺点

数据安全性略低:在发生故障时,最后一次持久化和故障之间的时间段内的数据可能丢失。如果RDB文件生成周期较长,潜在的数据丢失风险就越大。

资源消耗:虽然fork操作在现代操作系统中代价相对较小,但对于大容量数据的Redis实例,fork操作仍可能引起暂时的性能下降和较大的内存开销。

不适合大型在线更新场景:如果应用中有大量的写入操作,且需要非常严格的实时持久化保证,RDB可能不是最佳选择,因为RDB是以周期性快照方式进行持久化的。

2.AOF持久化方式的优点与缺点


2.1 优点

数据安全性高:AOF持久化以命令追加的方式记录,可以设置不同的同步策略(如appendfsync everysec),接近于实时持久化,大大降低了数据丢失的可能性。

容错性强:即便AOF文件损坏,Redis提供了redis-check-aof工具进行修复,可以从中找回大部分数据。

重写功能:缩小文件体积,减少磁盘的空间占用,优化存储效率,提示性能。

精确恢复:AOF记录了所有写操作,因此在Redis重启时可以按照写入命令的顺序逐条执行,精确恢复数据状态。

2.2 缺点

性能损耗:根据不同的同步策略,AOF可能需要频繁地将命令写入硬盘,尤其在always同步策略下,对性能影响较大。

文件体积增长较快:随着写操作的增多,AOF文件会逐渐变大,尽管Redis提供了AOF重写功能(bgrewriteaof)来压缩文件,但仍然需要一定的存储空间。

恢复速度相对较慢:AOF文件在Redis重启时需要逐条执行命令来恢复数据,相比于直接加载RDB文件,恢复速度较慢。

五、性能管理

1.内存碎片

内存碎片(Memory Fragmentation)是指在计算机内存管理中,由于分配和回收内存空间而导致的无法连续使用的内存区域。内存碎片分为两类:

内部碎片(Internal Fragmentation): 当内存分配器为一个程序分配内存时,分配的内存块可能会大于程序实际需要的空间。例如,分配器可能按照固定大小或者页大小分配内存,即使请求的内存小于分配单位大小,也会分配一个完整的单位。这部分分配给程序但未被使用的内存空间就是内部碎片。内部碎片不可用于分配给其他程序,即使它在物理上是可用的。

外部碎片(External Fragmentation): 随着程序的运行和内存的分配与回收,内存中可能会形成许多小的、不连续的空闲区域,虽然这些区域的总和足以满足一个大的内存请求,但由于它们彼此不连续,所以不能被分配给需要大块连续内存空间的程序。这些无法合并使用的空闲区域构成了外部碎片。

内存碎片的存在会降低内存利用率,尤其是在连续内存分配策略中,严重的内存碎片可能导致即使还有足够的内存总量,也无法分配给新的请求,这在资源有限的系统中尤为不利。现代内存管理系统通常会采用各种策略来减少或避免内存碎片,如动态内存分配算法、分页系统和垃圾回收机制等。

2.Redis内存碎片率

内存碎片率是衡量Redis内存利用率的一个关键指标,表示Redis在分配和回收内存过程中未使用的内存空间与已使用内存之间的比例。公式通常定义为 mem_fragmentation_ratio = used_memory_rss / used_memory,

其中

used_memory_rss 是Redis进程在操作系统层面所占用的实际物理内存大小。

used_memory 是Redis为了存储数据所分配的内存总量。

碎片率较高意味着Redis分配了大量的内存但并未完全有效利用,可能是由于Redis在分配内存时倾向于分配整块空间,当存储的数据大小变化时,原有的内存块未被完全填满,形成了碎片。长期的碎片积累可能导致Redis内存效率低下,甚至在达到最大内存限制(maxmemory 设置)时因内存不足引发 OOM 错误

跟踪内存碎片率对理解Redis实例的资源性能是非常重要的:
内存碎片率稍大于1是合理的,这个值表示内存碎片率比较低,也说明 Redis 没有发生内存交换

内存碎片率超过1.5,说明Redis消耗了实际需要物理内存的150%,其中50%是内存碎片率。需要在redis-cli工具上输入shutdown save 命令,让 Redis 数据库执行保存操作并关闭 Redis 服务,再重启服务器。

内存碎片率低于1的,说明Redis内存分配超出了物理内存,操作系统正在进行内存交换。需要增加可用物理内存或减少 Redis 内存占用。

3.Redis内存使用率

内存使用率是指Redis已经使用的内存占总内存(或分配给Redis的最大内存)的比例。虽然Redis本身并不直接显示内存使用率这个百分比,但我们可以通过计算得出大致的使用情况。例如,如果你知道Redis实例的最大可用内存(即maxmemory设定值),则内存使用率可近似表示为 used_memory / maxmemory * 100%

可以使用 info memor命令查看内存使用情况

六、Redis内部Key回收策略

为了管理内存资源并防止内存溢出,Redis提供了多种数据淘汰策略( eviction policies ),当内存达到maxmemory限制时,Redis会根据选择的策略自动删除部分Key以释放内存空间

开启key回收,取消配置文件(通常为/etc/redis/6379.conf)中598行的注释,开启key回收

volatile-lru:仅针对设置了过期时间(TTL)的Key,按照最近最少使用(LRU)算法剔除最久未访问的Key。

allkeys-lru:对所有Key均采用LRU算法剔除。

volatile-ttl:剔除即将过期的Key中,剩余生存时间(TTL)最短的Key。

noeviction:不主动删除任何Key,但在尝试写入新的数据时,如果内存已满,则拒绝执行会导致内存增长的命令。

volatile-random 和 allkeys-random:随机剔除具有过期时间或所有Key中的某个Key。

除了上述策略外,管理员还可以通过手动执行 DEL 或 KEYS 指令配合 UNLINK (非阻塞版本的删除指令)来删除特定Key,以减少内存占用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Pytorch转onnx

pytorch 转 onnx 模型需要函数 torch.onnx.export。 def export(model: Union[torch.nn.Module, torch.jit.ScriptModule, torch.jit.ScriptFunction],args: Union[Tuple[Any, ...], torch.Tensor],f: Union[str, io.BytesIO],export_params: bool True,verbose: bool False…

《QT实用小工具·十六》IP地址输入框控件

1、概述 源码放在文章末尾 该项目为IP地址输入框控件,主要包含如下功能: 可设置IP地址,自动填入框。 可清空IP地址。 支持按下小圆点自动切换。 支持退格键自动切换。 支持IP地址过滤。 可设置背景色、边框颜色、边框圆角角度。 下面…

网址打包微信小程序源码 wap转微信小程序 网站转小程序源码 网址转小程序开发

内容目录 一、详细介绍二、效果展示2.效果图展示 三、学习资料下载 一、详细介绍 我们都知道微信小程序是无法直接打开网址的。 这个小程序源码提供了一种将网址直接打包成微信小程序的方法, 使得用户可以在微信小程序中直接访问这些网址内容。 这个源码没有进行加…

Python3 Ubuntu

一、安装中文输入法 1.sudo apt install ibus-sunpinyin 2.点击右上角输入法,然后点击加号,输入yin添加进来,最后选中输入法即可 二、安装截屏软件 1.sudo apt install gnome-screenshot 三、安装opencv-python 1.pip3 install --upgrade…

第九讲 Join 算法

1. 为什么我们需要 Join 我们对关系数据库中的表【tables】进行规范化【normalize】,这样我们就减少了信息的冗余和浪费的空间,但是现在我们为了可以响应传入的查询【Query】,我们必须把这些分离的东西重新组合在一起,以重建原始…

瑞吉外卖实战学习--15、批量启售和批量禁售

批量启售和批量禁售 前言代码实现 前言 代码实现 通过url我们可以获取到传过来的ids和状态值&#xff0c;现根据状态值查询出来相关数据然后直接附加状态值最后通过updateBatchById来进行修改 PostMapping("/status/{status}")public R<String> updateStatus(…

嵌入式学习48-单片机1

51单片机—————8位单片机 裸机驱动 无系统 linux驱动 有系统 驱动-----反映硬件变化 MCU 微控器 MPU CPU GPU 图像处理 IDE 集成开发环境 peripheral 外设 SOC&#xff1a; system on chip P0&#xff1a;8bit——8个引脚 位运算 & …

彩虹聚合DNS管理系统v1.0全新发布

聚合DNS管理系统&#xff08;https://github.com/netcccyun/dnsmgr&#xff09;可以实现在一个网站内管理多个平台的域名解析&#xff0c;目前已支持的域名平台有&#xff1a;阿里云、腾讯云、华为云、西部数码、CloudFlare。本系统支持多用户&#xff0c;每个用户可分配不同的…

python 01操作符与流程控制

一、算术运算符 , , *, /, %, **, // 二、赋值运算符 , , -, *, /, %, **, // 三、比较运算符 四、逻辑操作符 五、变量与赋值 赋值运算符是 &#xff0c;与比较运算符 进行区分 需要注意的是&#xff0c;python的变量是不可变对象&#xff0c;如果变量的值发生改变&…

[AIGC] Spring Interceptor 拦截器详解

文章目录 什么是Spring Interceptor如何使用Spring InterceptorSpring Interceptor的影响 什么是Spring Interceptor Interceptor&#xff08;拦截器&#xff09;是Spring MVC框架中的一种特性&#xff0c;类似于Servlet开发中的Filter&#xff08;过滤器&#xff09;&#xf…

【PyQt5篇】使用QtDesigner添加控件和槽

文章目录 &#x1f354;使用QtDesigner进行设计&#x1f6f8;在代码中添加信号和槽 &#x1f354;使用QtDesigner进行设计 我们首先使用QtDesigner设计界面 得到代码login.ui <?xml version"1.0" encoding"UTF-8"?> <ui version"4.0&q…

Java_18 字符串中的单词反转

字符串中的单词反转 你在与一位习惯从右往左阅读的朋友发消息&#xff0c;他发出的文字顺序都与正常相反但单词内容正确&#xff0c;为了和他顺利交流你决定写一个转换程序&#xff0c;把他所发的消息 message 转换为正常语序。 注意&#xff1a;输入字符串 message 中可能会…

移动端适配方案总结之vw

1、vw/vh是什么&#xff1f; vw是&#xff1a;viewport width 视口宽度单位 vh是&#xff1a; viewport height 视口高度单位 实际开发中我们基本用vw&#xff1b; 2.相对视口的尺寸计算结果 1vw 1/100视口宽度 1vh 1/100视口高度 例如&#xff1a; 当前屏幕视口是 375像素…

数据结构---顺序表实现

目录 1.顺序表 2.动态顺序表的实现 &#xff08;4&#xff09;顺序表初始化 &#xff08;5&#xff09;顺序表销毁 &#xff08;6&#xff09;顺序表的插入 a.尾插 b.头插 &#xff08;7&#xff09;顺序表的删除 a.尾删 b.头删 &#xff08;8&#xff09;指定位置之…

【大数据存储】spark-编程

实验8-spark编程 实验&#xff1a;编写Spark应用程序&#xff08;掌握Spark应用程序的编写、编译打包和运行方法&#xff09; 1、对于两个输入文件A和B&#xff0c;编写Spark独立应用程序&#xff0c;对两个文件进行合并&#xff0c;并剔除其中重复的内容&#xff0c;得到一个…

VSCode如何调试C#代码?

1、启动VSCode&#xff1b; 一、创建项目 1、创建一个文件夹(workspace)&#xff1a; 2、进入这个文件夹 cd tt1 3、创建解决方案 dotnet new sln -o MyApp 4、进入解决方案 cd .\MyApp\ 5、创建项目&#xff08;在此假定为一个命令行的项目&#xff09; dotnet new …

例47:键盘事件演示

建立一个EXE工程&#xff0c;在默认窗体上放一个Image框和一一个text框。在text的按键事件中输入代码&#xff1a; Function Form1_Text1_WM_KeyDown(hWndForm As hWnd, hWndControl As hWnd,nVirtKey As Long, lKeyData As Long) As LongIf nVirtKey VK_SPACE ThenImage1.Pi…

Django的html在for遍历后显示“一、二、三...”和“1,2,3...”分级标题

例如当天的html为&#xff1a; {% load static %} {% csrf_token %} <!DOCTYPE html> <html> <head><title>生活规划师</title><link rel"stylesheet" href"{% static css/LifePlanningGuide.css %}"><script src…

FreeRtos入门-7 中断管理

中断管理 中断管理相比非中断的优势 1&#xff0c;简洁和效率。 2&#xff0c;同步和安全。提供了中断安全的操作&#xff0c;确保在中断上下文中执行时不会引发竞态条件或破坏系统状态。 3&#xff0c;通过配置中断的优先级&#xff0c;可以确保高优先级的中断能够立即响应…

AI跟踪报道第36期-新加坡内哥谈技术-这周的AI新闻铺天盖地

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…