Redis——常见问题
2018-07-14 本文已影响0人
黄金矿工00七
fork操作
一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
我们知道:
- fork操作是同步的,所以fork操作有可能会阻塞主进程
- 内存越大,耗时越长(与机器类型有关)
- 改善fork :
- 优先使用物理机或者高效支持fork的虚拟化技术
- 控制redis的maxmemory
- 合理配置Linux内存的分配策略
- 降低fork频率 :降低AOF自动重写的频率以及不必要的全量复制
子进程开销和优化
- CPU:
- 开销 :RDB和AOF文件生成,属于CPU密集型
- 优化 : 不做CPU绑定,不和CPU密集型应用部署在一起
- 单机多部署时 :避免大量RDB和AOF
- 内存 :
- 开销 :frok内存开销,cow策略(Linux的fork()使用写时拷贝(copy-on-write)页实现。写时拷贝是一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝。只有在需要写入的时候,数据才会被复制,从而使各个进程拥有各自的拷贝。也就是说,资源的复制只有在需要写入的时候才进行,在此之前,只是以只读方式共享。这种技术使地址空间上的页的拷贝被推迟到实际发生写入的时候。)
- 硬盘 :
- 开销 :AOF 和RDB
- 优化 :
- 不要和高硬盘负载服务部署在一起:存储服务、消息队列等
- no-appendfsync-on-rewrite = yes(指定是否在后台aof文件rewrite期间调用fsync,默认为no,表示要调用fsync(无论后台是否有子进程在刷盘)进行save操作。Redis在后台写RDB文件或重写afo文件期间会存在大量磁盘IO,此时,在某些linux系统中,调用fsync将 AOF 文件保存到磁盘中可能会阻塞。)
AOF追加阻塞
- 在AOF_FSYNC_NO模式下:
在这种模式下,SAVE 只会在以下任意一种情况中被执行:
• Redis 被关闭
• AOF 功能被关闭
• 系统的写缓存被刷新(可能是缓存已经被写满,或者定期保存操作被执行)
这三种情况下的 SAVE 操作都会引起 Redis 主进程阻塞。 - 在AOF_FSYNC_EVERYSEC保存模式下,SAVE 原则上每隔一秒钟就会执行一次,因为 SAVE 操作是由后台子线程调用的,所以它不会引起服务器主进程阻塞。
在实际运行中,程序在这种模式下对 fsync或 fdatasync 的调用并不是每秒一次,它和调用 flushAppendOnlyFile 函数时 Redis 所处的状态有关。
每当 flushAppendOnlyFile 函数被调用时,可能会出现以下四种情况:- 子线程正在执行 SAVE ,并且:
- 这个 SAVE 的执行时间未超过 2 秒,那么程序直接返回,并不执行 WRITE 或新的SAVE 。
- 这个 SAVE 已经执行超过 2 秒,那么程序执行 WRITE ,但不执行新的 SAVE 。
注意,因为这时 WRITE 的写入必须等待子线程先完成(旧的) SAVE ,因此这里WRITE 会比平时阻塞更长时间。
- 子线程没有在执行 SAVE ,并且:
- 上次成功执行 SAVE 距今不超过 1 秒,那么程序执行 WRITE ,但不执行 SAVE 。
-
上次成功执行 SAVE 距今已经超过 1 秒,那么程序执行 WRITE 和 SAVE。
AOF追加阻塞