美文网首页
Redis的一些坑

Redis的一些坑

作者: 思想在散步 | 来源:发表于2017-09-07 17:06 被阅读0次

出现问题常见的原因有:

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的一些坑

      本文链接:https://www.haomeiwen.com/subject/fjgijxtx.html