redis五种罕用的数据结构为string (字符串)、list (列表)、set (汇合)、hash (哈希) 和 zset (有序汇合)。小白易读,倡议珍藏。

万丈高楼平地起

reids是键值对构造的NoSql数据库,key都是字符串,常说的数据类型不同,说的都是value

redis所有的数据都会有一个dicEntry,泛滥dicEntry组成一个链表。上方那个sds就是key,能够看出是一个字符串。下方那个绿色的redisObject就是value。能够看出图中给的例子就是string类型。redisObject会指向实在的数据(比方图中的字符串“world”)。前面咱们说的数据类型特指value局部。

string (字符串)

Redis 的字符串是动静字符串,是能够批改的字符串。当字符串长度小于 1M 时,扩容都是加倍现有的空间,如果超过 1M,扩容时一次只会多扩 1M 的空间。一个字符串最大能够接受512M。

罕用指令

设置获取值

127.0.0.1:6379> set name pjjltOK127.0.0.1:6379> get name"pjjlt"127.0.0.1:6379> exists name(integer) 1

设置应用set,获取应用get,查看某key是否存在用exists

设置过期工夫

127.0.0.1:6379> setex company 10  gongsiOK127.0.0.1:6379> get company"gongsi"127.0.0.1:6379> get company(nil)

能够在设置值的时候间接指定,keycompany能够存活10秒。此外,也能够将设置值设置过期工夫离开,应用expire

127.0.0.1:6379> set company gongsiOK127.0.0.1:6379> expire company 10(integer) 1127.0.0.1:6379> get company"gongsi"127.0.0.1:6379> get company(nil)

保障不笼罩value

redis还提供了命令,在设置值的时候,如果发现key已存在,此次设置失败,保障原始value不被笼罩。应用setnx命令。

127.0.0.1:6379> setnx company gongsi(integer) 1# 能够看到第二次设置失败,返回值为 0.127.0.0.1:6379> setnx company haha(integer) 0127.0.0.1:6379> get company"gongsi"

批量设置获取值

127.0.0.1:6379> mset name pjjlt age 26 company gongsiOK127.0.0.1:6379> mget name age company1) "pjjlt"2) "26"3) "gongsi"

批量设置应用mset,批量获取应用mget。批量设置获取,缩小IO,进步性能,你值得领有。

计数

redis还能够通过自增的形式计数。

127.0.0.1:6379> set key 10OK127.0.0.1:6379> incr key(integer) 11127.0.0.1:6379> incr key(integer) 12# 字符串报错127.0.0.1:6379> set key2 hahaOK127.0.0.1:6379> incr key2(error) ERR value is not an integer or out of range# 超出long的范畴127.0.0.1:6379> set key3 9223372036854775807OK127.0.0.1:6379> incr key3(error) ERR increment or decrement would overflow# key4不存在127.0.0.1:6379> incr key4(integer) 1127.0.0.1:6379> incr key4(integer) 2

能够通过incr关键字自增,能够看出key自增了两次。不能给字符串自增,那样会报错,例如key2。不能超过long的范畴,那样也会报错,例如key3。如果初始key不存在,则增从0开始,例如key4。

追加值

127.0.0.1:6379> set name pjOK127.0.0.1:6379> append name jlt(integer) 5127.0.0.1:6379> get name"pjjlt"

字符串长度

127.0.0.1:6379> get name"pjjlt"127.0.0.1:6379> strlen name(integer) 5

设置并返回原先值

127.0.0.1:6379> get name"pjjlt"127.0.0.1:6379> getset name mj"pjjlt"127.0.0.1:6379> get name"mj"

设置指定地位的字符

127.0.0.1:6379> get name"mj"127.0.0.1:6379> setrange name 0 p(integer) 2127.0.0.1:6379> get name"pj"

获取局部字符串

127.0.0.1:6379> set name pjjltOK127.0.0.1:6379> getrange name 0 2"pjj"

总结

命令解释
set设置值
get获取值
setex设置值并增加过期工夫
setnx保障不笼罩value
mset批量设置值
mget批量获取值
incr计数
append追加值
strlen字符串长度
getset设置并返回原先值
setrange设置指定地位的字符
getrange获取局部字符串

外部编码

尽管某种数据类型的value名称是统一的,比方都是string,然而依据数据量的大小,会采纳不同的外部编码,这样能够更高效的利用空间嘛。外部编码类型也贮存在redisObject中。利用object encoding key可查看外部编码类型。

int:长整型,超过长整型或者是字符串会降级。

embstr:小于等于44个字节的字符串。笔者用的是redis5.0.9,有人说这个字节范畴是39,亲测是44。查了一下,源码的确改了,当初是44.

raw:大于44个字节的字符串。

127.0.0.1:6379> set name 1234567890OK127.0.0.1:6379> object encoding name"int"# 这里设置44个字符127.0.0.1:6379> set name qwertyuiopqwertyuiopqwertyuiopqwertyuiopqwerOK127.0.0.1:6379> object encoding name"embstr"# 这里设置45个字符127.0.0.1:6379> set name qwertyuiopqwertyuiopqwertyuiopqwertyuiopqwertOK127.0.0.1:6379> object encoding name"raw"

应用场景

能够用于计数,比方网站访问量。
能够共享Session,比方分布式系统,多个实例验证用户是否登录。
能够限速,比方管制一个ip或者一个用户肯定工夫内拜访次数。

list (列表)

Redis 的列表相当于 Java 语言外面的 LinkedList,留神它是链表而不是数组。这意味着list 的插入和删除操作十分快,工夫复杂度为 O(1),然而索引定位很慢,工夫复杂度为O(n)。list的两端都能够弹入弹出数据,所以能够做队列

栈与队列

栈如同一个死胡同,只有一个进口,后进来的先出,先进来的后出。

127.0.0.1:6379> rpush books python java golong(integer) 3127.0.0.1:6379> rpop books"golong"127.0.0.1:6379> rpop books"java"127.0.0.1:6379> rpop books"python"127.0.0.1:6379> rpop books(nil)

数据从左边进(rpush),左边出(rpop),先进去的最初进去。

队列

队列如同排队打饭的同学们,先进先出。

127.0.0.1:6379> rpush books python java golong (integer) 3127.0.0.1:6379> lpop books"python"127.0.0.1:6379> lpop books"java"127.0.0.1:6379> lpop books"golong"127.0.0.1:6379> lpop books(nil)

数据从左边进(rpush),右边出(lpop),先进先出。

常用命令

向队列任意地位退出元素

方才演示的rpushlpush都是从中间退出元素,这两个命令不再演示。还能够应用linsert在某指定元素前或后插入新的元素。

127.0.0.1:6379> rpush books python java golong(integer) 3# 在java后面插入 ruby127.0.0.1:6379> linsert books before java ruby(integer) 4# 在java前面插入 c#127.0.0.1:6379> linsert books after java c#(integer) 5# 查看所有元素127.0.0.1:6379> lrange books 0 -11) "python"2) "ruby"3) "java"4) "c#"5) "golong"

依据下面在java前后插入了rubyc#

查找元素

127.0.0.1:6379> lrange books 0 -11) "python"2) "ruby"3) "java"4) "c#"5) "golong"127.0.0.1:6379> lindex books 2"java"127.0.0.1:6379> llen books(integer) 5

指令简略,索性写一块吧。
lrange能够遍历列表,参数为startend。这里0 -1,是指从第一个到最初一个,即遍历列表。
lindex查找指定地位的元素,参数是下标值。这个命令是慢查问,须要遍历链表。
llen能够查看列表元素个数。

删除数据

方才演示的rpoplpop能够弹出一个元素,不再演示。

能够应用lrem 删除多个同一元素
count > 0:从左到右,删除最多 count 个元素。
count < 0:从右到左,删除最多 count 绝对值 个元素。
count = 0,删除所有。

# 从左删除a元素,删除了3个127.0.0.1:6379> rpush char a a b b a a c (integer) 7127.0.0.1:6379> lrem chae 3 a(integer) 0127.0.0.1:6379> lrem char 3 a(integer) 3127.0.0.1:6379> lrange char 0 -11) "b"2) "b"3) "a"4) "c"# 从右删除 3 个a元素127.0.0.1:6379> rpush char1 a a b b a a c (integer) 7127.0.0.1:6379> lrem char1 -3 a(integer) 3127.0.0.1:6379> lrange char1 0 -11) "a"2) "b"3) "b"4) "c"# 删除所有 a 元素127.0.0.1:6379> rpush char2 a a b b a a c(integer) 7127.0.0.1:6379> lrem char2 0 a(integer) 4127.0.0.1:6379> lrange char2 0 -11) "b"2) "b"3) "c"

还能够应用ltrim截取一部分数据,删除其余数据

127.0.0.1:6379> rpush char3 a b c d e f g(integer) 7127.0.0.1:6379> ltrim char3 1 3OK127.0.0.1:6379> lrange char3 0 -11) "b"2) "c"3) "d"

批改

127.0.0.1:6379> lrange books 0 -11) "python"2) "ruby"3) "java"4) "c#"5) "golong"127.0.0.1:6379> lset books 2 javaScriptOK127.0.0.1:6379> lrange books 0 -11) "python"2) "ruby"3) "javaScript"4) "c#"5) "golong"

能够用lset更改某个地位上的元素,这也是个慢查问,工夫复杂度为O(n)。

阻塞操作

blpopbrpoplpoprpop根底上减少了阻塞工夫,如果间接获取,发现列表中没有数据,那么会阻塞期待一段时间,如果该段时间内还是无奈失去数据,就返回期待时长。若设置的工夫是0的话,即为有限期待。这里须要两个终端做配合。

# 终端1 127.0.0.1:6379> lpop books(nil)127.0.0.1:6379> blpop books 5(nil)(5.06s)# 这里须要在终端1 执行blpop后插入一条数据127.0.0.1:6379> blpop books 201) "books"2) "java"(4.61s)# 这里须要在终端1 执行blpop后插入一条数据127.0.0.1:6379> blpop books 01) "books"2) "python"(9.66s)# 除此之外,还能够同时阻塞多个队列,先有数据的那个弹出127.0.0.1:6379> blpop books schools 01) "schools"2) "hzsy"(26.75s)

总结

命令解释
rpush lpush弹入数据
rpop lpop弹出数据
brpop blpop阻塞弹出数据
linsert向队列任意地位退出元素
lrange遍历列表
lindex查找指定地位上元素
llen列表长度
lrem删除多个同一元素
ltrim截取指定列表
lset批改列表指定地位元素

外部编码

ziplist:当列表的元素个数小于list-max-ziplist-entries配置(默认 512 个),同时列表中每个元素的值都小于list-max-ziplist-value 配置时(默认 64 字节),Redis 会选用ziplist 来作为 列表 的外部实现来缩小内存的应用。
linkedlist:当列表类型无奈满足ziplist的条件时,Redis会应用linkedlist作为列表的外部实现。

应用场景

能够做或者队列
还能够利用阻塞性能做音讯队列

hash (哈希)

Redis 的字典相当于Java语言外面的HashMap,它是无序字典。外部实现构造上同Java的HashMap也是统一的,同样的数组 + 链表二维构造。扩容rehash的时候,采纳渐进式。在rehash时,保留两个新旧hash构造,查问的时候都查,再依据定时工作,一点点将旧hash上的数据迁徙到新的hash上,迁徙结束,旧hash被删除,并发出内存。咱们默认key为hashKey,filed为小key

常用命令

设置值

127.0.0.1:6379> hset user name pjjlt(integer) 1127.0.0.1:6379> hset user age 26(integer) 1127.0.0.1:6379> hset user company gongsi(integer) 1

获取值

127.0.0.1:6379> hget user name"pjjlt"

删除field

127.0.0.1:6379> hdel user company(integer) 1

计算field个数

127.0.0.1:6379> hlen user(integer) 2

批量设置获取值

127.0.0.1:6379> hmset user name pjjlt age 26 city shijiazhuangOK127.0.0.1:6379> hmget user name age1) "pjjlt"2) "26"

判断filed是否存在

127.0.0.1:6379> hexists user name(integer) 1

获取所有filed或者value

127.0.0.1:6379> hkeys user1) "name"2) "age"3) "city"127.0.0.1:6379> hvals user1) "pjjlt"2) "26"

获取所有filed和value

127.0.0.1:6379> hgetall user1) "name"2) "pjjlt"3) "age"4) "26"5) "city"6) "shijiazhuang"

自增

127.0.0.1:6379> hincrby user age -8(integer) 18127.0.0.1:6379> hset user scroe 99.6(integer) 1127.0.0.1:6379> hincrbyfloat user scroe 0.4"100"

hincrbyhincrbyfloat别离减少或者缩小整型浮点型

计算值的长度

127.0.0.1:6379> hget user name"pjjlt"127.0.0.1:6379> hstrlen user name(integer) 5

总结

命令解释
hset设置值
hget获取值
hdel删除值
hlen计算field个数
hmset批量设置值
hmget批量获取值
hexists判断field是否存在
hkeys获取所有field
hvals获取所有value
hgetall获取所有filed和value
hincrby减少整型数值
hincrbyfloat减少浮点型数值
hstrlen计算值的长度

外部编码

ziplist:当列表的元素个数小于list-max-ziplist-entries配置(默认 512 个),同时列表中每个元素的值都小于list-max-ziplist-value 配置时(默认 64 字节),Redis 会选用ziplist 来作为 列表 的外部实现来缩小内存的应用。

hashtable:当哈希类型无奈满足ziplist的条件时,Redis会应用hashtable作为哈希的外部实现,因为此时ziplist的读写效率会降落,而hashtable的读写工夫复杂度为O(1)。

应用场景

hash很适宜缓存对象,比方商城零碎能够寄存商品,hashkey为商品id,field为各种属性,value为数据。当然string也能够寄存商品,只不过它的value,时json串,还须要解析,从代码角度和网络代价来讲都不如hash

set (汇合)

set相当于Java语言外面的 HashSet,它外部的键值对是无序的惟一的。它的外部实现相当于一个非凡的字典,字典中所有的value都是一个值NULL。

常用命令

减少元素

127.0.0.1:6379> sadd books java python python ruby java(integer) 3

sadd能够增加一个或者多个元素,并且去重。

删除元素

127.0.0.1:6379> srem books python ruby(integer) 2

srem能够删除一个或者多个元素。

计算元素个数

127.0.0.1:6379> sadd books python ruby c#(integer) 3127.0.0.1:6379> scard books(integer) 4

判断元素是否在汇合中

127.0.0.1:6379> sismember books java(integer) 1127.0.0.1:6379> sismember books c(integer) 0

随机返回肯定数量的元素

127.0.0.1:6379> srandmember books 21) "java"2) "ruby"127.0.0.1:6379> srandmember books 21) "c#"2) "ruby"

随机弹出一个元素

127.0.0.1:6379> spop books"ruby"127.0.0.1:6379> scard books(integer) 3

获取所有元素

127.0.0.1:6379> smembers books1) "c#"2) "java"3) "python"

计算并查集

127.0.0.1:6379> sadd set1 a b c d e(integer) 5127.0.0.1:6379> sadd set2 d e f g(integer) 4# 计算两个汇合交加127.0.0.1:6379> sinter set1 set21) "e"2) "d"# 计算两个汇合并集127.0.0.1:6379> sunion set1 set21) "g"2) "a"3) "d"4) "e"5) "c"6) "f"7) "b"# 计算两个汇合差集127.0.0.1:6379> sdiff set1 set21) "c"2) "b"3) "a"

总结

命令解释
sadd减少元素
srem删除元素
scard计算元素个数
sismember判断元素是否在汇合中
srandmember随机返回肯定数量的元素
spop随机弹出一个元素
smembers获取所有元素
sinter计算两个汇合交加
sunion计算两个汇合并集
sdiff计算两个汇合差集

外部编码

intset:当汇合中的元素都是整数且元素个数小于set-max-intset-entries配置(默认 512 个)时,Redis会选用intset来作为汇合的外部实现,从而缩小内存的应用。

hashtable:当汇合类型无奈满足intset的条件时,Redis会应用hashtable作为汇合的外部实现。

应用场景

利用并查集能够用于查找用户共同爱好。

利用不可重复性,能够用于抽奖,保障每个用户只能中一次奖。

zset(有序汇合)

zset可能是Redis提供的最为特色的数据结构。它相似于Java的SortedSet和HashMap的结合体,一方面它是一个set,保障了外部value的唯一性,另一方面它能够给每个value赋予一个score,代表这个value的排序权重。

常用命令

# 设置值127.0.0.1:6379> zadd books 9 java(integer) 1127.0.0.1:6379> zadd books 8 python(integer) 1127.0.0.1:6379> zadd books 7 golang(integer) 1# 查看肯定范畴内的值127.0.0.1:6379> zrange books 0 -11) "golang"2) "python"3) "java"# 删除某个值127.0.0.1:6379> zrem books golang(integer) 1# 依据score 正序排127.0.0.1:6379> zrange books 0 -11) "python"2) "java"# 依据score 顺叙排127.0.0.1:6379> zrevrange books 0 -11) "java"2) "python"# 查看元素个数127.0.0.1:6379> zcard books(integer) 2# 查看某元素分值127.0.0.1:6379> zscore books java"9"# 正序排名,从0开始127.0.0.1:6379> zrank books  python(integer) 0127.0.0.1:6379> zrank books java(integer) 1# 肯定范畴内scor内的元素127.0.0.1:6379> zrangebyscore books 0 8.81) "python"

总结

命令解释
zadd设置值
zrange查看肯定范畴内的值
zrem删除某个值
zrange依据score正序排
zrevrange依据score顺叙排
zcard查看元素个数
zscore查看某元素分值
zrank正序排名,从0开始
zrangebyscore肯定范畴内scor内的元素

外部编码

zset外部的排序功能是通过「跳跃列表」数据结构来实现的,它的构造十分非凡,也比较复杂。举个例子吧,就如同一个公司,有9个员工,分为3各小组,每个小组算一个小组长(留神小组长还具备员工角色,只不过多了小组长角色)小组长再选出一个技术总监(技术总监同时具备员工、小组长、技术总监角色)

应用场景

适宜排名性质的场景,比方微博热搜,某技术网站热门博客等等。

总结不易,小伙伴给个赞再走吧。