参考书籍:《redis深度历险:核心原理与应用实践》
redis有5种数据结构,分别为string,list,set,hash,zset。redis的所有数据结构都是以唯一的key字符串作为名称,然后通过这个唯一的key值来获取相应的value数据。不同类型的数据结构的差异就在于value的结构不一样。对于除了string类型以外的所有类型,都是加入数据时如果没有则创建,当容器里的数据弹出完了,就删掉这个数据结构来释放空间。对于所有的数据结构,只要你创建了,就会一直存在于你的redis,就算关机了也是一样。除非你自己弹出数据完全释放,或者对你的key设置过期时间,到点自动删除,回收内存。同时,如果value值是一个整数,还可以对他进行自增操作。自增是有范围的,它的范围就是signed long的最大最小值,差偶偶这个值,redis会报错。
string:
redis的字符串是动态字符串,是可以修改的字符串。采用预分配冗余空间的方式来减少内存的频繁分配。当字符串的长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时只会依次多扩1M的空间。需要注意的是字符串最大长度为512M。字符串是由多个字节组成,每个字节又是由8个bit位组成,这样便可以将一个字符串看成是很多bit的组合,这便是位图。
#创建字符串 set name codehole #获得字符串 get name #获取存在字符串个数 exists name #删除字符串 del name #批量创建字符串 mset name1 boy name2 girl name3 unknown #批量获取字符串 mget name1 name2 name3#返回一个列表
list:
redis的列表是链表而不是数组,常用来做异步队列使用。将需要延后处理的任务结构体序列化成字符串塞进redis的list,另一个线程从这个链表中轮询数据进行处理。redis的list拥有lindex和Itrim(慢操作)lindex需要对链表进行遍历,性能随着index的增大而变差。ltrim的参数start_index和end_index定义了一个区间,在这个区间内的值,ltrim要保留,区间之外统统砍掉。我们可以通过ltrim来实现一个定长的链表。index与python中的很相似,也可以为负数,index=-1表示倒数第一个元素。
在深入一点,你会发现redis的底层存储是一个块表quicklist。首先,在列表元素较少的情况下会使用一块连续的内存存储,这个结构是压缩列表,他将所有的元素紧挨一起存储。当数据比较多的时候才会改成块表,将压缩列表进行链式存储。这样既满足了快速删除性能,又不会出现太大的空间冗余。
右进左出队列
#右边进入数据 rpush books python java golang #测量列表的数据个数 llen books #左边弹出数据 lpop books
右进右出栈
#右边输入数据 rpush books python java golang #右边弹出数据 rpop
hash:
redis的字典是无序字典,内部是数组+链表结构。第一维hash数组的位置冲突时,就将冲突元素用链表串接起来。redis的字典的值只能是字符串,采用了渐进式rehash策略。渐进式rehash会在rehash的同时,保留新旧两个hash结构,然后在后续的定时任务中乙级hash操作指令中,循序渐进得奖旧hash的内容一点点迁移到新的hash结构中。当搬迁完成时,就会使用新的hash结构取而代之。
#建立hash hset books java "think in java"#命令行的字符串如果包含空格要用引号括起来 hset books golang "concurrency in go" #批量建立 hmset books java "think in java" golang "concurrency in go" #获得所有数据 hget books#key和value间隔出现 #获得单个数据 hget books java #获得字典长度 hlen books
set:
set就是集合,相当于c++里的set,它内部的键值对是无序的唯一的。
#加入一个数据 sadd books python #输出所有的数据 smembeers books#注意顺序,set是无序的 #查询某个valu是否存在 sismember books python #获取长度 scard books #弹出一个 spop books
zset:
zset类似于set和hash的结合体,一方面它是一个set,保证了内部value的唯一性,另一方面,他可以给每个value赋予一个score,代表这个value的排序权重。它的内部实现用的是一种叫做跳跃列表的数据结构。跳跃列表是层级制。最下面的一层的所有元素都会使用指针串起来。然后每隔几个元素挑选出一个代表作为组长使用另外一级指针串起来,然后在这些代表里在挑选代表再串起来。
#创建zset zadd books 9.0 "think in java" zadd books 8.9 "java concurrency" zadd books 8.6 "java cookbook" #按score排序输出,参数区间为排名范围 zrange books 0 -1 #按score逆序输出,参数区间为排名范围 zrevrange books 0 -1 #输出zset的数据数量 zcard books #获取指定value的score zscore books "java concurrency" #排名 zrank books "java concurrency" #根据分值区遍历zset zrangebyscore books 0 8.91 #根据分值区遍历,同时返回分值 zrangebyscore books 0 8.91 whithscores #删除value zrem books "java concurrency"
过期时间:
set name codehole #设置5秒后过期 expire name 5 #创建时直接设置过期时间 setex name 5