redis-为什么redis速度快?
为什么redis速度快1redis的核心瓶颈从不是cpu而是网络IOredis的单线程模型指的是网络IO与键值对读写是用单线程完成的。之所以使用单线程支撑如此高的并发关键在于核心事件处理模型“IO多路复用”IO多路复用redis利用操作系统提供的机制让单个线程可以同时监听多个客户端连接的”读写事件“有事件发生时就去处理没有事件就阻塞等待或去处理其他任务。非阻塞IO:一种不等待的IO模型当线程调用 read / write / accept 等系统调用时如果数据尚未准备好或缓冲区满内核会立即返回一个错误而不是将线程挂起等待仍可执行其他任务。非阻塞 I/O 不让单线程卡在某个慢连接上多路复用告诉它哪个连接准备好了两者结合实现极致性能。使得redis可以高效处理成千上万的并发连接而不创建大量线程。redis性能瓶颈绝大部分情况下是网络IO而不是CPU计算。单线程是解决网络并发高效方式之一避免多线程在共享数据时复杂的加锁机制。2单线程与redis6.0的多线程随着网络硬件的发展网络IO延迟大大降低同时redis存储的数据也越来越复杂某些情况cpu消耗开始显现单线程面对这些慢操作时会阻塞所有请求。redis6.0的多线程多线程不是将读写命令的执行变成多线程多线程只用于处理网络IO的读写核心命令执行依旧是单线程。目的是为了利用多核CPU加速网络包的解析又保持了核心数据结构的安全性避免并发竞争。3总结所以真正拖垮redis的不是高QPS而是慢查询关键是命令的复杂度如keys * ,大集合交集运算等这些命令会让redis的单线程陷入长时间阻塞。虽然cpu不是性能瓶颈但内存是。如内存不足导致的内存碎片写时复制的内存抖动频繁的淘汰策略才是生产环境更常见性能问题。RDB与AOF的持久化机制尤其AOF的刷盘策略会引入磁盘IO,这才是可能成为瓶颈的地方高 QPS如 10 万次 GET单次耗时 约10 微秒一次慢查询如 KEYS *可能数秒。虽然 Redis 是内存数据库但内存不足不会直接导致 Redis 变慢而是引发一系列连锁反应最终表现为高延迟、高 CPU、甚至宕机。性能问题内存碎片成因频繁的增删改、key 过期等解决# 查看碎片率redis-cli INFO memory|grepmem_fragmentation_ratio# 主动整理Redis 4.0redis-cli MEMORY PURGE# 配置自动碎片整理activedefragyesactive-defrag-ignore-bytes 100mb写时复制Copy-on-WriteCOW内存抖动场景BGSAVERDB或 BGREWRITEAOF 时fork 子进程问题主进程写数据时操作系统会复制被修改的内存页导致内存瞬间翻倍影响内存不足时触发 swap 或 OOM Killer解决避免在高峰期间执行持久化操作调优 repl-diskless-sync 等参数增加物理内存或使用从库持久化频繁淘汰eviction触发maxmemory 达到上限且 maxmemory-policy 为 allkeys-lru / volatile-lru 等行为Redis 在每次写入命令时尝试淘汰数据消耗 CPU表现写入延迟突增QPS 骤降解决提高 maxmemory优化淘汰策略缓存场景用 allkeys-lru数据不可丢用 noeviction监控 evicted_keys 指标案例一KEYS * 导致生产瘫痪现象Redis CPU 飙升到 100%所有超时原因新入职 DBA 在 Master 上执行 KEYS *实例有 2 亿 Key后果阻塞 30 秒触发哨兵误判主库下线切换后数据丢失改进禁用 KEYS提供 SCAN 接口给运维脚本案例二内存碎片率 300% 引发 swap现象used_memory 8GB但 used_memory_rss 24GB服务器频繁 swap原因业务频繁更新 Hash 字段jemalloc 产生大量外部碎片解决执行 MEMORY PURGE开启 activedefrag碎片率降至 1.1案例三大 Key 删除引发阻塞现象业务低峰期执行 DEL 一个 5000 万成员的 Set阻塞 8 秒导致从库复制中断解决改用 UNLINK异步删除或分批 SPOP核心结论真正拖垮 Redis 的是O(N) 命令和内存使用不当。高 QPS 并不可怕可怕的是一个 KEYS * 或一个未拆分的大 Hash。生产中应该设置禁用危险命令拆分 BigKey监控内存碎片和淘汰持久化操作移至从库使用 UNLINK 替代 DELbigkey优化1拆分bigkey按业务维度拆分多个小key按需查询字段不要一次拉取全量数据2数据压缩缩减value存储空间部分文本超长json业务数据无法拆分时开启压缩使用snappy、gzip等压缩算法压缩后value占用空间能砍半或者更多缓解内存负载。但压缩解压缩会影响cpu算力适用低频率访问的历史数据归档日志。高频数据不建议压缩。3更换适配数据结构弃用String像商品多规格多属性数据改用hash结构更优主key固定product:1001name、price单独作为file字段单点取值不用解析整个json规避bigkey问题。list、set也可以按需替换string场景4过期控制定时巡检、提前预防冗余bigKey很多bigkey源于过期数据遗留注销用户缓存临时业务缓存到期未回收。日常开发给缓存配置合理TTL依托redis过期淘汰机制自动失效搭配定时脚本巡检定时扫描清理无用冗余key从·源头杜绝大key持续堆积。持久化方式RDB与AOF是如何工作的1RDB快照工作方式与写时复制什么是RDB :按一定时间间隔将某一时刻的数据生成快照以二进制压缩格式写入磁盘文件dump.rdb。如何触发RDB:1、到达配置⽂件中默认的快照配置时2、主从复制3、save命令 主线程直接执行快照生成过程中阻塞所有客户端请求直至快照完成。通常用于停机维护场景。4、bgsave命令不会阻塞主进程异步生成快照主进程fork一个子进程负责将内存数据写入rdb文件。主进程继续处理客户端请求不受影响。写时复制技术:fork子线程时操作系统使用写时复制技术。1、子进程创建时复制主进程页表不复制内存数据与主进程共享同一块物理内存页。父子进程所有内存页全部标为只读。2、当主进程需要修改某个内存页时操作系统会将该页复制给主进程延时复制子进程依然指向原内存页。这意味着子进程持久话的是fork那一刻的内存快照主进程修改不会影响快照的一致性。3、子进程遍历所有数据将键值对序列化为rdb格式写入临时文件完成后主线程将临时文件重命名为目标RDB文件写时复制问题写时复制但如果在生成快照期间有大量写操作操作系统会频繁复制内存页增加内存开销与cpu消耗。但内存不一定翻倍只复制修改的内存页。页表Page Table每个进程拥有独立的页表。告诉cpu页表中虚拟地址对应哪块物理地址优点1文件体积小适合全量备份异地容灾2与AOF相⽐⼤数据量恢复速度快直接加载到内存3备份时性能快不影响主线程写时复制缺点1定时备份策略导致数据丢失风险默认配置900秒内至少1次修改300秒内至少10次修改60秒内至少10000次修改2宕机时丢失最后一次快照后所有数据3写时复制问题2AOF日志工作机制与重写原理什么是AOF :通过记录写命令方式持久化当redis执行一条写命令如sethset等就将该命令追加至AOF文件末尾。AOF工作过程1执行完写命令后将写命令先写入缓冲区根据同步策略决定何时刷盘。2文件刷盘 appendfsync同步策略always每个命令都刷一次盘最多丢一个命令性能最差everysec每秒刷一次盘默认策略最多丢失一秒数据性能与安全的平衡选择no由操作系统决定何时刷盘性能最好丢失数据最多3AOF文件记录所有命令随着时间增加文件会不断增长需要定期重写压缩体积。重写核心思想不读取就AOF文件直接读取当前内存数据用最少量命令记录数据。如一个key被反复修改100次重写时只记录最终值一条set命令。重写过程1主进程fork一个子进程子进程根据当前内存数据生成新的AOF文件。2重写期间主进程收到写命令会同时记录到旧的AOF缓冲区追加至旧AOF文件与重写缓冲区rewrite_buffer3子进程完成后主进程将重写缓冲区所有命令追加到新的AOF文件然后新的AOF文件原子替换旧的AOF文件保证数据不丢失。追加旧 AOF 文件保证重写期间的写命令实时持久化防止宕机丢数据。重写缓冲区记录增量命令用于重写完成后追加到新 AOF 文件保证新文件完整优点1支持秒级持久化2数据丢失极低3文件可读性强4单个AOF⽂件太⼤时Redis会⾃动切换新的⽇志⽂件缺点1文件体积大写操作频繁AOF备份性能通常⽐RDB更慢。2数据恢复时重放命令较慢3持久化策略选型与混合持久化生产环境通常 RDB 与AOF同时开启redis重启时优先使用AOF文件恢复因为AOF文件丢失数据更少。如果AOF未开启使用RDB文件恢复。如果AOF文件毁坏使用redis-check-AOF 工具对AOF文件修复移除损坏的尾部命令。如果文件损坏严重可弃用AOF改用RDB。RDB用于定期全量备份应对大规模快速恢复场景AOF保证增量数据极致安全减少意外丢失。redis4.0引入了混合持久化策略AOF与RDB的结合AOF重写时不是生成纯AOF格式的命令而是将当前内存数据先以RDB格式写入AOF文件的开头在追加重写缓冲区增量命令。恢复时先加载RDB部分快速恢复大部分数据在重放后面的增量命令。兼顾了RDB恢复快AOF丢失数据少的特点。4生产环境下如何选择1数据不重要可以不开启持久化只当缓存使用2可以容忍几分钟数据丢失可以之开启RDB配置快照间隔5分钟/十分钟3不能容忍数据丢失必须开启AOF配和everysec最多丢失1秒数据4重要数据同时开启AOF与RDBRDB用于快速备份和恢复演练AOF使用宕机恢复。5对数据安全极高场景开启混合持久化同时配置主从复制和定期备份到远程存储。性能与安全的权衡方面AOF的everysec适合绝大数场景。always策略会严重降低写性能单机写QPS可能从10万降至1万非必要不适用RDB的bgsave虽然不堵塞主线程但fork子进程在内存较大时耗时较长如30G内存fork可能需要几百毫秒甚至几秒。建议业务低峰期执行RDB快照 。几个问题RDB快照生成时redis还能处理请求吗bgsave与save核心区别bgsave如何做到不堵塞线程写时复制的作用?大量写操作会导致内存翻倍吗AOF文件膨胀怎末办AOF重写是新请求如何罗盘AOF重写底层逻辑appdendfsync同步策略双持久化恢复优先级AOF文件损坏的修复混合持久化的价值