目录
一、介绍
Redis列表是简单的字符串列表,按照插入顺序排序,列表值可以重复。可以添加一个元素到列表的头部(左边)或者尾部(右边)。它的底层实际是双向链表,对两端的操作性能很高,通过索引下标操作中间的节点性能会较差。总结其特征与Java中的LinkedList类似:
- 有序
- 元素可以重复
- 插入和删除快
- 查询速度一般
1.1. List底层数据结构
List底层数据结构历经了三次更新迭代,分别为:
1. Redis 3.2 版本之前:采用ZipList(压缩列表)和LinkedList(双向链表)
Redis3.2 以前主要以 ZipList 进行存储,在不满足 ZipList 的存储要求后转换为 LinkedList 列表存储。当列表对象同时满足以下两个条件时,列表对象使用 ZipList 进行存储,否则用 LinkedList 存储:
列表对象保存的所有字符串元素的长度小于 64 字节;
列表对象保存的元素数量小于 512 个
压缩列表的不足:插入元素过多或字符串太大时,需要调用 Realloc 扩展内存。
双向链表的不足:使用附加指针 Prev 和 Next,比较浪费空间,加重内存的碎片化。
Redis3.2 版本开始,List 类型数据使用的底层数据结构是QucikList(快速链表),快速列表是以压缩列表为节点的双向链表,将双向链表按段切分,每一段使用压缩列表进行内存的连续存储,多个压缩列表通过 prev 和 next 指针组成的双向链。
zlbytes | 占用 4 个字节,记录了整个 ziplist 占用的总字节数 |
zltail | 占用 4 个字节,指向最后一个 entry 偏移量,用于快速定位最后一个 entry |
zllen | 占用 2 字节,记录 entry 总数 |
entry | 元素列表,redis中存储的都是(key,value)格式,每个(key,value)都称为一个entry。 |
zlend | ziplist 结束标志,占用 1 字节,值等于 255 |
快速链表作为 ZipList 和 LinkedList 的混合体,它将 LinkedList 按段切分,每一段使用 ZipList 来紧凑存储,多个 ZipList 之间使用双向指针串接起来,这样性能就的得到了更大的提升。
head | 表的头部节点 |
tail | 表的尾部节点 |
count | 表中所有节点中元素总数 |
len | 表中节点的个数 |
fill | ziplist 节点的最大大小 值默认 8KB 超出大小后会新建一个 ziplist,对应 list-max-ziplist-size 参数,占 16bit。 |
compress | 节点压缩深度,表示节点是否使用 LZF 算法压缩,对应 list-compress-depth 参数,占16bit |
二、常用命令
更详细的Redis命令操作指南,请查看Redis官网,有关命令的入口地址如下:
最好的学习方式就是阅读官方文档及源代码
2.1. lpush/rpush
lpush/rpush <key><value1><value2><value3>...从左边/右边插入一个或多个值
2.2. lpop/rpop
lpop/rpop <key><count> 从左边/右边取出一个或多个值,值在键在,值取光键就无了
2.3. rpoplpush
rpoplpush <key1><key2>从<key1>列表的右边取出一个值插到<key2>列表右边
2.4. lrange
lrange <key><start><stop> 按照索引下标获得元素(从左到右),0 -1表示获取所有
2.5. lindex
lindex <key><index>按照索引下标获得元素(从左到右)
2.6. llen
llen <key>获得列表长度
2.7. linsert
linsert <key> before <value><newvalue>在<value>的前面插入<newvalue>
linsert <key> after <value><newvalue>在<value>的后面插入<newvalue>
2.8. lrem
lrem <key><n><value>从<key>的左边删除n个value(从左到右)
2.9. lset
lset <key><inde><value>将列表key下标为index的值替换成value
2.10. BLPOP和BRPOP
与LPOP和RPOP类似,只不过在没有元素时等待指定时间,而不是直接返回nil
三、应用场景
3.1. 常用分布式数据结构
Stack(栈) = LPUSH + LPOP
Queue(队列) = LPUSH + RPOP
Blocking MQ(阻塞队列 )= LPUSH + BRPOP
3.2. 微博和微信公众号消息流
小明在微博关注了胡歌、毛不易等明星
1. 胡歌发微博,消息ID为10018
LPUSH msg:{小明ID} 10018
2. 毛不易发微博,消息ID为10086
LPUSH msg:{小明ID} 10086
3. 小明查看最新消息
LRANGE msg{小明ID} 0 4
注:该场景应用主要适合于粉丝量不大(一万左右或以内)的大V,超大粉丝量的大V每发布一条消息就给每个粉丝LPUSH几百万几千万的消息,Redis服务器是扛不住的。