redis优化编码之字符串

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: Redis数据结构之字符串

redis 优化编码之字符串

 字符串优化

字符串对象是redis内部最常用的数据类型。

  • 所有的键是字符串对象
  • 值对象除了整数之外都是使用字符串存储
lpush cache:type "redis" "tair" "memcache" "leveldb"

创建如上一个链表 需要创建一个链表对象和四个字符串对象。至少需要五个字符串对象。

字符串结构

redis为采用原生C语言类型的字符串结构,拥有自己的字符串结构 ----内部简单动态字符串(simple dynamic string , SDS)
image

graph LR
    subgraph SDS字符串结构体
        c[char buf ] -->cexp[字节数组]
     end
   subgraph SDS字符串结构体
        b[int free ] --> bexp[未用字节长度]
    end
   subgraph SDS字符串结构体
        a[int len ] --> aexp[已用字节长度] 
    end
    style aexp fill:#f9f,stroke:#333,stroke-width:2px
    style bexp fill:#f9f,stroke:#333,stroke-width:2px
    style cexp fill:#f9f,stroke:#333,stroke-width:2px

特点如下:

  • [ ] O(1) 时间复杂度获取:字符串长度、已用长度、未用长度
  • [ ] 内部实现空间预分配机制 降低再分配
  • [ ] 惰性删除机制,字符串缩减后的空间不释放,作为预分配空间保留

预分配机制

字符串存在预分配机制,需要注意预分配带来的内存浪费。

阶段一

image

graph LR
    subgraph SDS字符串结构体
        c[char buf ] 
     end
   subgraph SDS字符串结构体
        b[free = 0 ] 
    end
   subgraph SDS字符串结构体
        a[len = 60 ] 
    end
      c  -->cexp[used+free+\O=61字节]

    style cexp fill:#f9f,stroke:#333,stroke-width:2px

    这里忽略int类型和free字段消耗的8字节

阶段二

image

graph LR

    subgraph SDS字符串结构体
        c[char buf ] 
     end
   subgraph SDS字符串结构体
        b[free = 120 ] 
    end
   subgraph SDS字符串结构体
        a[len = 120 ] 
    end
      c  -->cexp[used+free+\O=241字节]

    style cexp fill:#f9f,stroke:#333,stroke-width:2px

追加操作后字符串对象预分配一倍容量作为预留空间-大量追加操作内存重分配造成内存碎片

阶段三

image

graph LR

    subgraph SDS字符串结构体
        c[char buf ] 
     end
   subgraph SDS字符串结构体
        b[free = 0 ] 
    end
   subgraph SDS字符串结构体
        a[len = 120 ] 
    end
      c  -->cexp[used+free+\O=121字节]

    style cexp fill:#f9f,stroke:#333,stroke-width:2px

降低一倍的空间同时碎片率也降低了

测试用例环境:

  • redis 3.2.8
  • mem_allocator libc
  • maxmemory 5G
  • model standalone

数据量阶段操作说明命令内存内存碎片率
200W阶段1新插入200W数据set367.33M1.79
阶段2在阶段1的基础上追加1倍数据append760.21M1.62
阶段3重新插入200W数据 value是之前的1倍set500.84M1.72


数据量阶段操作说明命令内存内存碎片率
400W阶段1新插入400W数据set690.91M1.8
阶段2在阶段1的基础上追加1倍数据append1.45G1.63
阶段3重新插入400W数据 value是之前的1倍set961.76M2.48

数据量阶段操作说明命令内存内存碎片率
600W阶段1新插入600W数据set1.00G1.8
阶段2在阶段1的基础上追加1倍数据append2.16G1.63
阶段3重新插入600W数据 value是之前的1倍set1.40G2.48

数据量阶段操作说明命令内存内存碎片率
800W阶段1新插入800W数据set1.3G1.31
阶段2在阶段1的基础上追加1倍数据append2.85G1.65
阶段3重新插入800W数据 value是之前的1倍set1.831.19

数据量阶段操作说明命令内存内存碎片率
1000W阶段1新插入1000W数据set1.66G1.8
阶段2在阶段1的基础上追加1倍数据append3.60G1.63
阶段3重新插入1000W数据 value是之前的1倍set2.84G1.46

上述进行了200W、400W、600W、800W、1000W 数据量的 测试,内存以及内存碎片率

  • 同样的数据追加后内存的消耗非常严重。

  • 字符串预分配的方式 是为防止修改数据操作不断重分配内存和字节数据

  • 造成内存浪费,并不是每次都是翻倍

    • 第一次创建len 等于数据实际大小 free等于0, 不做预分配
    • 修改后 free空间不足,且数据小于1M,则分配1倍(len=60bytes,free=0,再追加60bytes 预分配120bytes 。总空间就是60+60+120+ 1 bytes)
    • 修改后free空间不足,且数据大约1M 则每次预分配1M (len=30MB ,free=0,追加100bytes 预分配1MB 总空间 30MB+100bytes+1MB + 1bytes)

总结

  • 尽量减少字符串频繁修改操作 如append,setrange

  • 改为直接使用set修改字符串

  • 降低预分配带来的内存浪费和碎片
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
17天前
|
XML JSON NoSQL
Redis的常用数据结构之字符串类型
Redis的常用数据结构之字符串类型
19 0
|
24天前
|
存储 消息中间件 NoSQL
Redis数据类型详解:选择合适的数据结构优化你的应用
Redis数据类型详解:选择合适的数据结构优化你的应用
|
1月前
|
NoSQL 安全 Linux
Redis 字符串:SDS
Redis 字符串:SDS
38 0
|
2天前
|
存储 NoSQL 安全
Redis入门到通关之数据结构解析-动态字符串SDS
Redis入门到通关之数据结构解析-动态字符串SDS
|
24天前
|
存储 消息中间件 缓存
Redis 字符串:用一串数据解决多种问题
Redis 字符串:用一串数据解决多种问题
|
1月前
|
存储 缓存 NoSQL
探索Redis的多样应用场景:加速和优化现代应用
探索Redis的多样应用场景:加速和优化现代应用
34 2
|
1月前
|
NoSQL 算法 数据管理
【Redis】Redis配置参数详解:优化过期删除机制
【Redis】Redis配置参数详解:优化过期删除机制
80 0
|
2月前
|
存储 监控 NoSQL
Redis 大键问题解析:如何管理和优化巨型数据【redis拓展】
Redis 大键问题解析:如何管理和优化巨型数据【redis拓展】
74 0
|
3月前
|
存储 缓存 监控
Redis 7.0性能大揭秘:如何优化缓存命中率?
Redis 7.0,这货不仅仅是一个简单的缓存工具,它更是一款高性能的数据结构服务器。现在,大家都知道缓存命中率对性能影响特别大,但怎么优化它呢?
|
3月前
|
监控 NoSQL 安全
Redis进阶-JedisPool参数优化 & 如何合理估算核心参数 & redis连接池预热
Redis进阶-JedisPool参数优化 & 如何合理估算核心参数 & redis连接池预热
93 0

相关产品

  • 云数据库 Redis 版