一,概念
list,列表,可以实现左进左出,右进右出,可以存在重复值,具有下标等特性。
二,常用命令
1.插入
左进一个:lpush key value value value...
底层执行过程是 a, b a , c b a 。所以最后输出的时候是c b a。
左一次性进入多个: 与分别进入,是一个效果,只不过减少了命令发送次数。
右进同理,但是它的顺序就不相同了。
2.删除
1.左出:直接弹出下标为0的元素:lpop key
2.右出:弹出最后一个元素:rpop key
3.删除范围外的元素,只留下范围内的元素:
由于只有4个元素,所以没有删除,但是范围扩大,也没有产生错误。
4.删除指定value值的元素
lrem key count value
ListOperations<String, String> listOperations = redisTemplate.opsForList();
Long remove = listOperations.remove("mylist", 0, "aa");
System.out.println(remove);
3.获取
1.通过索引获取
2.通过下标范围获取
ListOperations<String, String> listOperations = redisTemplate.opsForList();
List<String> mylist = listOperations.range("mylist", 0, 10);
for(int i=0;i<mylist.size();i++){
System.out.println(mylist.get(i));
}
3.获取列表长度
4.修改
通过下标进行修改
count的含义:+n,从左边开始,删除n个值为value的元素,为-n表示从右边开始删除n个值为value的元素。count=0,表示删除全部值为value的元素。
可以用来去重。
三,应用场景分析
1.异步队列
2.热点数据
3.对数据量大的集合数据删减:列表数据显示,关注列表,粉丝列表,留言评论,热点新闻。
四,底层原理
编码方式:ziplist , linkedlist ---》 quicklist
早期的redis使用的是ziplist 和 linkedlist两种方式,当元素少时使用ziplist,元素多时使用linkedlist。考虑到链表的附加空间相对太高,prev和next指针要占去一共16个字节空间,另外每个节点的内存都是单独分配,会加剧内存的碎片化,影响内存管理效率。所以redis新版本对列表数据结构进行了改造,使用quicklist代替ziplist和linkedlist。
编码转换:老版本:当列表保存的所有字符串的长度<64字节,而且列表对象保存的元素数量<512个的时候,就使用ziplist存储,不满足就使用linkedlist来存储。(这个上限值是可以修改的。)
新版本
struct quicklistNode{
quicklistNode* prev;
quicklistNode* next;
ziplist* zl; //指向 压缩列表
int32 size; //ziplist的字节总数
int16 count; //ziplist中的元素数量
int2 encoding; //存储形式2bit ,原生字节数组还是LZF 压缩存储
....
}
struct quicklist{
quicklistNode* head;
quicklistNode* tail;
long count; // 元素总数
int nodes; //ziplist 节点的个数
int compressDepth; //LZF算法压缩深度
...
}
结构图:
quicklist参考:https://www.jianshu.com/p/d1138ad60ff6