注.这是在学完课程之后写的文章,并没有经过实战的检验,希望大家不要不信也不要全信,尽信书不如无书。
redis版本说明:redis3.x
1.底层设计
图 1-1
redis给使用者提供了5种数据类型,其实在底层实现时只使用了一个结构体来实现,如图 1-1所示 .可以看出reids里面有不超过16种的类型和不超过16种的编码类型,一种类型有多种编码方式。refcount一看就知道是引用计数,表名这个结构的数据可以共享. void *ptr表示可以存任意类型的数据,lru这个属性说明redis中使用到了最近最少访问算法来实现key淘汰.
图 1-2
从图 1-2可以看出字符串类型在一般情况下使用RAW编码方式,少量数据时使用EMBSTR编码方式,特殊情况下使用INT编码方式。
图 1-3
图 1-3展示了RAW编码时的字符串结构示例,sds是redis中存字符串的一个结构,其中Free表示还剩余的长度,Len表示已使用的长度,如果长度不够的话,就会去申请更大的长度来存储数据,也说明对于字符串来说有一个预分配内存的机制。buf就是存储的字符串本身,由于有了Len这个属性,就不用使用\0来表示字符串的结束。
图 1-4
在String类型的数据存储长度少于39的时候,内部存储如图 1-4所示,redis将图 1-3中的redisObject和sds放到了一个redisObject中来了,这时redis内部使用jemalloc来分配内存,jemalloc安照2,4,8,16,32,64个模式来分配字节数,上述结构如果刚好Len的长度为39,就刚好使用了64个字节的内存。
图 1-5
当String类型存的数据是一个正整数的时候,reidsObject使用INT编码,而且当正整数的范围在0-10000之间且lru无效时,redis会共享这0-10000个数字,也就是说0-10000在内存中只使用了一份内存,无论我们有多少个1000存在redis中,redis只使用了存一份1000的内存,我们可以利用redis的这个特性来优化我们使用redis的程序,从而让redis占用更少的内存。
图 1-6
图 1-6总结了String编码方式
图 1-7
图 1-8
在数据量小的情况下,redis会对数据做压缩,节省了内存开销,但是在数据量大的时候如果继续使用压缩结构的话会导致性能问题。redis中提供了如图 1-7的配置项,来定义什么是数据量小。其中hash结构会在key-value对小于512个且每个key-value对中的value长度小于64的时候会使用压缩列表。
图 1-9
如果我们redis内存不够用,我们可以充分利用压缩列表的特性来对我们的key-value进行拆分,使其更节约内存。