redis简单的优化

这里提供三种优化方案

  1. redis持久化

  2. 内存管理与数据淘汰机制

  3. redis性能调优

 

 

 

redis持久化

redis持久化目前有二种模式,RDB,AOF

 

RDB持久化

采用RDB持久方式,Redis会定期保存数据快照至一个rbd文件中,并在启动时自动加载rdb文件,恢复之前保存的数据。可以在配置文件中配置Redis进行快照保存的时机

在Redis中RDB持久化的触发分为两种:自己手动触发与Redis定时触发

 

针对RDB方式的持久化,手动触发可以使用

  1. save:会阻塞当前Redis服务器,直到持久化完成,线上应该禁止使用。

  2. bgsave:该触发方式会fork一个子进程,由子进程负责持久化过程,因此阻塞只会发生在fork子进程的时候。

 

而自动触发的场景主要是有以下几点:

  1. 根据我们的 save m n 配置规则自动触发;

  2. 从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点会触发 bgsave;

  3. 执行 debug reload 时;

  4. 执行 shutdown时,如果没有开启aof,也会触发。

 

RDB的优点:

  1. 对性能影响最小。如前文所述,Redis在保存RDB快照时会fork出子进程进行,几乎不影响Redis处理客户端请求的效率。

  2. 每次快照会生成一个完整的数据快照文件,所以可以辅以其他手段保存多个时间点的快照(例如把每天0点的快照备份至其他存储媒介中),作为非常可靠的灾难恢复手段。

  3. 使用RDB文件进行数据恢复比使用AOF要快很多。

RDB的缺点:

  1. 快照是定期生成的,所以在Redis crash时或多或少会丢失一部分数据。

  2. 如果数据集非常大且CPU不够强(比如单核CPU),Redis在fork子进程时可能会消耗相对较长的时间(长至1秒),影响这期间的客户端请求

 

RDB的配置

save [seconds] [changes]
##采用RDB持久方式,Redis会定期保存数据快照至一个rbd文件中,并在启动时自动加载rdb文件,恢复之前保存的数据。可以在配置文件中配置Redis进行快照保存的时机

---------------------------------------------------------------------

save 60 100##意为在[seconds]秒内如果发生了[changes]次数据修改,则进行一次RDB快照保存

---------------------------------------------------------------------

save 900 1save 300 10save 60 10000#####
会让Redis每60秒检查一次数据变更情况,如果发生了100次或以上的数据变更,则进行RDB快照保存。
可以配置多条save指令,让Redis执行多级的快照保存策略。
Redis默认开启RDB快照,默认的RDB策略如下

 

 

AOF持久化

采用AOF持久方式时,Redis会把每一个写请求都记录在一个日志文件里。在Redis重启时,会把AOF文件中记录的所有写操作顺序执行一遍,确保数据恢复到最新

AOF的整个流程大体来看可以分为两步,

  1. 命令的实时写入(如果是 appendfsync everysec 配置,会有1s损耗),

  2. 对aof文件的重写。

对于增量追加到文件这一步主要的流程是:命令写入=》追加到aof_buf =》同步到aof磁盘。那么这里为什么要先写入buf在同步到磁盘呢?如果实时写入磁盘会带来非常高的磁盘IO,影响整体性能。

aof重写是为了减少aof文件的大小,可以手动或者自动触发,关于自动触发的规则请看上面配置部分。fork的操作也是发生在重写这一步,也是这里会对主进程产生阻塞。

手动触发: bgrewriteaof,自动触发 就是根据配置规则来触发,当然自动触发的整体时间还跟Redis的定时任务频率有关系。

在重写期间,由于主进程依然在响应命令,为了保证最终备份的完整性;因此它依然会写入旧的AOF file中,如果重写失败,能够保证数据不丢失。

为了把重写期间响应的写入信息也写入到新的文件中,因此也会为子进程保留一个buf,防止新写的file丢失数据。

重写是直接把当前内存的数据生成对应命令,并不需要读取老的AOF文件进行分析、命令合并。

AOF文件直接采用的文本协议,主要是兼容性好、追加方便、可读性高可认为修改修复

 

AOF的优点:

  1. 最安全,在启用appendfsync always时,任何已写入的数据都不会丢失,使用在启用appendfsync everysec也至多只会丢失1秒的数据。

  2. AOF文件在发生断电等问题时也不会损坏,即使出现了某条日志只写入了一半的情况,也可以使用redis-check-aof工具轻松修复。

  3. AOF文件易读,可修改,在进行了某些错误的数据清除操作后,只要AOF文件没有rewrite,就可以把AOF文件备份出来,把错误的命令删除,然后恢复数据。

AOF的缺点:

  1. AOF文件通常比RDB文件更大

  2. 性能消耗比RDB高

  3. 数据恢复速度比RDB慢

 

AOF的配置

AOF默认是关闭的,如要开启,进行如下配置:

appendonly yes

 

AOF提供了三种fsync配置,

  1. appendfsync no:不进行fsync,将flush文件的时机交给OS决定,速度最快

  2. appendfsync always:每写入一条日志就进行一次fsync操作,数据安全性最高,但速度最慢

  3. appendfsync everysec:折中的做法,交由后台线程每秒fsync一次

appendfsync everysec
##通常使用折中的配置

 

重写AOF文件

Redis提供了AOF rewrite功能,可以重写AOF文件,只保留能够把数据恢复到最新状态的最小写操作集

auto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb
##上面两行配置的含义是,Redis在每次AOF rewrite时,会记录完成rewrite后的AOF日志大小,当AOF日志大小在该基础上增长了100%后,自动进行AOF rewrite。同时如果增长的大小没有达到64mb,则不会进行rewrite

 

 

 

内存管理与数据淘汰机制

 

内存管理

最大内存设置,默认情况下,在32位OS中,Redis最大使用3GB的内存,在64位OS中则没有限制。

在使用Redis时,应该对数据占用的最大空间有一个基本准确的预估,并为Redis设定最大使用的内存。否则在64位OS中Redis会无限制地占用内存(当物理内存被占满后会使用swap空间),容易引发各种各样的问题。

在内存占用达到了maxmemory后,再向Redis写入数据时,Redis会:

  1. 根据配置的数据淘汰策略尝试淘汰数据,释放空间

  2. 如果没有数据可以淘汰,或者没有配置数据淘汰策略,那么Redis会对所有写请求返回错误,但读请求仍然可以正常执行

在为Redis设置maxmemory时,需要注意:如果采用了Redis的主从同步,主节点向从节点同步数据时,会占用掉一部分内存空间,如果maxmemory过于接近主机的可用内存,导致数据同步时内存不足。所以设置的maxmemory不要过于接近主机可用的内存,留出一部分预留用作主从同步。

 

通过如下配置控制Redis使用的最大内存:

maxmemory 751619276##本机自带内存只有1G,一般推荐Redis设置内存为最大物理内存的四分之三,所以设置0.75G,换成byte是751619276。也有mb格式的

 



数据淘汰机制

Redis提供了5种数据淘汰策略:

  1. volatile-lru:使用LRU算法进行数据淘汰(淘汰上次使用时间最早的,且使用次数最少的key),只淘汰设定了有效期的

  2. key allkeys-lru:使用LRU算法进行数据淘汰,所有的key都可以被淘汰

  3. volatile-random:随机淘汰数据,只淘汰设定了有效期的

  4. key allkeys-random:随机淘汰数据,所有的key都可以被淘汰

  5. volatile-ttl:淘汰剩余有效期最短的key


最好为Redis指定一种有效的数据淘汰策略以配合maxmemory设置,避免在内存使用满后发生写入失败的情况。

一般来说,推荐使用的策略是volatile-lru,并辨识Redis中保存的数据的重要性。对于那些重要的,绝对不能丢弃的数据(如配置类数据等),应不设置有效期,这样Redis就永远不会淘汰这些数据。对于那些相对不是那么重要的,并且能够热加载的数据(比如缓存最近登录的用户信息,当在Redis中找不到时,程序会去DB中读取),可以设置上有效期,这样在内存不够时Redis就会淘汰这部分数据。

配置方法:

maxmemory-policy volatile-lru 
#默认是noeviction,即不进行数据淘汰,常用的就是volatile-lru模式

 

 

 

Redis性能调优

尽管Redis是一个非常快速的内存数据存储媒介,也并不代表Redis不会产生性能问题。

针对Redis的性能优化,主要从下面几个层面入手:

  1. 最初的也是最重要的,确保没有让Redis执行耗时长的命令

  2. 使用pipelining将连续执行的命令组合执行 操作系统的Transparent huge pages功能必须关闭:

  3. 如果在虚拟机中运行Redis,可能天然就有虚拟机环境带来的固有延迟。可以通过./redis-cli --intrinsic-latency 100命令查看固有延迟。同时如果对Redis的性能有较高要求的话,应尽可能在物理机上直接部署Redis。

  4. 检查数据持久化策略

  5. 考虑引入读写分离机制

关闭操作系统的Transparent huge pages功能

echo never >> /sys/kernel/mm/transparent_hugepage/enabled
echo never >> /sys/kernel/mm/transparent_hugepage/defrag