[转帖]关于redis,你需要了解的几点!

关于,redis,需要,了解,几点 · 浏览次数 : 0

小编点评

**Redis 数据类型** * **String 类型**:作为原子计数器,可用于incr、decr、incrby2 等操作。 * **hash 类型**:用于存储键值对,支持设置最大条目数、元素大小等配置。 * **ziplist 或 hashtable1 类型**:用于存储多个元素的连续存储,可提高内存效率。 **Redis 存储** * **类型**:数据类型,包含数据类型、值类型等信息。 * **encoding**:数据值存储的内部实现,可参考 `object idletime` 属性。 * **lru**:最后一次被访问时间,辅助回收。 * **refcount**:当前对象被引用次数,辅助回收。 **对象属性存储** * **json 或 hash 对象属性存储**:通过整体json存储或hash kv存储数据。 **数据编码** * 不同数据类型可以采用不同的编码,以节省内存。 **内存碎片处理** * 避免差异化的键值使用,做好数据对齐。 * 通过重启服务、使用 `maxmemory` 和 `maxmemory-policy` 设置最大可用内存及内存回收策略。 **其他** * ziplist 存储结构可模拟双向链表,支持 O(1) 的读写性能。 * 针对内存碎片,可以使用 `zlend` 属性记录列表结尾,并提供相应的优化策略。

正文

 

 

一、关于 redis key:

1、是二进制安全的,也就是说,你可以使用任何形式的二进制序列来作为key,比如一个string,或者一个jpg图片的数据,需要说明的是,空字符串也是一个有效的key。

2、不建议使用过长的key,影响内存占用及数据查性能,对于过长的key,可以通过hash(例如SHA1)处理转换。

3、建议使用有意义及统一格式的key。

4、最大允许key大小为512M。

二、String 类型应用:

1、作为原子计数器:incr、decr、incrby

2、结合append命令,作为基于时间的增量序列。

3、随机访问及获取值区域,getrange、setrange。

附:需要注意的是append及range操作容易引起内存浪费和碎片化问题。

三、hash 类型:ziplist or hashtable

1、单个hash最多支持232 - 1个键值对。

2、关于hash类型的内部编码:ziplist(压缩列表) & hashtable(哈希表)

配置:hash-max-ziplist-entries(hash类型最大kv数据,默认512)、hash-max-ziplist-value(单个v值最大值, 默认64)

redis 采用何种结构取决于hash中元素数及元素值得大小,当同时满足小于配置时,redis使用ziplist编码存储,否则会转化为hashtable。

ziplist编码使用更加紧凑的结构实现多个元素的连续存储,因此占用的内存更小。

当数据类型无法满足配置条件,此时使用ziplist编码存储读写效率会下降,所以转换使用hashtable编码存储(O(1)时间复杂度)。

示例:添加 testuser hash类型key,先后设置元素name、desc不同长度元素值,分别查看内部编码类型

四、关于redis存储:redisObject

redis 对象内部存储形态。

1、type:数据类型、例如sting、hash、list、set、zset等,值类型查看命令【type】。

2、encoding:值存储内部实现的数据结构,具体可以参考第七部分。

3、lru:最后一次被访问时间,辅助回收,可以通过 object idletime {key} 在不更新lru属性情况下查看key的空闲时间。

4、refcount:当前对象被引用次数,辅助回收,可以通过 object refcount {key} 查看引用数,当对象为整数且值在范围在[0-9999]时,redis可以通过共享对象的方式来节省内存。

目前共享对象池只对整数设置了0~9999个共享对象,一方面整数对象池复用率最大,同时等值判断上时间复杂度为O(1)。

5、*ptr:数据存储或指向,数据本身或者指向数据的指针,redis3.0之后,长度在39以内的字符串数据,内部编码为embstr,内存创建时,字符串和redisObject一起分配,减少一次内存分配。

五、关于SDS

simple dynamic string:redis内部自定义简单动态字符串结构。

1、字符串属性的O(1)时间复杂度获取。

2、空间预分配、减少内存再分配。

3、惰性删除机制,字符串缩减后空间不释放,作为预分配空间保留。

六、关于对象属性存储:json or hash

对象属性存储可以通过整体json存储或者hash kv存储。具体应用选择,可以结合整体对象大小及属性操作需求来决定。

对于频繁整体操作,且对象数据量较小的一般采用json字符串类型存储。

对于多对象属性层级操作情景,可能hash会比较合适。

七、关于存储编码

如上图,同一种数据类型,可以有多种不同内部编码存储形式。具体redis采用那种编码形式与实际应用的数据值类型相关,如上述第三部分论述hash类型的编码转换。

数据的编码类型在数据写入的时候确定,不可变换,且只能向大内存编码行使转换。

如下,重新设置 testuser desc值,testuser对象的编码形式保持不变:

编码转换时机:

 

 八、关于ziplist

通过第七节,我们可以看到hash、list、zset底层都有应用这种存储结构。

基本特点:

1、连续性内存存储。

2、可以模拟双向链表,O(1)时间复杂度内出入队操作。

3、读写性能跟数据的元素个数及值长度相关,适合存储小对象和长度有限的数据。

4、数据增删涉及复杂的内存操作。

ziplist基本结构:

1、zlbytes:int32类型、4字节,ziplist整体字节长度。

2、zltail:int32类型、4字节,记录距离尾节点偏移量,用于尾节点弹出。

3、zllen:int16类型,2字节,ziplist节点数量。

4、entry:数据节点,长度不定。

entry 即链表node,内部结构包含:

prev_entry_bytes_length:前一个节点所占用的空间,用户快速定位。

encoding:当前数据节点编码类型及长度,前两位标识编码类型,其余标识数据长度。

contents:节点数据值。

5、zlend:1字节,记录列表结尾。

九、关于redis内存消耗

redis内存消耗包括自身内存,键值对象占用、缓冲区内存占用及内存碎片占用。

1、缓冲区内存

包括客户端缓存、复制积压缓冲区及AOF缓冲区。

2、内存碎片

固定范围内存块儿分配。

redis默认使用jemalloc内存分配器,其它包括glibc、tcmalloc。

内存分配器会首先将可管理的内存分配为规定不同大小的内存块以备不同的数据存储需求,但是,我们知道实际应用中需要存储的数据大小不一,规范不一,内存分配器只能选择最接近数据需求大小的内存块儿进行分配,这样就伴随着“占不满”空间的碎片浪费。

jemalloc针对内存碎片有相应的优化策略,正常碎片率为mem_fragmentation_ratio在1.03左右。

第二部分我们说过,对string值得频繁append及range操作会会导致内存碎片问题,另外,第七部分,SDS惰性内存回收也会导致内存碎片,同时过期键内存回收也伴随着所释放空间的无法充分利用,导致内存碎片率上升的问题。

碎片处理:

应用层面:尽量避免差异化的键值使用,做好数据对齐。

redis服务层面:可以通过重启服务,进行碎片整理。

3、maxmemory 及 maxmemory-policy

redis 基于以上配置控制 redis 最大可用内存及内存回收。

需要注意的是内存回收执行影响redis的性能,避免频繁的内存回收开销。

 

作者:WindWant

与[转帖]关于redis,你需要了解的几点!相似的内容:

[转帖]关于redis,你需要了解的几点!

github:https://github.com/windwant 博客园 首页 新随笔 联系 订阅 管理 随笔 - 227 文章 - 4 评论 - 36 阅读 - 73万 一、关于 redis key: 1、是二进制安全的,也就是说,你可以使用任何形式的二进制序列来作为key,比如一个strin

[转帖]Redis的高并发及高可用,到底该如何保证?

https://zhuanlan.zhihu.com/p/404481762 一、redis如何通过读写分享来承载读请求QPS超过10万+ 1、redis高并发跟整个系统的高并发之间的关系 redis,你要搞高并发的话,不可避免,要把底层的缓存搞得很好 mysql,高并发,做到了,那么也是通过一系列

[转帖]7600字带你学会 Redis 性能优化点, 建议收藏!

https://www.cnblogs.com/shoshana-kong/p/14040195.html 在一些网络服务的系统中,Redis 的性能,可能是比 MySQL 等硬盘数据库的性能更重要的课题。比如微博,把热点微博[1],最新的用户关系,都存储在 Redis 中,大量的查询击中 Redi

[转帖]高性能IO模型:为什么单线程Redis能那么快?

https://zhuanlan.zhihu.com/p/596170085 你好,我是蒋德钧。 今天,我们来探讨一个很多人都很关心的问题:“为什么单线程的Redis能那么快?” 首先,我要和你厘清一个事实,我们通常说,Redis是单线程,主要是指Redis的网络IO和键值对读写是由一个线程来完成的

[转帖]Redis核心技术与实战

https://www.cnblogs.com/strick/p/14851429.html 最近在读一篇关于Redis的专栏,叫做《Redis核心技术与实战》,作者在Redis方面研究颇深,读后非常受益,特在此做记录。 一、Redis基础 1)知识图和问题画像图 Redis知识全景图都包括“两大维

[转帖]Redis Info 命令

https://www.runoob.com/redis/server-info.html Redis Info 命令以一种易于理解和阅读的格式,返回关于 Redis 服务器的各种信息和统计数值。 通过给定可选的参数 section ,可以让命令只返回某一部分的信息: server : 一般 Red

[转帖]Redis 6.0 redis-cluster-proxy 说明

https://www.cnblogs.com/zhoujinyi/p/13267222.html Redis3.0版本之后开始支持了Redis Cluster,Redis也开始有了分布式缓存的概念。关于Redis Cluster的相关说明,可以看之前的几篇文章:Redis Cluster 原理相关

[转帖]删除数据后的Redis内存占用率为什么还是很高?

https://zhuanlan.zhihu.com/p/490569316 有时候Redis明明做了数据删除,数据量已经不大了,但是使用top命令的时候,还会发现Redis占用了很多内存? PS:关于 Redis的高并发及高可用,到底该如何保证?可以参考下这个帖子:httss://http://z

[转帖]Redis命令DEL与UNLINK的区别,如何正确删除大Key!

https://www.itxm.cn/post/47824.html 背景 在这篇文章中做过使用del命令删除大key的实验,结果是del命令随着key的增大,主线程阻塞的时间就越长。 这与之前看redis5.0.8版本的代码中关于多线程删除操作的感官不符,于是决定先查看redis关于删除操作的代

[转帖]高性能 -Nginx 多进程高并发、低时延、高可靠机制在百万级缓存 (redis、memcache) 代理中间件中的应用

https://xie.infoq.cn/article/2ee961483c66a146709e7e861 关于作者 前滴滴出行技术专家,现任 OPPO 文档数据库 mongodb 负责人,负责 oppo 千万级峰值 TPS/十万亿级数据量文档数据库 mongodb 内核研发及运维工作,一直专注于