redis基本数据类型包含5种:string、list、set、map(散列),zset(有序set),下面分别列举各种数据类型对应的命令。
string
Redis字符串是动态字符串,是可以修改的字符串,结构上类似于Java中的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。可以使用的操作包括
set key value
get key value
del key value
expire key 5 //设置过期值
setex key 5 value // 同时设置过期时间和值
setnx key value //表示不存在的时候才进行设置
如果value是一个数值,可以对value进行自增,如果整数超过Long的最大值会产生错误。
incr key // 自增1
incrby key 5 //指定自增值
使用场景
String是基本类型任何场景都可以使用,通常用于缓存保存一个json串,单个状态或计数等。
分布式锁只用保存一个uuid所以可以使用string类型的的数据。
list
用来储存多个有序的字符串,列表中的每个字符串成为元素,在 Redis 中,可以队列表两端插入和弹出,还可以获取指定范围的元素列表、获取指定索引下的元素等,列表是一种比较灵活的数据结构,它可以充当栈和队列的角色。
Redis 底层存储的并不是一个简单的LinkedList,而是快速链表quickList。在列表元素较少时,使用一块连续的内存来储存,这个结构叫做zipList,也就是压缩链表,它将所有的元素紧挨着一起存储。当数据量较多时,改为quickList,这么做的原因是:普通的链表需要附加指针会占用空间,而且加重了内存的碎片化。所以Redis将链表和zipList结合组成了quickList,它将多个zipList通过双向指针串起来,这样既能满足快速插入删除性能,又不会出现严重的空间碎片化。
lpush list-key item
rpush list-key item
lpop list-key item
rpop list-key item
lindex list-key index
lrange list-key from to
使用场景
- 实现关注列表,粉丝列表等,通过list可以实现基于list的分页功能
- 保存浏览记录
- 结合阻塞操作实现阻塞队列,将需要延后处理的任务序列化成字符串,存到Redis的list列表中,另一个线程从这个列表中轮询数据进行处理。Redis 的 lpush + brpop 命令组合即可实现阻塞队列,生产者客户端是用 lpush 从列表左侧插入元素,多个消费者客户端使用 brpop 命令阻塞式的“抢”列表尾部的元素
set
Redis 的集合相当于Java 中的HashSet,它的内部实现相当于一个特殊的字典,字典中所有的value都是NULL。set集合中的元素无序且不能重复,可以用来存储活动中奖的用户id,可以保证同一个用户不会中奖两次。Redis 除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。合理的使用好集合类型,能在实际开发中解决很多实际问题。
sadd set-key item
srem set-key item
smembers set-key
sismember set-key item
sinterstore key1 key2 key3
使用场景
- 代替list优化查询效率,一般也用于保存一个分组,例如保存某个人的所有文章
- 基于set的运算,交并差等操作
hash
Redis的字典类似于Java中的HashMap。Redis 字典的值只能是字符串,而HashMap的值可以是多种类型。redis中的rehash不采用一次性rehash,而是通过渐进式hash,在后续对hash的操作中渐渐的将旧数组中的数据迁移到新数组中。所以在rehash时需要访问两个hash表,redis的字典需要维护两个hash表。
redis为字典保存两个hash表h0和h1渐进式rehash的步骤:
- 为h1分配空间,让字典同时持有h0和h1。
- 在字典中维持一个索引计数器rehash idx,初值为0,表示rehash工作正式开始。
- 在rehash进行期间,每次对字典执行添加、删除、查找或者更新操作时,程序就会顺带将ht[0]哈希表在rehashidx索引上所有的键值对rehash到ht[1],并将rehashidx的值加1。
- 随着字典操作的不断执行,最终ht[0]的所有键值对都会被rehash到ht[1],这时程序将rehashidx的值设为-1,表示rehash操作已完成。然后将ht[0]的空间释放掉,将ht[1]设置为ht[0]。
hset map-key item-key item-value
hget map-key item-key
hgetall map-key
hdel map-key item-key
使用场景
1、json对象可以直接保存为map类型,方便直接查询对应的字段
zset
zset中每个元素都有一个score,根据score进行排序。zset由ziplist和zskiplist两种结构组成,当有序集合保存的元素数量小于128个并且所有元素的长度都小于64字节时使用ziplist,每个元素使用两个连续的节点来保存,第一个节点保存元素的成员,第二个节点保存元素的分值。
如果元素数量草果128个且元素的长度大于64字节时使用zskiplist和dict,其中dict用于保存key/value对,方便通过key进行查找score,zskiplist用于保存有序的元素列表,按照分值对元素排序,便于执行range之类的命令。
跳表是一种链表加多层索引的结构,支持快速插入/删除/查找操作/平均查找复杂度是logn,空间复杂度n。跳表由zskiplist和在skip listNode两个结构构成,zskiplist结构用于保存跳跃节点相关的信息,比如节点的数量,表头表位节点的指针等;在skip list Node结构用于表示跳跃表节点。
跳表节点中有一个level数组,数组中每个元素都包含一个指向其他节点的指针,可以通过这些层来加快访问其他节点的速度。节点中还保存了元素的引用和分值,跳跃表中所有的节点都按照分值从小到大排序。
跳表相对红黑树和平衡树的优势:支持范围查找的方法更简单,节点的操作不需要涉及一些分裂和旋转操作。
zadd zset-key item score
zrange zset-key from to // 负数表示倒数
zrangebyscore zset-key min max
zrem zset-key item
zincreby zset-key item 1
zcard zeset-key //统计元素个数
zinterstore zset-dest 2 zset-src1 zset-src2 weights 1 2 //交集默认求和
zrank zset-key item //返回排序名次
使用场景
1、打榜排序,按消息维度进行排位
2、同步信号量
下面还有三个高级数据结构
bitset
SETBIT key offset value
GETBIT key offset
BITOP // 执行两个不同string的位操作.,包括AND,OR,XOR和NOT.
BITCOUNT // 统计位的值为1的数量。
BITPOS // 寻址第一个为0或者1的bit的位置
使用场景
bitset的优势是节省空间,如果只需要用到bool值表示状态,但是需要维护一个很长跨度的记录,可以考虑使用bitset节省空间,通过上面的各种命令可以实现一些有趣的功能。统计用户访问网站的天数,每次用户访问网站是将当前对应的位置为1,然后可以通过bitcount计算总天数。或者直接把结果取回本地,在本地对bitset进行分析。
HyperLogLogs
127.0.0.1:6380> PFADD hll a b c d d c
(integer) 1
127.0.0.1:6380> PFCOUNT hll
(integer) 4
127.0.0.1:6380> PFADD hll e
(integer) 1
127.0.0.1:6380> PFCOUNT hll
(integer) 5
127.0.0.1:6380> PFMERGE hlls hll1 hll2
hyperloglogs用于计算唯一事物的概率的数据结构,使用HLL时并不是真正添加项到HLL中(这一点和SETS结构差异很大),因为HLL的数据结构只包含一个不包含实际元素的状态。
使用场景
HLL数据结构的一个使用场景就是计算用户每天在搜索框中执行的唯一查询,即搜索页面UV统计。
GEO
geo可以将用户给定的地理位置(经度和纬度)信息储存起来,并对这些信息进行操作。
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEOHASH Sicily Palermo Catania
1) "sqc8b49rny0"
2) "sqdtr74hyu0"
redis> GEOPOS Sicily Palermo Catania NonExisting
1) 1) "13.361389338970184"
2) "38.115556395496299"
2) 1) "15.087267458438873"
2) "37.50266842333162"
3) (nil)
redis> GEODIST Sicily Palermo Catania
"166274.15156960039"
redis> GEORADIUS Sicily 15 37 100 km
1) "Catania"
redis> GEORADIUS Sicily 15 37 200 km
1) "Palermo"
2) "Catania"
redis> GEORADIUSBYMEMBER Sicily Agrigento 100 km
1) "Agrigento"
2) "Palermo"