一、是二进制安全的,也就是说,你可使用任何形式的二进制序列来做为key,好比一个string,或者一个jpg图片的数据,须要说明的是,空字符串也是一个有效的key。node
二、不建议使用过长的key,影响内存占用及数据查性能,对于过长的key,能够经过hash(例如SHA1)处理转换。redis
三、建议使用有意义及统一格式的key。json
四、最大容许key大小为512M。缓存
一、做为原子计数器:incr、decr、incrby安全
二、结合append命令,做为基于时间的增量序列。数据结构
三、随机访问及获取值区域,getrange、setrange。app
附:须要注意的是append及range操做容易引发内存浪费和碎片化问题。性能
一、单个hash最多支持232 - 1个键值对。优化
二、关于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 对象内部存储形态。
一、type:数据类型、例如sting、hash、list、set、zset等,值类型查看命令【type】。
二、encoding:值存储内部实现的数据结构,具体能够参考第七部分。
三、lru:最后一次被访问时间,辅助回收,能够经过 object idletime {key} 在不更新lru属性状况下查看key的空闲时间。
四、refcount:当前对象被引用次数,辅助回收,能够经过 object refcount {key} 查看引用数,当对象为整数且值在范围在[0-9999]时,redis能够经过共享对象的方式来节省内存。
目前共享对象池只对整数设置了0~9999个共享对象,一方面整数对象池复用率最大,同时等值判断上时间复杂度为O(1)。
五、*ptr:数据存储或指向,数据自己或者指向数据的指针,redis3.0以后,长度在39之内的字符串数据,内部编码为embstr,内存建立时,字符串和redisObject一块儿分配,减小一次内存分配。
simple dynamic string:redis内部自定义简单动态字符串结构。
一、字符串属性的O(1)时间复杂度获取。
二、空间与分配、减小内存再分配。
三、惰性删除机制,字符串缩减后空间不释放,做为预分配空间保留。
6、关于对象属性存储:json or hash
对象属性存储能够经过总体json存储或者hash kv存储。具体应用选择,能够结合总体对象大小及属性操做需求来决定。
对于频繁总体操做,且对象数据量较小的通常采用json字符串类型存储。
对于多对象属性层级操做情景,可能hash会比较合适。
如上图,同一种数据类型,能够有多种不一样内部编码存储形式。具体redis采用那种编码形式与实际应用的数据值类型相关,如上述第三部分论述hash类型的编码转换。
数据的编码类型在数据写入的时候肯定,不可变换,且只能向大内存编码行使转换。
以下,从新设置 testuser desc值,testuser对象的编码形式保持不变:
编码转换时机:
经过第七节,咱们能够看到hash、list、zset底层都有应用这种存储结构。
基本特色:
一、连续性内存存储。
二、能够模拟双向链表,O(1)时间复杂度内出入队操做。
三、读写性能跟数据的元素个数及值长度相关,适合存储小对象和长度有限的数据。
四、数据增删涉及复杂的内存操做。
ziplist基本结构:
一、zlbytes:int32类型、4字节,ziplist总体字节长度。
二、zltail:int32类型、4字节,记录距离尾节点偏移量,用于尾节点弹出。
三、zllen:int16类型,2字节,ziplist节点数量。
四、entry:数据节点,长度不定。
entry 即链表node,内部结构包含:
prev_entry_bytes_length:前一个节点所占用的空间,用户快速定位。
encoding:当前数据节点编码类型及长度,前两位标识编码类型,其他标识数据长度。
contents:节点数据值。
五、zlend:1字节,记录列表结尾。
redis内存消耗包括自身内存,键值对象占用、缓冲区内存占用及内存碎片占用。
一、缓冲区内存:包括客户端缓存、复制及压缓冲区及AOF缓冲区。
二、内存碎片:固定范围内存块儿分配。
redis默认使用jemalloc内存分配器,其它包括glibc、tcmalloc。
内存分配器会首先将可管理的内存分配为规定不一样大小的内存块以备不一样的数据存储需求,可是,咱们知道实际应用中须要存储的数据大小不一,规范不一,内存分配器只能选择最接近数据需求大小的内存块儿进行分配,这样就伴随着“占不满”空间的碎片浪费。
jemalloc针对内存碎片有相应的优化策略,正常碎片率为mem_fragmentation_ratio在1.03左右。
第二部分咱们说过,对string值得频繁append及range操做会会致使内存碎片问题,另外,第七部分,SDS惰性内存回收也会致使内存碎片,同时过时键内存回收也伴随着所释放空间的没法充分利用,致使内存碎片率上升的问题。
碎片处理:
应用层面:尽可能避免差别化的键值使用,作好数据对齐。
redis服务层面:能够经过重启服务,进行碎片整理。
三、maxmemory及maxmemory-policy控制redis最大可用内存及内存回收。须要注意的是内存回收执行影响redis的性能,避免频繁的内存回收开销。