thinkphp5网站开发自己怎么给网站做优化排名
thinkphp5网站开发,自己怎么给网站做优化排名,做网站外包好吗,手举牌战队图片在线制作Redis 删了 2GB 数据#xff0c;内存却纹丝不动#xff1f;深挖内存碎片的真相你有没有遇到过这样诡异的场景#xff1a;明明已经删除了大量 Key#xff0c;用 top 命令一看#xff0c;Redis 进程内存占用依然高居不下#xff1b;或者 info memory 告诉你 Redis 存储的数…Redis 删了 2GB 数据内存却纹丝不动深挖内存碎片的真相你有没有遇到过这样诡异的场景明明已经删除了大量 Key用top命令一看Redis 进程内存占用依然高居不下或者info memory告诉你 Redis 存储的数据只有 1GB但操作系统却显示进程吃掉了 3GB 内存还在报内存不足的错误别慌今天我们就来拆穿这个让无数 Redis 用户抓狂的内存幻术——内存碎片。一、先从一个灵魂问题开始假设你的 Redis 实例保存了5GB 的数据现在你删除了2GB此时 Redis 进程占用的内存会降到 3GB 左右吗答案大概率不会。很可能你用top命令看到的 RSS进程实际占用的物理内存页数依然在5GB 左右徘徊即便 Redis 里存储的数据只剩 3GB。这不是 Bug也不是 Redis 在耍你——背后有一套完整的内存管理逻辑。搞清楚这套逻辑你才能真正驾驭 Redis。二、Redis 的内存从哪来又到哪去了2.1 先设好 maxmemory这是底线在深入原理之前有一条铁律要先说清楚# 通过命令动态设置CONFIG SET maxmemory 100mb# 或者在 redis.conf 中配置maxmemory 100mb一定要设置maxmemory如果不设Redis 会无限制地为新数据分配内存直到系统内存耗尽最终导致应用程序报错OOM。虽然不至于宕机但你的业务已经完蛋了。当内存达到上限时会触发内存淘汰策略maxmemory_policy决定删除哪些数据腾出空间。2.2 Redis 的内存都花在哪里了Redis 进程的内存消耗主要由四个部分构成Redis 进程内存 ├── 自身启动内存可忽略很小 ├── 对象数据内存大头存储所有 Key-Value 数据 ├── 缓冲区内存 │ ├── client-output-buffer-limit客户端输出缓冲区 │ ├── 复制积压缓冲区主从复制用 │ └── AOF 缓冲区持久化用 └── 内存碎片隐形杀手对象数据内存占比最大所有 Key-Value 都在这里缓冲区内存大流量场景容易失控需要重点监控内存碎片隐形杀手明明有空间却无法使用2.3 用info memory看透内存状况想知道 Redis 内存的真实情况info memory是你最好的朋友127.0.0.1:6379info memory# Memoryused_memory:1132832# Redis 存储数据实际占用的内存used_memory_human:1.08M# 人类可读形式used_memory_rss:2977792# 操作系统视角进程占用的物理总内存RSSused_memory_rss_human:2.84M used_memory_peak:1183808# 历史内存占用峰值used_memory_peak_human:1.13M used_memory_lua:37888# Lua 引擎消耗的内存maxmemory:2147483648# 最大可用内存字节maxmemory_human:2.00G maxmemory_policy:noeviction# 当前内存淘汰策略mem_fragmentation_ratio:2.79# 内存碎片率重点关注其中最关键的指标是mem_fragmentation_ratio也就是内存碎片率内存碎片率 used_memory_rssOS 分配给 Redis 的物理内存 ÷ used_memoryRedis 实际存储数据的内存上面的例子里碎片率是2.79意味着操作系统分配给 Redis 2.84MB 的物理内存但 Redis 只用其中 1.08MB 存了数据另外 1.76MB 都是碎片和开销。三、内存碎片是什么一个电影院的比喻光说数字可能还不够直观来个生活化的例子。你和漂亮小姐姐去电影院看电影肯定希望坐在一起。现在影厅有8 个座位已经卖出了 4 张票还剩 4 个空位。但你打开选座界面一看座位分布 [已售] [空闲] [已售] [空闲] [已售] [空闲] [已售] [空闲]好巧不巧买票的人每隔一个座位买一张导致4 个空座位全是分散的无法买到两张相邻的票。你有再多的钱也买不到两张连座。内存碎片的本质就是这个问题空闲内存总量够用但不是连续的无法满足新的数据存储请求。四、内存碎片是怎么产生的内存碎片的产生主要有两大根源。4.1 内存分配器的好意Redis 默认使用jemalloc作为内存分配器也可选 glibc、tcmalloc。内存分配器并不是你要多少就给多少而是按照固定大小的内存块分配比如 8 字节、16 字节、32 字节……2KB、4KB 等固定档位。当你申请内存时jemalloc 会分配最接近且不小于申请量的固定大小空间。举个例子程序申请 1.5 KB → jemalloc 分配 2 KB → 多出 0.5 KB碎片 程序申请 22 字节 → jemalloc 分配 32 字节 → 多出 10 字节碎片这么做并非毫无道理——减少内存分配次数提升性能。比如你先写入 22 字节jemalloc 分配了 32 字节。后续再写入 10 字节时不需要再向操作系统申请内存直接用之前剩余的空间就行了。但代价就是每次分配都会产生少量边角料碎片。4.2 Key-Value 频繁修改和删除这是碎片产生的更主要原因。场景一修改 Key 导致碎片原始字符串占用 32 字节的内存块 修改后字符串只需要 20 字节 → 释放了 12 字节的空间 下一个请求需要申请 13 字节 → 刚释放的 12 字节空间不够用只能另外申请新空间 → 原来的 12 字节沦为碎片场景二删除 Key 导致 RSS 不降删除 Key 之后Redis 并不会立即把内存归还给操作系统。原因是底层内存分配器的管理机制——大多数已删除的 Key 依然与其他有效 Key 分配在同一个内存页中操作系统无法单独回收其中一部分内存页。这就解释了为什么删了 2GB 数据RSS 依然显示 5GB。不过这里有个好消息当你再次往 Redis 写入数据时RSS 不会继续增长因为内存分配器会优先复用之前释放的内存块。五、碎片率多少算危险mem_fragmentation_ratio 1 → 异常物理内存不够用Redis 在用 swap性能会极差 1 ≤ mem_fragmentation_ratio 1.5 → 正常合理范围 mem_fragmentation_ratio ≥ 1.5 → 警告碎片超过 50%需要处理当碎片率大于 1.5意味着操作系统分配给 Redis 的内存中有超过 1/3 都是碎片不仅是资源浪费还可能导致有内存却存不了数据的诡异问题。六、解决内存碎片的两种方式6.1 重启大法简单粗暴慎用最直接的方式就是重启 Redis重启后内存重新分配碎片自然消失。但代价不小未开启持久化数据全部丢失开启了持久化重启后需要用 RDB 或 AOF 恢复数据数据量大时恢复时间很长期间服务不可用高可用性大打折扣除非数据允许丢失或数据量极小否则不建议把重启当成常规手段。6.2 自动清理内存碎片Redis 4.0 推荐方案Redis 4.0 版本引入了自动内存碎片清理机制Active Defragmentation。原理类比电影院的场景已经在电影院里的观众互相协商把座位挪一挪让大家都聚在一起空出来一块连续的座位区。对 Redis 而言操作系统把分散在不同位置的数据依次挪动拼接到连续的内存空间再把原来占用的空间释放出来形成大块连续的空闲内存。开启自动清理CONFIG SET activedefragyes触发清理的条件两个条件同时满足才会触发# 条件一碎片占用的内存绝对值达到 200MBactive-defrag-ignore-bytes 200mb# 条件二碎片空间占 Redis 总分配空间的比例超过 20%active-defrag-threshold-lower20控制清理对性能的影响自动清理涉及内存数据的复制移动会占用 CPU 资源影响 Redis 处理请求的性能。通过以下两个参数控制 CPU 占用比例# 清理过程中占用 CPU 的时间比例下限保证清理任务能正常推进active-defrag-cycle-min20# 最少占用 20% CPU# 清理过程中占用 CPU 的时间比例上限超过立即停止避免影响业务active-defrag-cycle-max50# 最多占用 50% CPU这两个参数让清理任务在彻底清理和不影响业务之间找到平衡点——既不会因为清理任务太猛拖慢业务也不会因为资源太少导致碎片永远清不干净。七、一张图搞懂全流程Redis 内存问题排查与处理流程 │ ▼ 执行 info memory 查看 mem_fragmentation_ratio │ ┌───────┴───────┐ │ │ 1.5 ≥ 1.5 正常 碎片过多 无需处理 需要处理 │ ┌─────────┴──────────┐ │ │ 能接受短暂不可用 不能接受停服 │ │ 重启 开启自动碎片清理 数据量小时可用 activedefrag yes 合理设置触发条件 合理设置 CPU 占用上限八、完整配置参考# 1. 限制 Redis 最大内存必须设置maxmemory 4gb maxmemory_policy allkeys-lru# 2. 开启自动内存碎片清理activedefragyes# 3. 触发清理的条件active-defrag-ignore-bytes 200mb active-defrag-threshold-lower20# 4. 控制清理对性能的影响active-defrag-cycle-min20active-defrag-cycle-max50性能问题排查 Tip如果你发现 Redis 某段时间内响应变慢怀疑是碎片清理在捣鬼先看下activedefrag是否开启再把active-defrag-cycle-max调小比如从 50 调到 25观察延迟是否恢复正常。九、总结问题原因解决方案删数据后 RSS 不降内存分配器不立即归还内存给 OS正常现象再写入数据时会复用碎片率 1.5jemalloc 按固定块分配 频繁删改 Key开启activedefrag yes自动清理影响性能内存数据复制移动消耗 CPU调小active-defrag-cycle-maxRedis 报内存不足未设置 maxmemory立即设置maxmemory 淘汰策略记住这个公式和这个阈值内存碎片率 used_memory_rss ÷ used_memory 碎片率 1.5 → 无需处理 碎片率 ≥ 1.5 → 开启自动清理Redis 删了数据内存没降不是 Redis 的锅是内存碎片在作祟。搞懂原理配好参数让 Redis 的每一个字节都物尽其用。如果这篇文章对你有帮助欢迎点赞收藏有 Redis 内存相关的坑踩过的评论区聊聊