当前位置: 首页 > news >正文

做网站要用到的技术全球邮企业邮箱登录

做网站要用到的技术,全球邮企业邮箱登录,公司网络推广公司,华为手机业务最新消息今天生产机报内存爆满异常被叫过去查看问题#xff0c;通过各种排除最终定位到了Redis的内存碎片的问题#xff0c;这篇博客将详细介绍Redis内存碎片问题并给出最佳实践解决此问题。 Redis的内存碎片原理 先引用Redis官方的原话#xff1a; 当键被删除时#xff0c;Redis … 今天生产机报内存爆满异常被叫过去查看问题通过各种排除最终定位到了Redis的内存碎片的问题这篇博客将详细介绍Redis内存碎片问题并给出最佳实践解决此问题。 Redis的内存碎片原理 先引用Redis官方的原话 当键被删除时Redis 并不总是会释放归还内存给操作系统。这不是 Redis 的特别之处但这是大多数 malloc() 实现的工作方式。例如如果您用 5GB 的数据填充一个实例然后删除相当于 2GB 的数据则驻留集大小也称为 RSS即进程消耗的内存页数可能仍约为 5GB即使 Redis 声称用户内存约为 3GB。发生这种情况的原因是底层分配器无法轻松释放内存。例如通常大多数被删除的键都分配在与仍然存在的其他键相同的页面上。 内部碎片 首先介绍一下Redis内存管理原理操作系统内存管理思想一致是按照固定大小内存单位来分配而非按需分配为了减少频繁分配内存Linux下默认一次分配内存单位是4KBRedis的内存也是按照单位进行分配的例如范围有 8、16、32、64、128、256、512 字节为单位的大小也有大的内存单位如2KB、4KB等。例如存储一个键值对大小为29字节则会分配一个32字节的连续内存。那么就会造成3个字节的内存碎片这3个字节就不会被分配给其他键值对。这个是内在的原因称为内部碎片。 外部碎片 Redis分配内存时会根据需要申请一段连续的内存空间。但当Redis删除或修改数据时释放的内存空间并不一定能被立即重新利用尤其是当这些空闲内存空间大小不一致时就可能导致内存碎片的出现。Redis释放的内存有可能是不连续的这种不连续的内存很可能无法再次使用最终造成了内存的浪费这种空闲但是无法使用的内存便是内存碎片。比如说现在客户端存了100个键值对每个键值对大小53字节占用了一片连续的存储空间分配内存单位为32字节一共用了640个字节如果这个时候删除了中间的1个键值对那么中间将空出64个字节这64个字节可能对于大于32字节的键值对无法有效使用小于32字节的内存申请可能可以重新分配但是概率较小就会造成内存碎片。这些碎片称为外部碎片。 总结使用大白话说就是固定的内存分配单位就像一个个标准化的箱子箱子有8、16、32、64等规格的而你的物品假设为33规格的那么就需要连续的33内存存放因此申请内存的时候可以分配连续的328的内存但是如果中间只有32的内存另外的8是不连续的那么是无法分配这32内存只能空着。除非刚好有一个小于32的对象就可以被分配给到。 为了提高内存使用的效率Redis内部使用内存分配器来对内存的申请和释放进行管理。Redis使用的内存分配器默认是jemalloc。 会导致的问题 一般而言存取较小的键值对不太会导致内存碎片的问题但是如果存储非常大的复合数据结构Hash、Set、List并且对这些对象频繁的修改、删除等操作那么可能这个对象的实际大小假设为1.5GB但是存储系统分配给Redis用来存储这个对象的实际内存为8个GB。这就会导致内存爆满的问题而多出的这6.5GB其实就是内存碎片导致的。 查看内存碎片 登录到Redis客户端输入命令info或者info memory就可以查看到内存信息如下 127.0.0.1:7001 info# Server redis_version:7.2.5 ... # Memory used_memory:1853040 used_memory_human:1.77M used_memory_rss:9101312 used_memory_rss_human:8.68M used_memory_peak:1902032 used_memory_peak_human:1.81M used_memory_peak_perc:97.42% used_memory_overhead:1632076 used_memory_startup:1596680 used_memory_dataset:220964 used_memory_dataset_perc:86.19% allocator_allocated:2207416 allocator_active:2572288 allocator_resident:4976640 total_system_memory:1019793408 total_system_memory_human:972.55M used_memory_lua:31744 used_memory_vm_eval:31744 used_memory_lua_human:31.00K used_memory_scripts_eval:0 number_of_cached_scripts:0 number_of_functions:0 number_of_libraries:0 used_memory_vm_functions:32768 used_memory_vm_total:64512 used_memory_vm_total_human:63.00K used_memory_functions:184 used_memory_scripts:184 used_memory_scripts_human:184B maxmemory:0 maxmemory_human:0B maxmemory_policy:noeviction allocator_frag_ratio:1.17 allocator_frag_bytes:364872 allocator_rss_ratio:1.93 allocator_rss_bytes:2404352 rss_overhead_ratio:1.83 rss_overhead_bytes:4124672 mem_fragmentation_ratio:4.97 mem_fragmentation_bytes:7271160 mem_not_counted_for_evict:0 mem_replication_backlog:20508 mem_total_replication_buffers:20504 mem_clients_slaves:0 mem_clients_normal:3856 mem_cluster_links:10720 mem_aof_buffer:0 mem_allocator:jemalloc-5.3.0 active_defrag_running:0 lazyfree_pending_objects:0 lazyfreed_objects:0对上面字段解释如下 内存使用概述 used_memory: Redis 分配的内存总量字节。 used_memory_human: 以人类可读格式表示的 used_memory例如1.77M。 used_memory_rss: 从操作系统角度来看Redis 使用的实际内存驻留集大小。 used_memory_rss_human: 以人类可读格式表示的 used_memory_rss例如8.68M。 内存峰值 used_memory_peak: Redis 历史上使用的最大内存量。 used_memory_peak_human: 以人类可读格式表示的 used_memory_peak。 used_memory_peak_perc: 当前内存使用量相对于历史峰值的百分比。 内存开销 used_memory_overhead: Redis 的内存开销包括数据结构、客户端连接、备份等的内存。 used_memory_startup: Redis 启动时消耗的初始内存。 used_memory_dataset: 实际存储数据所使用的内存。 used_memory_dataset_perc: 数据集占用的内存相对于总内存使用量的百分比。 内存分配器 allocator_allocated: 通过内存分配器 jemalloc 分配的内存。 allocator_active: 内存分配器 jemalloc 实际使用的内存。 allocator_resident: jemalloc 分配的驻留内存。 系统内存 total_system_memory: 系统总内存。 total_system_memory_human: 以人类可读格式表示的系统总内存。 Lua 脚本 used_memory_lua: Lua 脚本使用的内存。 used_memory_vm_eval: Lua 脚本虚拟机使用的内存评估脚本时。 used_memory_lua_human: 以人类可读格式表示的 used_memory_lua。 used_memory_scripts_eval: 用于脚本评估的内存。 缓存的脚本 number_of_cached_scripts: 缓存的脚本数量。 number_of_functions: 注册的函数数量。 number_of_libraries: 加载的库数量。 虚拟内存 used_memory_vm_functions: 虚拟内存中函数使用的内存。 used_memory_vm_total: 虚拟内存总使用量。 used_memory_vm_total_human: 以人类可读格式表示的 used_memory_vm_total。 脚本和函数 used_memory_functions: 函数使用的内存。 used_memory_scripts: 脚本使用的内存。 used_memory_scripts_human: 以人类可读格式表示的 used_memory_scripts。 最大内存设置 maxmemory: Redis 配置的最大可用内存。 maxmemory_human: 以人类可读格式表示的 maxmemory。 maxmemory_policy: 内存超过最大值时的处理策略例如noeviction 表示不驱逐。 内存碎片率 allocator_frag_ratio: 内存分配器碎片率分配的内存与实际使用的内存之比。 allocator_frag_bytes: 内存分配器碎片字节数。 allocator_rss_ratio: 分配器驻留集大小比率分配的内存与驻留内存之比。 allocator_rss_bytes: 分配器驻留内存字节数。 rss_overhead_ratio: RSS 的开销比率。 rss_overhead_bytes: RSS 的开销字节数。 mem_fragmentation_ratio: 内存碎片总比率。 mem_fragmentation_bytes: 内存碎片字节数。 其他内存统计 mem_not_counted_for_evict: 不计入驱逐的内存。 mem_replication_backlog: 复制日志的内存。 mem_total_replication_buffers: 总复制缓冲区的内存。 mem_clients_slaves: 从客户端使用的内存。 mem_clients_normal: 正常客户端使用的内存。 mem_cluster_links: 集群链接使用的内存。 mem_aof_buffer: AOF追加文件缓冲区的内存。 mem_allocator: 使用的内存分配器如 jemalloc-5.3.0。 active_defrag_running: 活动的碎片整理状态是否正在运行。 lazyfree_pending_objects: 懒惰释放待处理对象的数量。 lazyfreed_objects: 懒惰释放的对象数量。最重要的是找到如下几个字段 INFO memory # Memory used_memory:1074741736 used_memory_human:1024.30M used_memory_rss:1997159792 used_memory_rss_human:1.86G … mem_fragmentation_ratio:1.86 这里有一个mem_fragmentation_ratio指标非常重要它表示的就是Redis当前的内存碎片率。它是used_memory_rss和used_memory相除的结果mem_fragmentation_ratio used_memory_rss/ used_memory 。used_memory_rss 等于碎片内存时间数据使用内存也就是操作系统分给Redis的实际内存。used_memory是Redis存储数据实际使用的内存。可以发现如果不存在碎片内存那么mem_fragmentation_ratio1但是这是最理想的情况一般而言这个值为1.2较为健康范围如下 1.5 mem_fragmentation_ratio 1内存碎片在合理范围内。mem_fragmentation_ratio 1.5需要考虑降低内存碎片率。mem_fragmentation_ratio 1Redis没有足够的内存可以使用了会导致redis一部分的内存数据会被换到swap中硬盘中之后redis访问swap中的数据延迟会变大性能下降。 解决方法 重启Redis 低于4.0-RC3版本的Redis 并没有内置的内存碎片整理工具。如果想要清理内存碎片可以通过重启的方式。当Redis重新启动时它会通过RDB持久化功能将数据存储到磁盘然后再从磁盘加载数据到内存这个过程可以有效地清理内存碎片。但这种方法会导致服务的临时中断。因此非常不推荐 配置 active-defrag Active-defrag主动碎片整理是 Redis 的一个功能用于在后台自动整理内存碎片提升内存利用率和性能。内存碎片是指内存块之间存在空隙导致内存使用效率下降。通过主动碎片整理Redis 可以减少这些空隙提高内存的有效利用。 从4.0-RC3版本开始引入了active-defrag 特性。可以在不重启的情况下自动进行碎片清理。开启配置如下此选项的默认值是关闭的激活碎片整理可能会占据一些 CPU 时间。手动开启如下 redis config set activedefrag yes 注意自动清理内存碎片的功能需要该Redis的内存分配器是jemalloc时才能启用。启用后需要同时满足下面2个参数的设置条件时才会触发自动清理。如果使用手动开启而redis.conf文件中没有配置那么会使用默认值进行碎片整理。 active-defrag-ignore-bytes 100mb # 默认100MB,表示内存碎片空间达到100MB时才会整理碎片 active-defrag-threshold-lower 10 # 默认10表示内存碎片空间占OS分配给redis的物理内存空间的比例达到10%时即碎片率为1.1才整理注意配置碎片自动整理会占用主线程如果配置不合理会导致主线程阻塞因此下面配置很关键。 active-defrag-cycle-min 1 # 默认1表示自动清理过程所用 CPU 时间的比例不低于1%保证清理能正常开展 active-defrag-cycle-max 25 # 默认25表示自动清理过程所用 CPU 时间的比例不高于 25%一旦超过就停止清理从而避免在清理时大量的内存拷贝阻塞 Redis导致响应延迟升高。另外一开始也可以在配置文件中启用和配置主动碎片整理可以在 Redis 配置文件redis.conf中设置以下选项下面的都是Redis7.0配置文件的默认值 active-defrag yes #启用或禁用主动碎片整理。 active-defrag-ignore-bytes 100mb #小于此值的内存片段将被忽略不进行碎片整理。 active-defrag-threshold-lower 10 # 低于此碎片率百分比时不进行碎片整理。碎片率1.1 active-defrag-threshold-upper 100 # 超过此碎片率百分比时最大限度进行碎片整理。碎片率2 active-defrag-cycle-min 1 # 最小碎片整理周期百分比控制最小CPU资源用于碎片整理。 active-defrag-cycle-max 25 #最大碎片整理周期百分比控制最大CPU资源用于碎片整理。 active-defrag-max-scan-fields 1000 #一次最大扫描字段个数其他关于内存的命令如下 在Redis客户端可以通过下面命令查看更加具体的内存情况 MEMORY HELP MEMORY DOCTOR - 输出内存问题报告 MEMORY USAGE key [SAMPLES count] - 估计key的内存使用情况 MEMORY STATS - 显示内存使用情况详细信息 MEMORY PURGE - 要求分配器释放内存主线程阻塞式执行 MEMORY MALLOC-STATS - 显示分配器内部统计信息查看一个bigkey的内存占用 memory usage mybigkey 51344216查看 内存详细情况 memory stats peak.allocated #redis启动以来allocator分配的内存峰值单位字节同INFO的used_memory_peak 2604763296 total.allocated #allocator 当前分配的内存总字节数同 INFO命令used_memeory 595052416 startup.allocated #Redis启动完成消耗的内存字节数同INFO的used_memory_startup 11403768 replication.backlog #Redis复制积压缓存区内存字节数同INFO的repl_backlog_size 0 clients.slaves #所有副本节点内存消耗总字节数(查询输出缓冲区连接内存消耗) 0 clients.normal #Redis所有常规客户端内存消耗总字节数(查询输出缓冲区连接内存消耗) 207724178 aof.buffer #当前和重写AOF缓冲区内存消耗总字节数同 INFO命令aof_buffer_length和aof_rewrite_buffer_length之和 0 lua.caches 30536 db.0 overhead.hashtable.main #每个数据库中元数据占用的额外内存字节数。redis的db就是一张hash表首先就是这张hash表使用的内存每一个key-value对都有一个dictEntry来记录他们的关系元信息便包含该db中所有dictEntry使用的内存 redis使用redisObject来描述value所对应的不同数据类型string、list、hash、set、zset那么redisObject占用的空间也计算在元信息中。 10823332 overhead.hashtable.expires #用于存储key的过期时间耗费的内存资源。 865120 db.1 overhead.hashtable.main 275384 overhead.hashtable.expires 77552 .... overhead.total #Redis 额外内存消耗总字节数例如startup.allocated, replication.backlog, clients.slaves, clients.normal, aof.buffer 以及管理keyspace使用的内部数据接口消耗的内存字节数 同INFO的used_memory_overhead 233196498 keys.count #整个redis实例key的个数 183900 keys.bytes-per-key #每个key平均字节数 3173 dataset.bytes #Redis 实例中数据占用的总字节数计算方法total.allocated减去overhead.total 361855918 dataset.percentage #Redis 数据消耗内存占总内存的百分比 61.998931884765625 peak.percentage #当前内存消耗占峰值内存消耗的百分比 22.844778060913086 fragmentation #同 INFO的 mem_fragmentation_ratio 0.96442300081253052注意以上命令是使用了内存分配器 jemalloc的情况下才能使用Redis默认使用的是jemalloc分配器。 Redis 使用 jemalloc 作为默认的内存分配器。jemalloc 会将内存划分为不同大小的块并在需要时分配和释放这些内存块。然而在某些情况下jemalloc 可能不会立即将未使用的内存返回给操作系统这可能会导致内存看起来被占用而实际并未被使用。通过 MEMORY PURGE命令可以强制 jemalloc 进行内存清理将不再使用的内存返回给操作系统。但这个命令是主线程执行的会阻塞其他命令。 最后注意在线上生产机上排查BigKey时最后把RDB文件拉取下来分析禁止在生产机Master上使用如下命令寻找BigKey主线程执行阻塞其他命令非要用可以在Slave节点操作 redis-cli -p 9001 -a 12345678 --bigkeys最佳实践 看了这么多有没有想一个问题——为什么Redis官方默认配置设置activfrag no 。原因就是Redis内置了jemalloc这样的内存分配神器它能够对已占用的空闲内存碎片利用到极致Redis官方建议我们采用“鸵鸟算法”即啥都不用做只需要设置合适的maxmemory即可即使碎片率非常大后续的内存也是安全的因为jemalloc会自己去利用碎片。这里的逻辑就是Redis在删除键值的时候会将内存还给jemalloc而不是操作系统。这部分内存可能是碎片也可能不是如果Redis需要申请内存则先看内存分配器是否有足够的可分配内存。额外的碎片过多是因为Reids释放了大量内存但jemalloc手中的大量的内存没有及时返回给操作系统这可能是是因为没有设置合适的maxmemory原因。这个时候其实Redis继续存入键值对并不会向操作系统申请内存而是向jemalloc申请。因此如果不设置maxmemory那么Redis可能无限地向操作系统申请内存而不是jemalloc中的碎片内存。下面给出Redis官方原话结合前面最开始的Redis原话阅读 但是jemalloc分配器非常智能能够重用空闲的内存块因此在您释放5GB数据集中的2GB后当您再次开始添加更多键时您会看到RSS驻留集大小保持稳定不会随着您添加多达2GB的额外键而进一步增长。分配器基本上是试图重用先前逻辑上释放的 2GB 内存。正因为如此当内存使用量在峰值时远大于当前使用的内存时碎片率并不可靠。碎片率的计算方法是实际使用的物理内存RSS值除以当前使用的内存量Redis执行的所有分配的总和。 由于RSS 反映的是峰值内存因此当虚拟使用的内存较低因为释放了大量键/值但RSS较高时该比率将非常高RSS / mem_used。如果maxmemory没有设置Redis会继续按其认为合适的方式分配内存因此它会逐渐耗尽所有可用内存。因此通常建议配置一些限制。 最佳实践就是设置 maxmemory 0.8*系统内存并且设置数据淘汰策略LRU算法来删除部分key释放空间。最后如果使用碎片整理activefrag yes CPU需要做出一定的让步。慎重使用 以上有误麻烦指正 参考来源 https://cloud.tencent.com/developer/article/2343994 https://blog.csdn.net/qq_41372835/article/details/130046321
http://www.pierceye.com/news/450409/

相关文章:

  • 怎么做优惠卷网站公司做网站大概多少钱
  • 哪些网站是单页面应用程序在线做网站流程
  • 公司网站设计维护官方网站建设需要做哪些东西
  • 网站被k还能不能在百度做推广wordpress主题网址导航葬爱
  • 成都网站制作和建设辽阳北京网站建设
  • 合肥金融网站设计网页制作工具分哪两类
  • 专业营销型网站定制wordpress菜单绑定模板
  • 网站建设公司找哪家好石家庄网站改版
  • 建立一个网站要多久网页界面ps制作步骤
  • 珠海网站建设费用自己做网站切入地图
  • 个人在线视频播放网站搭建软件属于网站开发吗
  • 小米的企业网站建设思路c2c的网站
  • 网站设计书籍做网站的基础
  • 买下云服务器怎么做网站官方网站怎么查询
  • 手机版企业网站php西宁做网站公司排名
  • 微网站如何做推广做淘宝客网站需要备案吗
  • 天津网站制作重点windows与wordpress
  • 可以查企业备案的网站吗佛山住房和城乡建设部网站官网
  • 和初中生做视频网站怎么进入追信魔盒网站开发软件
  • 邯郸开发网站有哪些阳江市房产信息网
  • 快速网站推广公司丹阳房产网二手房
  • 做一个卖东西的网站黄村做网站的公司
  • 网站增长期怎么做广州seo推广优化
  • 怎么做拍卖网站吗免费网站推广入口
  • 农产品网站建设的主要工作岳阳seo招聘
  • 每年网站备案抽查惠州营销网站建设
  • 四川网站建设seo友汇网网站建设
  • 企业家居网站建设做公司网站方案
  • 特性设计的网站营销型网站建设的五力原则
  • 网站布局设计工具装修室内设计培训学校