redis优化编码之字符串

本文涉及的产品
PolarClaw,2核4GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
云数据库 PolarDB MySQL 版,列存表分析加速 4核8GB
简介: 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修改字符串

  • 降低预分配带来的内存浪费和碎片
目录
相关文章
|
7月前
|
缓存 运维 监控
Redis 7.0 高性能缓存架构设计与优化
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Redis 7.0高性能缓存架构,探索函数化编程、多层缓存、集群优化与分片消息系统,用代码在二进制星河中谱写极客诗篇。
1310 3
|
12月前
|
消息中间件 缓存 NoSQL
基于Spring Data Redis与RabbitMQ实现字符串缓存和计数功能(数据同步)
总的来说,借助Spring Data Redis和RabbitMQ,我们可以轻松实现字符串缓存和计数的功能。而关键的部分不过是一些"厨房的套路",一旦你掌握了这些套路,那么你就像厨师一样可以准备出一道道饕餮美食了。通过这种方式促进数据处理效率无疑将大大提高我们的生产力。
359 32
|
11月前
|
缓存 NoSQL 算法
高并发秒杀系统实战(Redis+Lua分布式锁防超卖与库存扣减优化)
秒杀系统面临瞬时高并发、资源竞争和数据一致性挑战。传统方案如数据库锁或应用层锁存在性能瓶颈或分布式问题,而基于Redis的分布式锁与Lua脚本原子操作成为高效解决方案。通过Redis的`SETNX`实现分布式锁,结合Lua脚本完成库存扣减,确保操作原子性并大幅提升性能(QPS从120提升至8,200)。此外,分段库存策略、多级限流及服务降级机制进一步优化系统稳定性。最佳实践包括分层防控、黄金扣减法则与容灾设计,强调根据业务特性灵活组合技术手段以应对高并发场景。
3056 7
|
缓存 NoSQL Redis
Redis如何优化频繁命令往返造成的性能瓶颈?
频繁的命令往返是Redis性能优化中需要重点关注的问题。通过使用Pipeline、Lua脚本、事务、合并命令、连接池以及合理设置网络超时,可以有效减少网络往返次数,优化Redis的性能。这些优化措施不仅提升了Redis的处理能力,还能确保系统在高并发情况下的稳定性和可靠性。
342 14
|
存储 监控 NoSQL
NoSQL与Redis配置与优化
通过合理配置和优化Redis,可以显著提高其性能和可靠性。选择合适的数据结构、优化内存使用、合理设置持久化策略、使用Pipeline批量执行命令、以及采用分布式集群方案,都是提升Redis性能的重要手段。同时,定期监控和维护Redis实例,及时调整配置,能够确保系统的稳定运行。希望本文对您在Redis的配置与优化方面有所帮助。
250 23
|
缓存 NoSQL JavaScript
Vue.js应用结合Redis数据库:实践与优化
将Vue.js应用与Redis结合,可以实现高效的数据管理和快速响应的用户体验。通过合理的实践步骤和优化策略,可以充分发挥两者的优势,提高应用的性能和可靠性。希望本文能为您在实际开发中提供有价值的参考。
441 11
|
存储 监控 NoSQL
NoSQL与Redis配置与优化
通过合理配置和优化Redis,可以显著提高其性能和可靠性。选择合适的数据结构、优化内存使用、合理设置持久化策略、使用Pipeline批量执行命令、以及采用分布式集群方案,都是提升Redis性能的重要手段。
280 7
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:百万级数据统计优化实践
【10月更文挑战第21天】 在处理大规模数据集时,传统的单体数据库解决方案往往力不从心。MySQL和Redis的组合提供了一种高效的解决方案,通过将数据库操作与高速缓存相结合,可以显著提升数据处理的性能。本文将分享一次实际的优化案例,探讨如何利用MySQL和Redis共同实现百万级数据统计的优化。
890 9
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:优化百万数据查询的实战经验
【10月更文挑战第13天】 在处理大规模数据集时,传统的关系型数据库如MySQL可能会遇到性能瓶颈。为了提升数据处理的效率,我们可以结合使用MySQL和Redis,利用两者的优势来优化数据查询。本文将分享一次实战经验,探讨如何通过MySQL与Redis的协同工作来优化百万级数据统计。
772 5

相关产品

  • 云数据库 Tair(兼容 Redis)