Redis高可用
在web服务器中,高可用是指服务器能够正常访问的时刻,衡量的标准是在多长时刻内能够供给正常服务(99.9%、99.99%、99.999%等等)。
可是在Redis语境中,高可用的含义似乎要广泛一些,除了确保供给正常服务(如主从别离、快速容灾技能),还需求考虑数据容量的扩展、数据安全不会丢掉等。
Redis高可用的技能
在Redis中,完结高可用的技能首要包括耐久化、主从仿制、岗兵和cluster集群,下面别离阐明它们的效果,以及处理了什么样的问题。
- 耐久化: 耐久化是最简略的高可用办法(有时甚至不被归为高可用的手法),首要效果是数据备份,行将数据存储在硬盘,确保数据不会因进程退出而丢掉。
-
主从仿制: 主从仿制是高可用Redis的根底,岗兵和集群都是在主从仿制根底上完结高可用的。主从仿制首要完结了数据的多机备份(和同步),以及关于读操作的负载均衡和简略的毛病康复。
- 缺陷:毛病康复无法主动化;写操作无法负载均衡;存储才能遭到单机的约束。
-
岗兵: 在主从仿制的根底上,岗兵完结了主动化的毛病康复。(主挂了,找一个从成为新的主,岗兵节点进行监控)
- 缺陷:写操作无法负载均衡;存储才能遭到单机的约束。
- Cluster集群: 经过集群,Redis处理了写操作无法负载均衡,以及存储才能遭到单机约束的问题,完结了较为完善的高可用计划。(6台起步,成双成对,3主3从)
Redis耐久化
耐久化的功用: Redis是内存数据库,数据都是存储在内存中,为了避免服务器断电等原因导致Redis进程异常退出后数据的永久丢掉,需求定时将Redis中的数据以某种办法(数据或指令)从内存保存到硬盘;当下次Redis重启时,利用耐久化文件完结数据康复。除此之外,为了进行灾难备份,能够将耐久化文件拷贝到一个长途方位。
Redis供给两种办法进行耐久化
- RDB耐久化:原理是将Reids在内存中的数据库记载守时保存到磁盘上。(守时对内存中的数据生成快照,以文件办法保存在硬盘中)
- AOF耐久化(append only file):原理是将Reids 的操作日志以追加的办法写入文件,相似于MySQL的binlog。(相似于Mysql的二进制日志,以追加的办法将写和删的操作指令记载到AOF文件中)
因为AOF耐久化的实时性更好,即当进程意外退出时丢掉的数据更少,因而AOF是现在干流的耐久化办法,不过RDB耐久化仍然有其用武之地。
RDB体积小,康复速度更快。对功能影响较小。
RDB耐久化
RDB耐久化是指在指定的时刻距离内将内存中当时进程中的数据生成快照保存到硬盘(因而也称作快照耐久化),用二进制紧缩存储,保存的文件后缀是rdb;当Redis重新发动时,能够读取快照文件康复数据。
触发条件
RDB耐久化的触发分为手动触发和主动触发两种。
手动触发
save指令和bgsave指令都能够生成RDB文件。
- save指令会堵塞Redis服务器进程,直到RDB文件创立结束停止,在Redis服务器堵塞期间,服务器不能处理任何指令恳求。
- 而bgsave指令会创立一个子进程,由子进程来担任创立RDB文件,父进程(即Redis主进程)则持续处理恳求。
bgsave指令履行进程中,只有fork子进程时会堵塞服务器,而关于save指令,整个进程都会堵塞服务器,因而save已根本被抛弃,线上环境要杜绝save的运用。
主动触发
在主动触发RDB耐久化时,Redis 也会挑选bgsave而不是save来进行耐久化。
主动触发最常见的状况是在装备文件中经过save m n
指定当m秒内产生n次变化时,会触发bgsave。
RDB耐久化存在的问题:实时性不行,最快也要60秒备份一次,假如50多秒时服务器宕机,则备份失利。
其他主动触发机制
除了save m n以外,还有一些其他状况会触发bgsave
- 在主从仿制场景下,假如从节点履行全量仿制操作,则主节点会履行bgsave指令,并将rdb文件发送给从节点。
- 履行shutdown指令时,主动履行rdb耐久化。
bgsave履行流程
- Redis父进程首要判别:当时是否在履行save,或 bgsave/ bgrewriteaof 的子进程,假如在履行则bgsave指令直接回来。
- bgsave/bgrewriteaof 的子进程不能一起履行,首要是依据功能方面的考虑:两个并发的子进程一起履行许多的磁盘写操作,或许引起严峻的功能问题。
- 父进程履行fork操作创立子进程,这个进程中父进程是堵塞的,Redis不能履行来自客户端的任何指令。
- 父进程fork后,bgsave 指令回来”Background saving started” 信息并不再堵塞父进程,并能够呼应其他指令。
- 子进程创立RDB文件,依据父进程内存快照生成暂时快照文件,完结后对原有文件进行原子替换。(原子替换:文件整体替换,要么都产生,要么都不产生)
- 子进程发送信号给父进程表明完结,父进程更新计算信息。
发动时加载
- RDB文件的载入工作是在服务器发动时主动履行的,并没有专门的指令。可是因为AOF的优先级更高,因而当AOF敞开时,Redis会优先载入AOF文件来康复数据;只有当AOF封闭时,才会在Redis服务器发动时检测RDB文件,并主动载入。 服务器载入RDB文件期间处于堵塞状况,直到载入完结停止。
- Redis载入RDB文件时,会对RDB文件进行校验,假如文件损坏,则日志中会打印过错,Redis发动失利。
AOF耐久化
- RDB耐久化是将进程数据写入文件,而AOF耐久化,则是将Redis履行的每次写、删去指令记载到单独的日志文件中,查询操作不会记载。
- 当Redis重启时再次履行AOF文件中的指令来康复数据。(重放指令进行康复)
- 与RDB比较,AOF的实时性更好,因而已成为干流的耐久化计划。(支持秒级写入)
敞开AOF
Redis服务器默许敞开RDB,封闭AOF的, 要敞开AOF,需求在/etc/redis/6379.conf
装备文件中装备。
履行流程
因为需求记载Redis的每条写指令,因而AOF不需求触发。
AOF的履行流程包括:
- 指令追加(append) :将Redis的写指令追加到缓冲区aof_ buf;
- 文件写入(write)和文件同步(sync) :依据不同的同步战略将aof_buf中的内容同步到硬盘;
- 文件重写(rewrite) :定时重写AOF文件,到达紧缩的意图。(将过期数据、无效指令、多条指令,进行紧缩或删去)
指令追加
- Redis先将写指令追加到缓冲区,而不是直接写入文件,首要是为了避免每次有写指令都直接写入硬盘,导致硬盘IO成为Redis负载的瓶颈。
- 指令追加的格局是Redis指令恳求的协议格局,它是一种纯文本格局,具有兼容性好、可读性强、简单处理、操作简略避免二次开支等长处。
- 在AOF文件中,除了用于指定数据库的select指令(如select 0为选中0号数据库)是由Redis添加的, 其他都是客户端发送来的写指令。
文件写入和文件同步
Redis供给了多种AOF缓存区的同步文件战略,战略涉及到操作体系的write函数和fsync函数,阐明如下:
- 为了进步文件写入功率,在现代操作体系中,当用户调用write函数将数据写入文件时,操作体系一般会将数据暂存到一个内存缓冲区里,当缓冲区被填满或超越了指守时限后,才真正将缓冲区的数据写入到硬盘里。
- 这样的操作虽然进步了功率,但也带来了安全问题:假如计算机停机,内存缓冲区中的数据会丢掉。因而体系一起供给了fsync、fdatasync等同步函数,能够强制操作体系马上将缓冲区中的数据写入到硬盘里,然后确保数据的安全性。
AOF缓存区的同步文件战略存在三种同步办法
装备文件/etc/redis/6379.conf的729行
-
appendfsync always:指令写入aof_buf后当即调用体系fsync操作同步到AOF文件,fsync完结后线程回来。 这种状况下,每次有写指令都要同步到AOF文件,硬盘IO成为功能瓶颈,Redis只能支持大约几百TPS写入,严峻下降了Redis的功能; 即便是运用固态硬盘(SSD) ,每秒大约也只能处理几万个指令,并且会大大下降SSD的寿数。
- 指令写入aof_buf后当即调用体系fsync操作同步到AOF文件。安全性高,功能低。
-
appendfsync no:指令写入aof_buf后调用体系write操作,不对AOF文件做fsync同步; 同步由操作体系担任,一般同步周期为30秒。 这种状况下,文件同步的时刻不可控,且缓冲区中堆积的数据会许多,数据安全性无法确保。
- 当缓冲区被填满或超越了指守时限后(默许30秒),才将缓冲区的数据写入到硬盘里。功能高,但安全性低。
-
appendfsync everysec:指令写入aof_buf后调用体系write操作,write完结后线程回来; fsync同步文件操作由专门的线程每秒调用一次。 everysec是前述两种战略的折中,是功能和数据安全性的平衡,因而是Redis的默许装备,也是我们推荐的装备。
- 每秒同步一次,是功能和数据安全性的平衡,因而是Redis的默许装备。
文件重写
- 跟着时刻消逝,Redis服务器履行的写指令越来越多,AOF文件也会越来越大;过大的AOF文件不只会影响服务器的正常运转,也会导致数据康复需求的时刻过长。
- 文件重写是指定时重写AOF文件,减小AOF文件的体积。需求留意的是,AOF 重写是把Redis进程内的数据转化为写指令,同步到新的AOF文件;不会对旧的AOF文件进行任何读取、写入操作!
- 关于文件重写需求留意的另一点是:关于AOF耐久化来说,文件重写虽然是强烈推荐的,但并不是有必要的;即便没有文件重写,数据也能够被耐久化并在Redis发动的时分导入。因而在一些实际中,会封闭主动的文件重写,然后经过守时使命在每天的某一时刻守时履行。
留意:
重写会消耗功能,影响业务,不能在业务高峰期进行重写。所以一般会封闭主动重写,由守时使命在每天的某一时刻守时履行重写功用。
文件重写能够紧缩AOF文件的原因
- 过期的数据不再写入文件。
- 无效的指令不再写入文件:如有些数据被重复设值(set mykey v1, set mykey v2)、 有些数据被删去了(set myset vl, del myset)等。
- 多条指令能够合并为一个:如sadd myset v1, sadd myset v2, sadd myset v3能够合并为sadd myset v1 v2 v3。(sadd添加调集)
rewrite之后aof文件会保存keys的最终状况,清除去之前冗余的,来缩小这个文件。因为重写后AOF履行的指令削减了,文件重写既能够削减文件占用的空间,也能够加快康复速度。
文件重写的触发
- 手动触发: 直接调用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操作。
vim /etc/redis/6379.conf
----771行----
771 auto-aof-rewrite-percentage 100
772 auto-aof-rewrite-min-size 64mb
-
auto-aof-rewrite-percentage 100
- 文件的巨细超越基准百分之多少后触发bgrewriteaof。默许这个值设置为100,意味着当时aof是基准巨细的两倍的时分触发bgrewriteaof。把它设置为0能够禁用主动触发的功用。
- 即当时AOF文件巨细(即aof_current_size)是前次日志重写时AOF文件巨细(aof_base_size)两倍时,产生BGREWRITEAOF操作。
- 留意:例如前次文件到达100M进行重写,那么这次需求到达200M时才进行重写。文件需求越来越大,所以一般不运用主动重写。假如运用主动重写,需求定时手动重写干预一次,让文件要求康复到100M。
-
auto-aof-rewrite-min-size 64mb
- 当文件大于64M时才会进行重写
- 当时aof文件大于多少字节后才触发。
- 当时AOF文件履行BGREWRITEAOF指令的最小值,避免刚开始发动Reids时因为文件尺度较小导致频频的BGREWRITEAOF
文件重写的流程
留意
- 重写由父进程fork子进程进行。
- 重写期间Redis履行的写指令,需求追加到新的AOF文件中,为此Redis引入了aof_rewrite_buf缓存
流程
- (1)Redis父进程首要判别当时是否存在正在履行bgsave/bgrewriteaof的子进程,假如存在则bgrewriteaof指令直接回来,假如存在bgsave指令则等bgsave履行完结后再履行。(正常状况下运用AOF就会运用AOF进行记载,不会运用RDB。主从仿制时会主动触发bgsave指令)
- (2)父进程履行fork操作创立子进程,这个进程中父进程是堵塞的(无法承受任何客户端的恳求)。
- (3.1)父进程fork后,bgrewriteaof 指令回来”Background append only file rewrite started” 信息并不再堵塞父进程,并能够呼应其他指令。Redis的一切写指令仍然写入AOF缓冲区,并依据appendfsync战略同步到硬盘,确保原有AOF机制的正确。
- (3.2)因为fork操作运用写时仿制技能,子进程只能共享fork操作时的内存数据。因为父进程仍然在呼应指令,因而Redis运用AOF重写缓冲区(aof_rewrite_ buf)保存这部分数据,避免新AOF文件生成期间丢掉这部分数据。也就是说,bgrewriteaof履行期间,Redis的写指令一起追加到aof_ buf和aof_rewirte_ buf两个缓冲区。 (确保新写入的数据不丢掉)
- (4)子进程依据内存快照,按照指令合并规则写入到新的AOF文件。
- (5.1)子进程写完新的AOF文件后,向父进程发信号,父进程更新计算信息,详细能够经过info persistence检查。
- (5.2)父进程把AOF重写缓冲区的数据写入到新的AOF文件,这样就确保了新AOF文件所保存的数据库状况和服务器当时状况共同。
- (5.3)运用新的AOF文件替换老文件,完结AOF重写。(替换是原子性的)
发动时加载
- 当AOF敞开时,Redis发动时会优先载入AOF文件来康复数据;只有当AOF封闭时,才会载入RDB文件康复数据。
- 当AOF敞开,但AOF文件不存在时,即便RDB文件存在也不会加载。
- Redis载入AOF文件时,会对AOF文件进行校验,假如文件损坏,则日志中会打印过错,Redis发动失利。但假如是AOF文件结束不完整(机器忽然宕机等简单导致文件尾部不完整),且aof-load-truncated参数敞开,则日志中会输出正告,Redis疏忽掉AOF文件的尾部,发动成功。aof-load-truncated参数默许是敞开的。
RDB和AOF的优缺陷
RDB耐久化的优缺陷
长处:
- RDB文件紧凑,体积小,网络传输快,适合全量仿制;康复速度比AOF快许多。当然,与AOF比较, RDB最重要的长处之一是对功能的影响相对较小。
(体积小,康复速度更快,对功能影响较小。)
缺陷:
- RDB文件的致命缺陷在于其数据快照的耐久化办法决定了必然做不到实时耐久化,而在数据越来越重要的今日,数据的许多丢掉许多时分是无法承受的,因而AOF耐久化成为干流。
- 此外,RDB文 件需求满足特定格局,兼容性差(如老版别的Redis不兼容新版别的RDB文件)。
- 关于RDB耐久化,一方面是bgsave在进行fork操作时Redis主进程会堵塞,另一方面,子进程向硬盘写数据也会带来IO压力。
(实时性差、兼容性差、在fork子进程时会堵塞父进程。)
AOF耐久化的优缺陷
- 与RDB耐久化相对应,AOF的长处在于支持秒级耐久化、实时性好、兼容性好,缺陷是文件大、康复速度慢、对功能影响大。
- 关于AOF耐久化,向硬盘写数据的频率大大进步(everysec战略下为秒级),IO 压力更大,甚至或许形成AOF追加堵塞问题。
- AOF文件的重写与RDB的bgsave相似,会有fork时的堵塞和子进程的 IO 压力问题。相对来说,因为AOF向硬盘中写数据的频率更高,因而对Redis主进程功能的影响会更大。
Redis功能管理
检查Redis内存运用
- 办法一:进入redis数据库检查
- 办法二:指令行检查
内存碎片率
内存碎片率的计算
内存碎片率=Redis向操作体系恳求的内存 / Redis中的数据占用的内存
- mem_fragmentation_ratio:内存碎片率。
- used_memory_rss:是Redis向操作体系恳求的内存。
- used_memory:是Redis中的数据占用的内存。
- used_memory_peak:redis内存运用的峰值。
内存碎片产生的原因
- Redis内部有自已的内存管理器,为了进步内存运用的功率,来对内存的恳求和开释进行管理。
- Redis中的值删去的时分,并没有把内存直接开释、交还给操作体系,而是交给了Redis内部有内存管理器。
- Redis中恳求内存的时分,也是先看自己的内存管理器中是否有满足的内存可用。
- Redis的这种机制,进步了内存的运用率,可是会使Redis中有部分自己没在用,却不开释的内存,导致了内存碎片的产生。
盯梢内存碎片率
盯梢内存碎片率,对了解Redis实例的资源功能是非常重要的:
- 内存碎片率在1到1.5之间是正常的,这个值表明内存碎片率比较低,也阐明Redis 没有产生内存交换。
- 内存碎片率超越1.5,阐明Redis消耗了实际需求的物理内存的150%,其间50%是内存碎片率。
- 内存碎片率低于1的,阐明Redis内存分配超出了物理内存,操作体系正在进行内存交换(运用虚拟内存,会下降功能)。需求添加可用物理内存或削减Redis内存占用。
处理碎片率大的问题
- 假如你的Redis版别是4.0以下的,需求在redis-cli 工具上输入shutdown save指令,让Redis数据库履行保存操作并封闭Redis服务,再重启服务器。Redis服务器重启后,Redis 会将没用的内存归还给操作体系,碎片率会降下来。
- Redis4.0版别开始,能够在不重启的状况下,线上收拾内存碎片,将未运用的内存归还给操作体系。
config set activedefrag yes #主动碎片整理
memory purge #手动碎片整理
内存运用率
redis实例的内存运用率超越可用最大内存,操作体系将开始进行内存与swap空间交换。
避免内存交换产生的办法:
- 针对缓存数据巨细挑选装置Redis 实例
- 尽或许的运用Hash数据结构存储
- 设置key的过期时刻
内收回key
内存整理战略,确保合理分配redis有限的内存资源。
当内存运用到达设置的最大阈值时,需挑选一种key的收回战略,默许状况下收回战略是制止删去(noenviction)。
装备文件中修正 maxmemory-policy 特点值:
vim /etc/redis/6379.conf
---598行----
maxmemory-policy noenviction #修正max-memory-policy特点值
##收回战略有以下几种:##
volatile-lru
#运用LRU算法从已设置过期时刻的数据调集中筛选数据
(移除最近最少运用的key,针对设置了TTL的key)
volatile-ttl
#从已设置过期时刻的数据调集中挑选行将过期的数据筛选
(移除最近过期的key)
volatile-random
#从已设置过期时刻的数据调集中随机挑选数据筛选
(在设置了TTL的key里随机移除)
allkeys-lru
#运用LRU算法 从一切数据调集中筛选数据
(移除最少运用的key,针对一切的key)
allkeys-random
#从数据调集中任意挑选数据筛选(随机移除key)
noenviction
#制止筛选数据(不删去直到写满时报错)
redis 优化
- 敞开 AOF 耐久化
- 设置 config set activedefrag yes 敞开内存碎片主动整理,或许 守时履行 memory purge 整理内存碎片
- 设置 内存筛选战略 maxmemory-policy 完结确保内存运用率不超越体系最大内存
- 尽或许运用 Hash 数据类型存储数据,假如 Hash 中包括很少的字段,那么该类型的数据也将仅占用很少的空间
- 设置 key 的过期时刻,精简键名 和 键值,控制键值的巨细
- 设置 config set requirepass 敞开暗码验证
- 合理设置 maxclient 最大衔接数参数(10000),tcp-backlog 衔接排队数(1024), timeout 衔接超时时刻(30000)
缓存和数据库双写共同性问题
先更新数据库,然后再删去缓存 + 缓存做过期时刻,数据过期后再有读恳求可从数据库直接更新缓存
缓存雪崩
缓存同一时刻大面积的过期失效,所以,后边的恳求都会落到数据库上,形成数据库短时刻内承受许多恳求而崩掉。
处理计划:
- 缓存数据的过期时刻设置随机,避免同一时刻许多数据过期现象产生。
- 一般并发量不是特别多的时分,运用最多的处理计划是加锁排队。
- 给每一个缓存数据添加相应的缓存符号,记载缓存的是否失效,假如缓存符号失效,则更新数据缓存。
缓存击穿
缓存中没有但数据库中有的数据(一般是缓存时刻到期),这时因为并发用户特别多,一起读缓存没读到数据,又一起去数据库去取数据,引起数据库压力瞬间增大,形成过大压力。 和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,许多数据都查不到然后查数据库。
处理计划:
- 设置热点数据永久不过期。
- 加互斥锁,互斥锁
缓存穿透
缓存和数据库中都没有的数据,导致一切的恳求都落到数据库上,形成数据库短时刻内承受许多恳求而崩掉。
处理计划:
- 接口层添加校验,如用户鉴权校验,id做根底校验,id<=0的直接拦截;
- 从缓存取不到的数据,在数据库中也没有取到,这时也能够将key-value对写为key-null,缓存有用时刻能够设置短点,如30秒(设置太长会导致正常状况也无法运用)。这样能够避免进犯用户反复用同一个id暴力进犯
- 采用布隆过滤器,将一切或许存在的数据哈希到一个满足大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,然后避免了对底层存储体系的查询压力
总结
RDB:redis定时的将内存中的数据快照保存到硬盘中,并紧缩,文件名一般以.rdb为后缀
AOF:redis将每次的写操作指令追加到aof_buf缓冲区中,然后依据同步战略每秒将缓冲区的数据刷到硬盘里,文件名一般以.aof为后缀
差异:
- RDB耐久化生成的文件体积小,康复速度更快,可是实时性差,在fork子进程进程时会堵塞redis主进程,在耐久化向硬盘写入数据时会带来IO压力
- AOF支持妙计耐久化,实时性好,可是耐久化生成的文件大,康复速度慢,文件重写时fork子进程进程期间会阻寨redis主进程,IO压力更大