Redis的一些坑

出现问题常见的原因有:

1. 网络问题,比如跨网跨机房

2. 个别慢查询导致的整个redis受阻,记住,redis是单线程

3. 存储不当,比如类型存储错误,该用zset却用list,value值过大

4. aof的增量写入和aof重写带来的瞬间阻塞(单线程,操作同个文件,io阻塞了)

5. rdb fork子线程导致的阻塞问题

关于AOF

redis的持久化有两种方式,一种是RDB,一种是AOF。

先说AOF,AOF说白了就是操作redis的日志文件,与MySQL的binlog有点类似,每个redis实例都有一份AOF文件,写入AOF有以下几种策略:no,always,every seconds。一般建议every seconds,毕竟no和always都太极端了。AOF的目的主要是用来当redis实例出现故障时,比如主机宕机,使用AOF来进行数据的恢复。

随着操作记录的增长,AOF也将随之增大,因此就有了AOF重写的机制,即rewrite,什么叫AOF rewrite,举个例子,假设有个key:value是carCount:1,对carCount设置了3次值,分别为

set carCount=2,set carCount=3,set carCount=4,那么最后carCount的值为4,如果不对AOF进行重写,那么将会有3条针对carCount的操作记录,为了减小AOF的大小,redis server会定期对AOF进行重写,重写之后,刚刚针对carCount的操作将会合并成1条,即set carCount=4(只保留最终的操作结果,省略了中间的过程)

AOF重写有多种策略,这里不做过多介绍。但是关于AOF增量写入和重写还是有坑的,笔者就曾经遇到过,现象就是redis每隔几分钟会出现几秒钟的阻塞,阻塞期间任何的读写操作都将无法正常进行,原因我们当时将AOF设置成每秒更新,即fsync,当fsync与rewrite同时进行的时候(操作同个文件啊),会导致IO性能受损而影响整个redis服务(redis是单线程),后来我们将AOF fsync的机制改成了在rewrite期间不进行fsync,以下是关于aof的相关配置:

############################## APPEND ONLY MODE ###############################

# 是否开启AOF,默认关闭(no)

appendonly yes

# 指定 AOF 文件名

appendfilename appendonly.aof

# Redis支持三种不同的刷写模式:

# appendfsync always #每次收到写命令就立即强制写入磁盘,是最有保证的完全的持久化,但速度也是最慢的,一般不推荐使用。

appendfsync everysec #每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,是受推荐的方式。

# appendfsync no    #完全依赖OS的写入,一般为30秒左右一次,性能最好但是持久化最没有保证,不被推荐。

#在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。

#设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no

no-appendfsync-on-rewrite no

#当前AOF文件大小是上次日志重写得到AOF文件大小的二倍时,自动启动新的日志重写过程。

auto-aof-rewrite-percentage 100

#当前AOF文件启动新的日志重写过程的最小值,避免刚刚启动Reids时由于文件尺寸较小导致频繁的重写。

auto-aof-rewrite-min-size 64mb

AOF还有一些坑,比如说AOF重写,Redis的AOF重写是通过fork出一个Redis进程来实现的,所以在一台服务器上最好要预留一半的内存(防止出现AOF重写集中发生,出现swap和OOM)。

再说说RDB与主从同步

在redis中,为了避免线程阻塞,在持久化RDB,主从同步,AOF重写时,redis会单开一个进程来处理。

对于RDB,当达到一定条件时,redis会进行持久化,此时会fork一个进程出来处理持久化,fork新的子进程时,虽说可以共享父进程的数据,但还是需要复制父进程的内存页表,如果redis的内存很大,那么这个内存页表也将是非常巨大的,可能达到百兆,此时进行复制,也需要时间,也会导致堵塞。

什么情况下会fork子进程

Master首次向slave同步数据,当master收到slave的syn请求,会fork一个子进程,将内存数据存储到文件上,然后再同步到slave。

AOF重写,重写并不会读AOF文件,而是直接使用内存中的数据,并归档日志。

持久化很容易造成阻塞,不管是AOF rewrite,还是RDB bgsave,都有可能会出现阻塞,原因是一般情况下,Redis服务设置了appendfsync everysec, 主进程每秒钟便会调用fsync(), 将数据写到存储硬件里. 但由于服务器正在进行大量IO操作, 导致主进程fsync()/操作被阻塞, 最终导致Redis主进程阻塞.解决方案这里就不多说了,上面已经有提到。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Redis 提供了多种不同级别的持久化方式: 了解 RDB 持久化和 AOF 持久化之间的异同是非常重要的, 以下...
    笑Skr人啊阅读 3,269评论 0 1
  • 本文翻译自官方文档http://redis.io/topics/persistence 。 Redis 持久化 R...
    六尺帐篷阅读 5,530评论 1 15
  • Redis持久化: 提供了多种不同级别的持久化方式:一种是RDB,另一种是AOF. RDB 持久化可以在指定的时间...
    不姓马的小马哥阅读 3,798评论 0 10
  • Redis 持久化: 常用的两种持久化 提供了多种不同级别的持久化方式:一种是RDB,另一种是AOF. RDB 持...
    边学边记阅读 4,826评论 0 1
  • 本文将从Redis的基本特性入手,通过讲述Redis的数据结构和主要命令对Redis的基本能力进行直观介绍。之后概...
    kelgon阅读 61,403评论 23 625