Redis开发与运维读书笔记之五——列表

作者: tcxurun 分类: 学习笔记 发布时间: 2020-03-24 20:13 ė 6 没有评论

列表List

 

List类型用来存储多个有序的字符串,列表中每个字符串成为元素(element);

一个List最多可以存储2^32-1个元素;

可以对List两端插入(push)或弹出(pop);

List可以充当栈和队列的角色

List的特点:

  • List中的Element是有序的,可以通过索引下标获取某个Element或某个范围内的Element List
  • List中的Element是可以重复的

 

 

常用命令

添加

从右边插入元素:rpush key value [value …]

从左边插入元素:lpush key value [value …]

向某个元素前或后插入元素:linsert key before|after pivot value (pivot为指定的某个元素 )

从左到右列出列表的所有元素:lrange listkey 0 -l

 

查找

获取指定范围的元素列表:lrange key start end,索引下标从左到右为从0到N-1,从右到左是-1到-N,end包含了自身

获取列表指定索引下标的元素: lindex key index

获取列表长度:llen key

 

删除

从列表左侧弹出元素:lpop key

从列表右侧弹出元素:rpop key

删除指定元素:lrem key count value,从列表中找到值为value的元素删除,根据count不同分为三种情况:

count>0:从左到右,删除最多count个元素

count<0:从右到左,删除最多count绝对值个元素

count=0:删除所有

 

修改

修改指定索引下标的元素:lset key index newValue

 

阻塞

blpop key [key …] timeout

brpop key [key …] timeout

blpop和brpop是lpop和rpop的阻塞版本,除了弹出方向不同,使用方法基本相同。

timeout的单位是秒

  • 列表为空:timeout=0,客户端会一直阻塞;timeout=3,会等待3秒返回
  • 列表不为空,timeout=0,客户端立即返回

 

使用brpop时需要注意两点:

  • 如果是多个键,brpop会从左到右遍历所有键,一旦有一个键能弹出元素,客户端立即返回
  • 如果多个客户端对同一个键执行brpop,最先执行brpop命令的客户端可以获取到弹出的值

 

 

列表类型的命令及对应的时间复杂度

 

命令

 时间复杂度

rpush key value [value …]

O(k)k是元素个数

lpush key value [value….]

O(k)k是元素个数

linsert ket before|after pivot value

O(n)npivot距离列表头或尾的距离

lrange key start end

O(s+n),sstart偏移量,nstartend的范围

lindex key index

O(n)n是索引的偏移量

llen key

O(1)

lpop key

O(1)

rpop key

O(1)

lrem key count value

O(n)n是列表长度

ltrim key start end

O(n)n是要裁剪的元素总数

lset key index newvalue

O(n)n是索引的偏移量

blpop key [key …] timeout

O(1)

brpop key [key…] timeout

O(1)

 

内部编码

  • ziplist:压缩列表,当列表的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的值都小于list-max-ziplist-value配置(默认64个字节),Redis会选用ziplist作为列表的内部实现来减少内存的使用
  • linkedlist:链表,当列表类型无法满足ziplist的条件,Redis会选用linkedlist作为List的内部实现
  • quicklist:Redis3.2提供,是一个以ziplist为节点的linkedlist,结合了两者的优势

 

使用场景:

  • 消息队列:lpush+brpop组合可以实现阻塞队列,生产者客户端使用lrpush从列表左侧插入元素,多个消费者客户端使用brpop命令阻塞式“抢”列表右侧的元素,多个客户端保证了消费的负载均衡和高可用
  • 文章列表:每个用户都有属于自己的文章列表,需要分页展示文章列表,可以使用List,因为List不但是有序的,还支持按照索引范围获取元素。

(1)、 每篇文章使用Hash结果存储

(2)、向用户文章列表添加文章使用lpush

(3)、分页获取用户文章列表使用lrange

 

注意:如果每次分页获取文章个数较多,使用hgetall效率较低,可以考虑使用pipeline批量获取,或者将文章数据序列化成字符串,使用mget批量获取。

lrange在列表两端性能较好,中间性能较差,可以将列表做二级拆分,或者使用Redis3.2的quicklist内部编码实现,效率较高。

 

场景选择时可以参考一下口诀

lpush + lpop = Stack(栈)

lpush + rpop = Queue(队列)

lpush + ltrim = Capped Collection(有限集合)

lpush + brpop = Message Queue(消息队列)

本文出自天一直很蓝,转载时请注明出处及相应链接。

本文永久链接: http://www.tcxurun.cn/archives/556

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Ɣ回顶部