首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【redis】redis内存管理、淘汰机制、内存优化

【redis】redis内存管理、淘汰机制、内存优化

作者头像
看、未来
发布2020-08-26 22:25:48
1.2K0
发布2020-08-26 22:25:48
举报

文章目录

- [配置redis](https://blog.csdn.net/#redis_2)
- [最大内存限制](https://blog.csdn.net/#_8)
- [查看redis内存相关信息:INFO memory](https://blog.csdn.net/#redisINFO_memory_22)
- [内存都去哪儿了?还没好好使用,就爆了](https://blog.csdn.net/#_34)
- [内存回收策略](https://blog.csdn.net/#_48)
    - [过期键值](https://blog.csdn.net/#_51)
        - [Redis如何淘汰过期的keys](https://blog.csdn.net/#Rediskeys_52)
- [内存移除控制策略](https://blog.csdn.net/#_70)
    - [8个解决方方案](https://blog.csdn.net/#8_72)
    - [回收进程如何工作](https://blog.csdn.net/#_105)
    - [近似LRU算法](https://blog.csdn.net/#LRU_113)
- [内存优化](https://blog.csdn.net/#_118)
    - [使用32位的redis](https://blog.csdn.net/#32redis_119)
    - [位级别和字级别的操作](https://blog.csdn.net/#_123)
    - [尽可能使用散列表](https://blog.csdn.net/#_130)

配置redis

如果想要运行一个内存高效的 Redis 数据库,首先需要理解那些在 redis.conf 配置文件中所有内存相关的指令。redis.conf 文件为大多数指令提供了丰富的内联文档,使得一些复杂的内存优化选项易于理解、更改和测试。

传送门:redis.conf翻译与配置内存管理部分

大多数 Redis 配置指令可以在运行时通过 CONFIG SET 命令进行设置。

最大内存限制

Redis使用 maxmemory 参数限制最大可用内存,默认关闭。

限制内存的目的主要 有:

用于缓存场景,当超出内存上限 maxmemory 时使用 LRU 等删除策略释放空间。
防止所用内存超过服务器物理内存。

maxmemory 限制的是Redis实际使用的内存量,也就是 used_memory统计项对应的内存。由于内存碎片率的存在,实际消耗的内存 可能会比maxmemory设置的更大,实际使用时要小心这部分内存溢出。redis.conf翻译与配置(内存碎片部分)

Redis默认无限使用服务器内存,为防止极端情况下导致系统内存耗 尽,建议所有的Redis进程都要配置maxmemory。 在保证物理内存可用的情况下,系统中所有Redis实例可以调整 maxmemory参数来达到自由伸缩内存的目的。

查看redis内存相关信息:INFO memory

当 memfragmentationratio > 1 时,说明有部分内存并没有用于数据存储,而是被内存碎片所消耗,如果该值很大,说明碎片率严重。当 memfragmentationratio < 1 时,这种情况一般出现在操作系统把 Redis 内存交换 (swap) 到硬盘导致,出现这种情况要格外关注,由于硬盘速度远远慢于内存,Redis 性能会变得很差,甚至僵死。

当 Redis 内存超出可以获得内存时,操作系统会进行 swap,将旧的页写入硬盘。从硬盘读写大概比从内存读写要慢5个数量级。used_memory 指标可以帮助判断 Redis 是否有被swap的风险或者它已经被swap。

建议要设置和内存一样大小的交换区,如果没有交换区,一旦 Redis 突然需要的内存大于当前操作系统可用内存时,Redis 会因为 out of memory 而被 Linix Kernel 的 OOM Killer 直接杀死。虽然当 Redis 的数据被换出 (swap out) 时,Redis的性能会变差,但是总比直接被杀死的好。:建议自:https://redis.io/topics/admin

内存都去哪儿了?还没好好使用,就爆了

1.自身内存:redis自身运行所消耗的内存,一般很小。

2.对象内存:这是redis消耗内存最大的一块,存储着用户所有的数据。

3.缓冲内存:缓冲内存主要包括:客户端缓冲、复制积压缓冲区、AOF缓冲区。

客户端缓冲:是指客户端连接redis之后,输入或者输出数据的缓冲区,其中输出缓冲可以通过配置参数参数client-output-buffer-limit控制。

复制积压缓冲区:一个可重用的固定大小缓冲区用于实现部分复制功能,根据repl-backlog-size参数控制,默认1MB。对于复制积压缓冲区整个主节点只有一个,所有的从节点共享此缓冲区,因此可以设置较大的缓冲区空间,如100MB,这部分内存投入是有价值的,可以有效避免全量复制。

AOF缓冲区:这部分空间用于在Redis重写期间保存最近的写入命令,AOF缓冲区空间消耗用户无法控制,消耗的内存取决于AOF重写时间和写入命令量,这部分空间占用通常很小。

4.内存碎片:当然,这是所有内存分配器无法避免的通病,但是可以优化。

如果对这方面有想法的话:走近STL – 空间配置器,STL背后的故事

内存回收策略

Redis 回收内存大致有两个机制:一是删除到达过期时间的键值对象;二是当内存达到 maxmemory 时触发内存移除控制策略,强制删除选择出来的键值对象。

过期键值

Redis如何淘汰过期的keys

Redis keys过期有两种方式:被动和主动方式。

当一些客户端尝试访问它时,key会被发现并主动的过期。

当然,这样是不够的,因为有些过期的keys,永远不会访问他们。 无论如何,这些keys应该过期,所以定时随机测试设置keys的过期时间。所有这些过期的keys将会从密钥空间删除。

具体就是Redis每秒10次做的事情:

测试随机的20个keys进行相关过期检测。
删除所有已经过期的keys。
如果有多于25%的keys过期,重复步奏1.

为了获得正确的行为而不牺牲一致性,当一个key过期,DEL将会随着AOF文字一起合成到所有附加的slaves。在master实例中,这种方法是集中的,并且不存在一致性错误的机会。

然而,当slaves连接到master时,不会独立过期keys(会等到master执行DEL命令),他们任然会在数据集里面存在,所以当slave当选为master时淘汰keys会独立执行,然后成为master。

内存移除控制策略

8个解决方方案

当maxmemory限制达到的时候Redis会使用的行为由 Redis的maxmemory-policy配置指令来进行配置。

在redis.conf中提出了8个解决方法。

volatile-lru ->退出使用近似的LRU,仅使用设置了过期值的键。
allkeys-lru ->使用近似的LRU驱逐任何密钥。
volatile-lfu ->使用近似的LFU逐出,仅使用具有过期集的键。
allkeys-lfu ->使用近似的LFU驱逐任何密钥。
volatile-random ->删除一个具有过期设置的随机键。
allkeys-random ->删除一个随机键,任意键。
volatile-ttl ->删除最近过期时间的密钥(较小的TTL)
noeviction ->不驱逐任何东西,只是在写操作时返回一个错误。

LRU表示最近最少使用

LFU表示使用频率最低

LRU、LFU和volatile-ttl都是使用近似随机算法实现的。

注意:使用上述任何策略,当没有合适的键用于驱逐时,Redis会在写操作时返回一个错误。

一般的经验规则:

使用allkeys-lru策略:当你希望你的请求符合一个幂定律分布,也就是说,你希望部分的子集元素将比其它其它元素被访问的更多。如果你不确定选择什么,这是个很好的选择。.
使用allkeys-random:如果你是循环访问,所有的键被连续的扫描,或者你希望请求分布正常(所有元素被访问的概率都差不多)。
使用volatile-ttl:如果你想要通过创建缓存对象时设置TTL值,来决定哪些对象应该被过期。

allkeys-lru 和 volatile-random策略对于当你想要单一的实例实现缓存及持久化一些键时很有用。不过一般运行两个实例是解决这个问题的更好方法。

为了键设置过期时间也是需要消耗内存的,所以使用allkeys-lru这种策略更加高效。

回收进程如何工作

理解回收进程如何工作是非常重要的:

一个客户端运行了新的命令,添加了新的数据。
Redis检查内存使用情况,如果大于maxmemory的限制, 则根据设定好的策略进行回收。
一个新的命令被执行,等等。
所以我们不断地穿越内存限制的边界,通过不断达到边界然后不断地回收回到边界以下。

近似LRU算法

Redis的LRU算法并非完整的实现。

Redis为什么不使用真实的LRU实现是因为这需要太多的内存。

内存优化

使用32位的redis

使用32位的redis,对于每一个key,将使用更少的内存,因为32位程序,指针占用的字节数更少。但是32的redis整个实例使用的内存将被限制在4G以下。

使用make 32bit命令编译生成32位的redis。RDB和AOF文件是不区分32位和64位的(包括字节顺序),所以你可以使用64位的reidis恢复32位的RDB备份文件,相反亦然。

位级别和字级别的操作

Redis 2.2引入了位级别和字级别的操作: GETRANGE, SETRANGE, GETBIT 和 SETBIT.使用这些命令。

对位操作不熟的话,可以看一下这两篇:

位运算 - 初见

位图 - 海量数据处理

尽可能使用散列表

小散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面。


本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-08-25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 配置redis
  • 最大内存限制
  • 查看redis内存相关信息:INFO memory
  • 内存都去哪儿了?还没好好使用,就爆了
  • 内存回收策略
    • 过期键值
      • Redis如何淘汰过期的keys
  • 内存移除控制策略
    • 8个解决方方案
      • 回收进程如何工作
        • 近似LRU算法
        • 内存优化
          • 使用32位的redis
            • 位级别和字级别的操作
              • 尽可能使用散列表
              相关产品与服务
              云数据库 Redis
              腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档