List列表
list的特性就像数组或者是顺序表,但是内部编码并不是,内部是一个双端队列。
列表类型是用来存储多个有序字符串,在下图中a,b,c,d,e五个元素从左到右组成了一个有序的列表,列表中的每个字符串都是为元素,一个列表可以存储元素的最大值是2^32-1个。

列表类型特点
列表中的元素是有序的,就可以通过索引下标获取某个元素或者某个范围的元素列表,这里的有序需要注意,有序有不同意思,有序可以是升序和降序,有序可以是指顺序很重要。列表的元素是可以重复的。

List命令
LPUSH命令
将一个或者多个元素从做左边插入到list中。key存在或者value对应的类型不是list,指令就会报错。
127.0.0.1:6379> lpush mylist 1 2 3 4
(integer) 4
127.0.0.1:6379> lpush mylist 5 6 7 8
(integer) 8
127.0.0.1:6379> lpush mylist 9 9
(integer) 10
LPUSHX命令
key存在时,可以将一个或者多个元素左边插入到list中,如果key是不存在,则指令返回0。
127.0.0.1:6379> lpushx key 10 11 12
(integer) 0
127.0.0.1:6379> lpushx mylist 10 11 12
(integer) 16
127.0.0.1:6379> lrange mylist 0 -1
"12"
"11"
"10"
"12"
"11"
"10"
"9"
"9"
"8"
"7"
"6"
"5"
"4"
"3"
"2"
"1"
RPUSH命令
将一个或者多个元素从右变插入到list中,返回的是list长度
127.0.0.1:6379> rpush mylist 0 -1 -2
(integer) 19
127.0.0.1:6379> lrange mylist 0 -1
"12"
"11"
"10"
"12"
"11"
"10"
"9"
"9"
"8"
"7"
"6"
"5"
"4"
"3"
"2"
"1"
"0"
"-1"
"-2"
RPUSHX命令
指令有用的前提是key存在,将一个或者多个元素从右边插入到list中。放回值为list长度
127.0.0.1:6379> rpushx key -3 -4
(integer) 0
127.0.0.1:6379> rpushx mylist -3 -4
(integer) 21
127.0.0.1:6379> lrange mylist 0 -1
"12"
"11"
"10"
"12"
"11"
"10"
"9"
"9"
"8"
"7"
"6"
"5"
"4"
"3"
"2"
"1"
"0"
"-1"
"-2"
"-3"
"-4"
LRANGE命令
获取start-end之间的所有元素,这里是左闭右闭。0到-1就可以获取所有的元素。end超出界限也不会报错,会尽可能提取多的元素,如果小于100的话,那么0到100也是获取全部元素,0到1000也是获取全部元素。
127.0.0.1:6379> lrange mylist 0 9
"9"
"9"
"8"
"7"
"6"
"5"
"4"
"3"
"2"
"1"
127.0.0.1:6379> lrange mylist -1 -2
(empty array)
127.0.0.1:6379> lrange mylist -2 -1
"2"
"1"
127.0.0.1:6379> lrange mylist 0 -1
"9"
"9"
"8"
"7"
"6"
"5"
"4"
"3"
"2"
"1"
LPOP命令
从list左边取出元素,返回值为取出的元素或者nil
127.0.0.1:6379> lrange mylist 0 -1
"12"
"11"
"10"
"12"
"11"
"10"
"9"
"9"
"8"
"7"
"6"
"5"
"4"
"3"
"2"
"1"
"0"
"-1"
"-2"
"-3"
"-4"
127.0.0.1:6379> lpop mylist
"12"
127.0.0.1:6379> lpop mylis
(nil)
RPOP命令
从list右边取出元素,redis 5之后多了一个参数count,这里的count就表示可以选择删除的个数
127.0.0.1:6379> rpop mylist
"-4"
127.0.0.1:6379> rpop mylist
"-3"
127.0.0.1:6379> rpop mylis
(nil)
LINDEX命令
获取从左到右下标为n的元素
127.0.0.1:6379> lrange mylist 0 -1
"11"
"10"
"12"
"11"
"10"
"9"
"9"
"8"
"7"
"6"
"5"
"4"
"3"
"2"
"1"
"0"
"-1"
"-2"
127.0.0.1:6379> lindex mylist 0
"11"
127.0.0.1:6379> lindex mylist 134
(nil)
127.0.0.1:6379> lindex mylist 12
"3"
127.0.0.1:6379> lindex mylis 12
(nil)
LINSERT命令
在指定位置插入元素,可以选择在指定位置的前后插入,这里的element指的是列表中元素的值,也就是先指定list中的一个值,任何选择从这个值的那一边插入。
LINSERT key <BEFORE | AFTER> pivot element
127.0.0.1:6379> lrange mylist 0 -1
"6"
"5"
"4"
"3"
"2"
"1"
127.0.0.1:6379> linsert mylist after 4 100
(integer) 7
127.0.0.1:6379> lrange mylist 0 -1
"6"
"5"
"4"
"100"
"3"
"2"
"1"
127.0.0.1:6379> linsert mylist before 4 200
(integer) 8
127.0.0.1:6379> lrange mylist 0 -1
"6"
"5"
"200"
"4"
"100"
"3"
"2"
"1"
127.0.0.1:6379> linsert mylit before 4 200
(integer) 0
LLEN命令
获取list的长度
LLEN key
LREM命令
移除列表中的元素,返回的是被移除元素个数,count可以为正负0,正数就是从列表头部开始,移除count数量且匹配的元素,负数就是从尾巴往前移除count数量且匹配的元素,0就是移除所有匹配的元素。
127.0.0.1:6379> lpush mylist 1 2 3 4 1 2 3 4
(integer) 8
127.0.0.1:6379> lrange mylist 0 -1
"4"
"3"
"2"
"1"
"4"
"3"
"2"
"1"
127.0.0.1:6379> lrem mylist -1 2
(integer) 1
127.0.0.1:6379> lrange mylist 0 -1
"4"
"3"
"2"
"1"
"4"
"3"
"1"
127.0.0.1:6379> lrem mylist 1 2
(integer) 1
127.0.0.1:6379> lrange mylist 0 -1
"4"
"3"
"1"
"4"
"3"
"1"
127.0.0.1:6379> lrem mylist 0 3
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
"4"
"1"
"4"
"1"
LTRIM命令
修建列表,只保留区间元素。
127.0.0.1:6379> lpush mylist "value1" "value2" "value3" "value4" "value5"
(integer) 5
127.0.0.1:6379> ltrim mylist 1 3
OK
127.0.0.1:6379> lrange mylist 0 -1
"value2"
"value3"
"value4"
LSET命令
设置列表指定索引的值
127.0.0.1:6379> lpush mylist "value1" "value2" "value3"
(integer) 3
127.0.0.1:6379> lset mylist 1 "newValue"
OK
127.0.0.1:6379> lrange mylist 0 -1
"value1"
"newValue"
"value3"
阻塞版本命令
blpop和brpop是lpop和rpop的阻塞版本,功能都一样,但是blpop和brpop在列表没用元素进行移除时会等待,而lpop和rpop则会直接返回结果。

命令合集

内部编码
列表类型的内部编码有两种:
ziplist(压缩列表):当列表的元素个数小于 list-max-ziplist-entries 配置(默认 512 个),同时列表中每个元素的长度都小于 list-max-ziplist-value 配置(默认 64 字节)时,Redis 会选择用 ziplist 来作为列表的内部编码实现来减少内存消耗。(节省空间,元素多,操作效率低)
linkedlist(链表):当列表类型无法满足 ziplist 的条件时,Redis 会使用 linkedlist 作为列表的内部实现。
上面这两种编码方式是 redis 之前的编码方式,现在的编码方式是以 quicklist 这样的数据结构来实现的,是ziplist 和 linkedlist 进行结合的!整体还是一个列表,但是列表的节点是一个压缩列表。
127.0.0.1:6379> lpush mylist 1 2 3 4 5 6
(integer) 6
127.0.0.1:6379> type mylist
list
127.0.0.1:6379> object encoding mylist
"quicklist"
使用场景
消息队列
如下图所示,Redis可以使用lpush+brpop命令组合实现阻塞式生产者-消费者模型队列,生产者客服端使用lpush从列表左边插入元素,多个消费者客服端使用brpop命令阻塞的等待从队列中获取元素。

分频道消息队列
Redis同样使用lpush+brpop命令,可以通过不同的键模拟频道概念,消费者可以通过brpop获取不同键值对应的值。
edis服务器 = 电视信号中心
不同频道(channel:news, channel:sports) = 不同的电视频道(CCTV-1, CCTV-5)
消息发布者(LPUSH) = 电视台制作节目
消费者(BRPOP) = 观众调台观看
央视新闻频道制作节目
LPUSH channel:news "晚间新闻:今日要闻..."
LPUSH channel:news "天气预报:明日晴转多云"
体育频道制作节目
LPUSH channel:sports "NBA总决赛精彩回放"
LPUSH channel:sports "世界杯预选赛分析"
观众小李只关心新闻,调到新闻频道
BRPOP channel:news 0 → 收到"晚间新闻:今日要闻..."
观众小王是体育迷,调到体育频道
BRPOP channel:sports 0 → 收到"NBA总决赛精彩回放"

用户画像
初级画像
姓名:李某某
年龄:28岁
城市:上海
职业:市场经理
中级画像
活跃时间:工作日晚上8-11点
兴趣偏好:美妆9分、穿搭8分、旅游7分
消费特征:月均消费5000元,偏好轻奢品牌
高级画像
潜在需求:可能近期有出国旅游计划
生命周期价值:高价值用户,预计年贡献2万元
流失风险:低(忠诚度高,互动频繁)
推荐策略:推送高端护肤品和海外旅行产品
用户画像就像是数字世界的镜子 ,它反映的不是真实的你,而是你在网络世界中的"数据投影"。这个投影帮助企业更好地理解和服务用户,但也需要平衡个性化体验 和隐私保护的关系。
实时记录用户行为(消息队列模式)
LPUSH user_behavior:track "小明|观看|视频123|猫咪,萌宠|2024-01-20 08:00:00"
LPUSH user_behavior:track "小明|点赞|视频456|游戏,电竞|2024-01-20 08:05:00"
消费者处理这些行为记录
BRPOP user_behavior:track 0 → 更新用户画像数据库
小明刷抖音看了这些视频
用户行为记录:
视频ID: 123, 标签: ["猫咪", "萌宠", "搞笑"]
视频ID: 456, 标签: ["英雄联盟", "游戏直播", "电竞"]
视频ID: 789, 标签: ["健身教程", "腹肌训练"]
Redis中记录小明的兴趣标签(使用Hash存储)
HSET user:小明:tags 猫咪 5 # 权重增加
HSET user:小明:tags 游戏 3
HSET user:小明:tags 健身 2