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,一经查实,立即删除!

相关文章

【CSS】响应式设计

响应式设计是指通过⼀些技术⼿段,使得⽹站或应⽤在不同终端设备(如桌⾯电脑、平板电脑、⼿机等)上能够⾃适应地呈现最佳的⽤户体验。 ⼀种实现⽅式是使⽤流体⽹格布局和百分⽐尺⼨等技术,以便根据设备屏幕的宽度和⾼度等信息⾃适…

ubuntu24.04中Osdlyrics报错:canberra-gtk-module和daemon: GDBus.Error:org

OSD Lyrics 是一个桌面应用程序,用于查看与各种媒体播放器兼容的歌词(比如Linux下最好的音乐播放器:audacious)。它不是一个插件,而是一个独立的程序。OSD Lyrics在您的桌面上显示歌词,风格类似于KaraOK。它…

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…

TSMC常见工艺库中7t/9t track的选择

在TSMC的工艺库中,"7T" 和 "9T" 是指标准单元库的轨道(track)数。轨道数(track count)通常是指每个单元的高度,这个高度决定了布线资源的密度和灵活性。 例如tcbn22ullbwp7t30p140_11…

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

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

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

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

Java中的equals()与==的区别与用法

1. 区别 “”操作符用于比较两个对象的地址是否相等。.equals() 方法用于比较两个对象的内容是否相等。 Object 类的 .equals() 方法默认采用的是“”操作符进行比较。假如子类没有重写该方法的话,那么“”操作符和 .equals() 方法的功效就完全一样——比较两个对…

探索AI全栈工程师之路:大模型应用开发基础

探索AI全栈工程师之路:大模型应用开发基础 作为AI领域的一名工程师,我深知掌握AI技术的重要性。随着人工智能技术的飞速发展,AI全栈工程师成为了炙手可热的职业。在本文中,我将结合《大模型应用开发基础》这份教学材料&#xff0…

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

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

学习笔记10:bos、cos和对象存储 的区别

bos、cos和对象存储 的区别 BOS(Baidu Object Storage)、COS(Cloud Object Storage)和对象存储(Object Storage)是几种不同的云存储服务,它们在功能、提供商和使用场景上有一些区别。下面我将详…

SwiftUI革新:Xcode UI开发的新纪元

SwiftUI革新:Xcode UI开发的新纪元 SwiftUI作为Apple推出的声明式UI框架,彻底改变了在Xcode中构建用户界面的方式。它不仅简化了代码,还提高了开发效率,并且使得UI设计更加直观和灵活。本文将深入探讨如何在Xcode中使用SwiftUI进…

制作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…

【OpenHarmony4.1 之 U-Boot 2024.07源码深度解析】014 - UBOOT 内存分布梳理

【OpenHarmony4.1 之 U-Boot 2024.07源码深度解析】014 - UBOOT 内存分布梳理 一、 UBOOT 内存分布梳理系列文章汇总:《【OpenHarmony4.1 之 U-Boot 源码深度解析】000 - 文章链接汇总》 本文链接:《【OpenHarmony4.1 之 U-Boot 2024.07源码深度解析】014 - UBOOT 内存分布梳…

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.日志作用 在数据库保存数据时,有时候不可避免会出现数据丢失或者被破坏,这样情况下,就必须保证数据的安全性和完整性&#…