Redis高可用技术之持久化

一、Redis高可用

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

        在Redis中,实现高可用的技术主要包括持久化、主从复制、哨兵和Cluster集群四种方法。下面分别说明它们的作用,以及解决了什么样的问题。

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

二、Redis持久化【☆】

持久化的功能:Redis是内存数据库,数据都是存储在内存中,为了避免服务器断电等原因导致Redis进程异常退出后数据的永久丢失,需要定期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘;当下次Redis重启时,利用持久化文件实现数据恢复。除此之外,为了进行灾难备份,可以将持久化文件拷贝到一个远程位置(异地灾备)。

Redis提供两种方式进行持久化:

RDB持久化:原理是将Reids在内存中的数据库记录定时保存到磁盘上。
AOF持久化(append only file):原理是将Reids的操作日志以追加的方式写入文件,类似于MySQL的binlog二进制日志。

由于AOF持久化的实时性更好,即当进程意外退出时丢失的数据更少,因此AOF是目前主流的持久化方式。RDB持久化主要用于在主从复制的场景中。

1)RDB持久化

RDB持久化:定时的将redis在内存中的数据进行快照并压缩保存到硬盘里
手动触发
:bgsave命令 
自动触发:满足配置文件中 save n m 的规则(在n秒内发生了m次数据更新就会自动触发);主从复制在做全量复制时;执行shutdown命令关闭数据库时
工作流程:redis父进程会fork子进程来进行RDB持久化快照保存内存数据到硬盘里,文件名:dump.rdb
优缺点:RDB持久化保存的文件占用空间较小,网络传输快,恢复速度比AOF更快,性能影响比AOF更小;实时性不如AOF,兼容性较差,持久化期间在fork子进程时会阻塞redis父进程

vim /usr/local/redis/conf/redis.conf
--433行--RDB默认保存策略
# save 3600 1 300 10 60 10000
#表示以下三个save条件满足任意一个时,都会引起bgsave的调用
save 3600 1 :当时间到3600秒时,如果redis数据发生了至少1次变化,则执行bgsave
save 300 10 :当时间到300秒时,如果redis数据发生了至少10次变化,则执行bgsave
save 60 10000 :当时间到60秒时,如果redis数据发生了至少10000次变化,则执行bgsave--454行--是否开启RDB文件压缩
rdbcompression yes
--481行--指定RDB文件名
dbfilename dump.rdb
--504行--指定RDB文件和AOF文件所在目录
dir /usr/local/redis/data


2)AOF持久化

AOF持久化:实时的以追加的方式将redis写操作的命令记录到aof文件中
工作流程
:命令追加(将写操作命令追到aof_buf缓冲区),文件写入和同步(文件名:appendonly.aof,同步策略:appendfsync everysec|always|no),文件重写(减少aof文件占用空间的大小和加快恢复速度,定期执行bgrewriteaof命令触发)
优缺点:实时性比RDB更好,支持秒级持久化,兼容性较好;持久化保存的文件占用空间更大,恢复速度更慢,性能影响更大,AOF文件重写期间在fork子进程时也会阻塞redis父进程,且IO压力更大。

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

vim /usr/local/redis/conf/redis.conf
------------------------------------------------------------------------
--1380行--修改,开启AOF
appendonly yes
--1407行--指定AOF文件名称
appendfilename "appendonly.aof"
--1505行--是否忽略最后一条可能存在问题的指令
aof-load-truncated yes
-------------------------------------------------------------------------
systemctl restart redis-server.service

AOF缓存区的同步文件策略

同步方式写入时机优点缺点
appendfsync always每次写入都会同步可靠,数据基本不丢失性能影响大
appendfsync no操作系统控制写会,默认30秒性能好宕机时丢失数据较多
appendfsync everysec每秒同步一次性能适中,数据丢失可控宕机时丢失1秒内数据
appendfsync always :命令写入aof_buf后立即调用系统fsync操作同步到AOF文件,fsync完成后线程返回。这种情况下, 每次有写命令都要同步到AOF文件,硬盘IO成为性能瓶颈 ,Redis只能支持大约几百TPS写入,严重降低了Redis的性能;即便是使用固态硬盘(SSD),每秒大约也只能处理几万个命令,而且会大大降低SSD的寿命。

② appendfsync no: 命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步;同步由操作系统负责,通常同步周期为30秒。这种情况下,文件同步的时间不可控,且缓冲区中堆积的数据会很多,数据安全性无法保证

③ appendfsync everysec: 命令写入aof_buf后调用系统write操作,write完成后线程返回;fsync同步文件操作由专门的线程每秒调用一次。everysec是前述两种策略的折中,是性能和数据安全性的平衡,因此是Redis的默认配置,也是我们推荐的配置。

文件重写触发方式

①手动触发:直接调用bgrewriteaof命令,该命令的执行与bgsave有些类似:都是fork子进程进行具体的工作,且都只有在fork时阻塞。
②自动触发:通过设置auto-aof-rewrite-min-size选项和auto-aof-rewrite-percentage选项来自动执行BGREWRITEAOF。 只有当auto-aof-rewrite-min-size和auto-aof-rewrite-percentage两个选项同时满足时,才会自动触发AOF重写,即bgrewriteaof操作。

  • auto-aof-rewrite-percentage 100:当前AOF文件大小(即aof_current_size)是上次日志重写时AO文件大小(aof_base_size)两倍时,发生BGREWRITEAOF操作
  • auto-aof-rewrite-min-size 64mb:当前AOF文件执行BGREWRITEAOF命令的最小值,避免刚开始启动Reids时由于文件尺寸较小导致频繁的BGREWRITEAOF

但一般情况下建议注释自动重写,而是配合crontab定时使用bgrewrite手动触发。原因时避免白天业务繁忙情况下进行重写,从而影响业务服务器。

三、Redis性能管理和优化

1、查看Redis内存使用

info memory

内存碎片
通过 info memory 命令查看内存的使用情况。
mem_fragmentation_ratio的值如果超过了1.5,建议可以考虑进行内存碎片的清理了。
mem_fragmentation_ratio的值如果小于1,说明物理内存不够真实数据的保存了,此时已经开始使用swap交换空间了,会导致redis性能的严重下降。应该考虑增加物理内存或减少redis内存占用。

config set activedefrag yes    #开启自动内存碎片清理
memory purge                   #手动内存碎片清理
注:由于内存碎片清理是redis主线程执行的,会发生阻塞。因此需要合理配置对应的参数和方式,保证redis的高性能。

2、 内存碎片率

mem_fragmentation_ratio:内存碎片率。                                                              mem_fragmentation_ratio = used_memory_rss / used_memory
used_memory_rss:是Redis向操作系统申请的内存。
used_memory:是Redis中的数据占用的内存。
used_memory_peak:redis内存使用的峰值。

1)内存碎片如何产生的?

        Redis内部有自己的内存管理器,为了提高内存使用的效率,来对内存的申请和释放进行管理。Redis中的值删除的时候,并没有把内存直接释放,交还给操作系统,而是交给了Redis内部的内存管理器。Redis在申请内存的时候,先看自己的内存管理器中是否有足够的内存可用。Redis的这种机制,提高了内存的使用率,但是会使Redis中有部分自己没在用,却不释放的内存,导致了内存碎片的发生。跟踪内存碎片率对理解Redis实例的资源性能是非常重要。

2)内存碎片率 = 已分配的内存 / 实际使用的内存

        内存碎片率在1到1.5之间是正常的,这个值表示内存碎片率比较低,也说明Redis没有发生内存交换。内存碎片率超过1.5,说明Redis消耗了实际需要物理内存的150%,其中50%是内存碎片率。内存碎片率低于1的,说明Redis内存分配超出了物理内存,操作系统正在进行内存交换。需要增加可用物理内存或减少Redis内存占用。

3)解决碎片率大的问题

        如果你的Redis版本是4.0以下的,需要在redis-cli工具上输入shutdown save命令,让Redis数据库执行保存操作并关闭Rediks服务,再重启服务器。Redis服务器重启后,Redis会将没用的内存归还给操作系统,碎片率会降下来。但生产环境中不允许这样操作。Redis4.0版本开始,可以在不重启的情况下,线上整理内存碎片。

        config set activedefrag yes 开启自动碎片清理,内存就会自动清理了(在清理过程中相当于把数据重新拷贝到新的位置,在移动数据的过程中,redis的父进程会成阻塞状态,不会响应客户端的请求,导致性能降低,一般情况下定时手动清理碎片

memory purge                        #手动碎片清理

3、redis优化【☆】:

修改配置文件

  • 设置maxmemory内存上限,避免使用swap空间影响redis性能;
  • 数据内存淘汰策略(maxmemory-policy)一般最常使用的是volatile-lru(只删除最近最少访问并设置了过期时间的键)或 allkeys-lru;
  • 开启自动内存碎片清理(activedefrag yes)
  • 设置maxclients客户端最大连接数量
  • 设置lazy free惰性删除机制(lazyfree-lazy-eviction、lazyfree-lazy-expire、lazyfree-lazy-server-del),因为删除数据时也会阻塞父进程,开启惰性删除会创建子进程进行删除;
  • 开启混合持久化方式

    使用命令 config set aof-use-rdb-preamble yes执行,或者修改配置文件

其他性能优化

1、设置键值合理的过期时间,避免大量key集中过期。大量数据同时失效不光会导致redis性能降低,同时还会导致缓存击穿缓存雪崩的问题。

2、尽可能使用hash类型存储数据。因为hash类型的一个key可以包含多个字段,且hash类型占用空间较小

3、开启自动内存碎片清理(activedefrag yes)

4、缩短键值对存储的长度,避免bigkey(大键是最容易导致redis数据阻塞的原因)

5、尽量使用物理机而非虚拟机部署Redis服务,使用高速固态盘作为AOF日志的写入盘

6、开启AOF持久化,设置刷盘策略为everysec;
7、使用分布式架构(主从复制、哨兵模式、集群)增加读写速度,并实现高可用

8、禁用内存大页(echo never > /sys/kernel/mm/transparent_hugepage/enabled),因开启内存大页会导致fork的速度变慢,也会拖慢写操作的执行时间

4、Redis三大缓存问题【☆】

        正常情况下,大部分访问请求应该是先先被redis响应的,在redis那里得不到的小部分访问请求才会去请求MySQL数据库获取数据,这样MySQL数据库的负载压力是非常小的,且可以正常工作;雪崩、穿透、击穿问题的根本原因在于redis缓存命中率下降 ,大量请求会直接发给MySQL数据库,导致MySQL数据库压力过大而崩溃。

1)缓存雪崩

缓存同一时间大面积的过期失效。所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。

解决方案:

1.使用随机数设置key的过期时间,防止集群过期 
2.设置二级缓存
3.数据库使用排他锁,实现加锁等待

2)缓存穿透

缓存穿透是指查询数据库和缓存都无数据,因为数据库查询无数据,出于容错考虑,不会将结果保存到缓存中,因此每次请求都会去查询数据库,这种情况就叫做缓存穿透。

解决方案:

1.对空值也进行缓存
2.使用布隆过滤器进行拦截一定不存在的无效请求
3.使用脚本实时监控,进行黑名单限制

3)缓存击穿

缓存击穿指的是某个热点缓存,在某一时刻恰好失效了,然后此时刚好有大量的并发请求,此时这些请求将会给数据库造成巨大的压力,这种情况就叫做缓存击穿。

解决方案:

1.设置永不过期
2.预先对热点数据进行缓存预热
3.数据库使用排他锁(也称写锁),实现加锁等待

5、如何保证MySQL和redis的数据一致性?

  • 读取数据时,先从redis读取数据,如果redis没有,再从MySQL读取,并将读取到的数据同步到redis缓存中。【☆】
  • 更新数据时,先更新MySQL数据,再更新redis缓存
  • 删除数据时,先删除redis缓存,再删除MySQL数据
  • 对于一些关键数据,可以使用定时任务,定时自动进行缓存预热,或使用MySQL触发器来实现同步redis缓存

如何排查redis占用内存高的问题?

1、登陆服务器,查看tcp连接数

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

2、查看redis是否存在过多空闲键

3、分析redis基本的内存信息

连接redis后,使用info memory命令查看redis内存的基本信息:查看每个db key的数量:查询redis已经连接的客户端数;查看单个redis key占用的空间 -- redis-memory-for-key -s ${host} -p ${port} key_name;如果redis是用的集群,找到key的槽位所在的节点,port用对应的节点即可。 寻找占用内存过高的key 。

4、内存快照分析

redis-rdb-tools 是一个 python 的解析 rdb 文件的工具,在分析内存的时候,主要用它生成内存快照。使用redis-rdb-tools 生成内存快照,通过内存快照,可以找出占用内存超大的单个key,分析问题key产生的原因。

5、redis内存限制

# 设置Redis最大占用内存大小为500M
config set maxmemory 500mb
# 获取设置的Redis能使用的最大内存大小
config get maxmemory

6、redis内存淘汰

获取当前的内存淘汰策略
config get maxmemory-policy

修改redis.conf设置redis淘汰策略: 

maxmemory-policy volatile-lru

通过命令修改淘汰策略:

config set volatile-lru allkeys-lru

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

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

相关文章

MySQL InnoDB事务隔离和并发控制面试题详解

1. 为什么 MySQL 使用 B+ 树作为索引而不是 B 树? MySQL 选择使用 B+ 树作为索引主要有以下几个原因: 减少 IO 次数,提高效率:B+ 树的所有数据都存储在叶子节点,非叶子节点只存储索引,树的高度较低,因此查找路径较短,减少了磁盘 IO 次数。查询效率更加稳定:由于数据仅…

Hyper-V 安装 CentOS 8.5

前言 Hyper-V安装文档:在 Windows 10 上安装 Hyper-VCentOS 系统下载:CentOS 国内镜像源 8.5.2111作者:易墨发布时间:2023.10.01原文地址:https://www.cnblogs.com/morang/p/devops-hyperv-centos-install.html使用命令安装 以管理员身份运行 PowerShell 命令: Enable-…

c++初阶知识——string类详解

目录 前言: 1.标准库中的string类 1.1 auto和范围for auto 范围for 1.2 string类常用接口说明 1.string类对象的常见构造 1.3 string类对象的访问及遍历操作 1.4. string类对象的修改操作 1.5 string类非成员函数 2.string类的模拟实现 2.1 经典的string…

GAMES104:05游戏引擎中的渲染系统2:渲染中的光照、材质和shader-学习笔记

文章目录 一、渲染方程及其挑战二、基础光照解决方案-简化版简化光源简化材质简化阴影 三、基于预计算的全局光照3.1挑战和计算思路傅里叶变换球谐函数(Spherical Harmonics) 3.2 SH Lightmap:预计算 GI3.3 探针 Probe:Light Prob…

无涯·问知财报解读,辅助更加明智的决策

财报解读就像是给公司做一次全面的体检,是理解公司内部运作机制和市场表现的一把钥匙,能够有效帮助投资者、分析师、管理层以及所有市场参与者判断一家公司的健康程度和发展潜力。 星环科技无涯问知的财经库内置了企业年报及财经类信息,并对…

Linux:传输层(1) -- UDP协议

1. 端口号 同一台主机的不同端口号(Port)标记了主机上不同的进程,如下图所示: 在 TCP/IP 协议中 , 用 " 源IP", "源端口号", "目的IP", "目的端口号", "协议号" 这样一个五元组来标识一个通信 ( 可…

制作excel模板,用于管理后台批量导入船舶数据

文章目录 引言I 数据有效性:基于WPS在Excel中设置下拉框选择序列内容II 数据处理:基于easyexcel工具实现导入数据的持久化2.1 自定义枚举转换器2.2 ExcelDataConvertExceptionIII 序列格式化: 基于Sublime Text 文本编辑器进行批量字符操作引言 需求: excel数据导入模板制…

基于 HTML+ECharts 实现的大数据可视化平台模板(含源码)

构建大数据可视化平台模板:基于 HTML 和 ECharts 的实现 大数据的可视化对于企业决策、市场分析和业务洞察至关重要。通过直观的数据展示,团队可以快速理解复杂的数据模式,发现潜在的业务机会。本文将详细介绍如何利用 HTML 和 ECharts 实现一…

js逆向——origin/refer请求头反爬

今日受害网站: https://www.regulations.gov/docket/FDA-2016-D-1399/document 最终目标:爬取该网站中的新闻摘要 首先打开网页,刷新一下,观察都返回了哪些数据 然后我们ctrlf进行关键字搜索 进一步,只过滤含有docu…

Linux_实现TCP网络通信

目录 1、实现服务器的逻辑 1.1 socket 1.2 bind 1.3 listen 1.4 accept 1.5 read 1.6 write 1.7 服务器代码 2、实现客户端的逻辑 2.1 connect 2.3 客户端代码 3、实现服务器与客户端的通信 结语 前言: 在Linux下,实现传输层协议为TCP…

MySQL数据库-备份恢复

一、MySQL日志管理 1.为什么需要日志 用于排错用来做数据分析了解程序的运行情况,了解MySQL的性能 2.日志作用 在数据库保存数据时,有时候不可避免会出现数据丢失或者被破坏,这样情况下,就必须保证数据的安全性和完整性&#…

鸿蒙SDK开发能力

什么是鸿蒙SDK:HarmonyOS(Software Development Kit)是面向应用和服务开发的开放能力合集,本质就是工具集,与JDK、AndroidSDK在逻辑上有相似之处 18N:1指的是手机,8指的是车机、音箱、耳机、手表/手环、平板、大屏、PC、AR/VR&am…

PCL-基于超体聚类的LCCP点云分割

目录 一、LCCP方法二、代码实现三、实验结果四、总结五、相关链接 一、LCCP方法 LCCP指的是Local Convexity-Constrained Patch,即局部凸约束补丁的意思。LCCP方法的基本思想是在图像中找到局部区域内的凸结构,并将这些结构用于分割图像或提取特征。这种…

DolphinScheduler学习

1.查看文档 点击访问:https://dolphinscheduler.apache.org/zh-cn/docs 我们可以看到相关的文档简介里有 介绍 DolphinScheduler是Apache DolphinScheduler 是一个分布式易扩展的可视化DAG工作流任务调度开源系统。适用于企业级场景,提供了一个可视化…

太原高校大学智能制造实验室数字孪生可视化系统平台建设项目验收

随着科技的不断进步,智能制造已经成为推动制造业转型升级的重要力量。太原高校大学智能制造实验室紧跟时代步伐,积极推进数字孪生可视化系统平台的建设,并于近日圆满完成了项目的验收工作。这一里程碑式的成果,不仅标志着实验室在…

uniapp安卓plus原生选择系统文件

uniapp安卓plus原生选择系统文件 效果&#xff1a; 组件代码&#xff1a; <template xlang"wxml" minapp"mpvue"><view></view> </template> <script>export default {name: file-manager,props: {},data() {return {is…

靶场实战 _ ATTCK 实战 Vulnstack 红队

环境配置 网络拓扑图 (仅供参考) 攻击机&#xff1a;kali ip:192.168.111.5靶机&#xff1a;web-centos 外网ip:192.168.111.10 内网ip:192.168.93.100web1-ubuntu ip: 192.168.93.120PC ip: 192.168.93.30win 2008 ip:192.168.93.20win 2012 ip:192.168.93.10 信息搜集 端口…

【C++】string类(下)

个人主页~ string类&#xff08;上&#xff09; string类 二、模拟实现string类1、头文件string.h2、常见构造3、容量函数4、访问及遍历5、类对象修改6、流插入流提取重载 二、模拟实现string类 今天我们来实现一下上篇文章中详细介绍过的接口 1、头文件string.h #pragma onc…

Redis的应用场景及类型

目录 一、Redis的应用场景 1、限流 2、分布式锁 3、点赞 4、消息队列 二、Redis类型的命令及用法 1、String类型 2、Hash类型 3、List类型 4、Set类型 5、Zset类型 6、Redis工具类 Redis使用缓存的目的就是提升读写性能 实际业务场景下&#xff0c;我们就可以把 Mys…

【常微分方程】

框架 常微分方程的概念一阶微分方程可变离分量齐次方程一阶线性微分方程可降阶的高阶微分方程二阶常系数齐次线性微分方程二阶常系数非齐次线性微分方程 讲解 【1】 常微分方程&#xff1a;是微分方程的特殊情况&#xff1b; 阶&#xff1a;是方程未知函数的最高阶导数的阶数&…