目录
一、数据类型及使用场景
redis是kv存储系统,key为字符串类型,值为redis对象。
由5种常用数据类型:String,List,Hash,Set,ZSet。
1、String
底层编码格式:
- int:当保存数据时整形(64位long)时,如果是浮点数类型,redis是现将浮点数转为字符串然后再保存;
- 简单动态字符串。
底层没有直接使用C字符串,而是使用简单动态字符串实现。区别:(1)是二进制安全的,不会遇到'\0'而终止,可以存储图像和序列化对象;(2)结构中有表示长度的字段,获取字符串长度时间复杂度时O(1);(3)空间不足时会自动扩容,大小小于1M时每次扩容一倍空间,大小大于等于1M时,每次扩容1M。惰性空间释放,数据修改导致长度变短时不会立即释放多余空间,而是把多余空间大小记录到free字段中,下次不够时优先使用多余空间,再进行扩容,减少了内存分配开销。
2、List
数据量小时使用ziplist存储,节省内存;当ziplist节点数超过512个,或者单个节点大小超过64字节,就会使用QuikList存储。
(1)ziplist
ziplist是把节点存放在一块连续内存里,节点内存储上一节点大小和当前节点的大小。不采用双向链表形式是因为(1)链表的前驱和后继指针都占用额外的内存空间,在数据量少的情况下实际数据所占大小还不如指针浪费的多(2)每个链表节点单独分配内存,内存不连续续会产生内存碎片(3)根据局部性原理,连续内存也能更好的命中CPU Cache。
操作时间复杂度:
- 头尾压入/弹出操作,查询头尾元素时间复杂度都是O(1);
- 对于中间元素查找复杂度是O(N),当新增/修改某个元素时内存空间要重新分配,可能会触发连锁更新。
- 每种redis数据结构都有单独的字段保存该数据长度,因此获取长度是O(1).
ziplist连锁更新:
每个节点都包含一个字段prevlen表示上一节点的所占大小,该字段是变长编码的。当长度小于254时使用1字节存储prevlen,当大于