云计算百科
云计算领域专业知识百科平台

Redis核心数据类型精讲:string/hash/list 命令详解与实战场景----《Hello Redis!》(2)

文章目录

  • string类型
    • 有关string类型的命令
    • string在Redis中的应用场景
  • hash类型
    • 有关hash的命令
    • hash在Redis中的应用场景
  • list(列表)
    • 有关list的命令
    • list在Redis中的应用场景

string类型

Redis中的所有的key都是字符串,但是value的类型是存在差异的(比如可以是hash啥的)

Redis中的字符串,都是按照二进制数据的方式存储的,不会做任何的编码转换,所以出现乱码问题的概率比mysql还小

Redis中的string不单单是用来存普通文本字符串的,还能存整数,json,二进制数据(图片,视频)这些–但是redis对string类型限制了大小的(最大是512M)

关于string类型的内部编码:

8个字节的长整型一般用int(比如1314),小于等于…字节的字符串一般用embstr,大于…字节的字符串一般用raw

注意:redis存储小数,本质还是当作字符串来存储,这就意味着每次进行算术运算,都需要把字符串转成小数,进行运算后再转会字符串进行保存

Redis会根据当前值的类型和长度动态决定使用哪种内部编码实现

如果在某个场景下,需要我们把redis规定应该用raw存储时的场景改成用embstr存储的话,改的方法:

1.先看redis是否提供了对应的配置项,能修改这个规定 2.如果没有提供配置项,那就需要对源码进行魔改了(所以大厂一般都自己造轮子)

有关string类型的命令

关于key的取名,业内一般:[项目名/前缀] : [模块名] : [业务主体] : [唯一标识/ID] : [具体属性]

eg:bbs:post:5521:likes论坛系统里面存5521号帖子的点赞数

set: 语法:set key value [EX seconds | PX milliseconds] [NX|XX]

EX seconds:使用秒为单位设置key的过期时间

PX milliseconds使用毫秒为单位设置key的过期时间

NX:key不存在时才set;key存在就不set

XX:key存在时才设置;key不存在就不set

默认是key之前存在就覆盖(关于这个key的ttl也全部失效)

时间复杂度O(1),返回值:设置成功返回OK;如果由于条件不满足,set不执行的话会返回nil

样例:SET user_1001 "更新后的用户信息" EX 3600 XX

mset:一次可以设置多个key的值 语法:MSET key value [key1 value1 …]

时间复杂度:O(N)N是key的个数,返回值:OK

当然,还有SETNX SETEX和PSETEX这几个,相当于set指令的简便版

get:获取key对应的value(如果value的数据类型不是string的话,会报错)

语法:get key

时间复杂度:O(1),返回值:key对应得value;key不存在时是nil

注意:如果获取的是非英文(比如中文)的话,客户端会对非英文字符进行十六进制转义展示(除非启动时–raw,才会显示原始字节流)

mget:一次性获取多个key的值 语法:MGET key [key1…]

时间复杂度:O(N)N是key的个数 返回值:对应value的列表

set与mset或者get与mget的区别:使用mset或者mget可以有效减少网络时间,性能相对较高

引申指令:flushall会把redis上所有的键值对都带走–但是注意:在公司千万不要用!!!这跟删库没区别了

计数命令:

incr是让value+1

incrby是让value+n

decr是让value-1

decrby是让value-n

incrbyfloat是让value+小数(小数为负就等效于-了)

更加详细的介绍:

incr 语法:incr key 使用时,key对应的value必须是整数!(如果key不存在就自动创建一个value为0的key去搞)

时间复杂度:O(1) 返回值:最后处理完的value值

注意:如果key对应的value不是一个整型或者范围超过了64位有符号整数,就报错

引申:redis的整数是64位的有符号整数

incrby 语法:incrby key n 其他的跟上面一样(包括时间复杂度)

decr 语法:decr key 其他的跟上面一样(包括时间复杂度)

decrby 语法:decrby key n 其他的跟上面一样(包括时间复杂度)

incrbyfloat 语法:incrbyfloat key 小数 使用时,key对应的value必须是string或者浮点数,不然就报错(支持用科学计数法表示浮点数)–(如果key不存在就自动创建一个value为0的key去搞)

时间复杂度:O(1) 返回值:返回处理完之后的value值

对字符串本身进行操作的指令:

append追加字符串(在key的最后追加上value,如果key不存在,就相当于set的效果了) 语法:append key value

时间复杂度:O(1) 返回值:追加完成之后string的长度(单位是字节,一个汉字就多半不止一个字节)–跟以字符为长度区分

eg:append key1 你好 ,注意:

setrange覆盖字符串的一部分 语法:setrange key …(偏移量) value就是用value把key…之后的部分覆盖了

eg:set key "Helloa" setrange key 0 "dog"之后就成了dogloa

`set key "Hello" setrange key 1 aaaaaaa`之后就成了`Haaaaaaa`

`setrange key 1 aaa`,`key`里面就是`\\x00aaa`,前面没填的地方会自动补0(key不存在的话会出现这种情况)

时间复杂度:O(N)N是修改后value的长度 返回值:被修改后的字符串的总字节长度

注意:字符串的偏移量是从0开始的

strlen获取字符串长度 语法:strlen key

时间复杂度是O(1),返回值是字符串的总字节长度,如果key不存在,就返回0

getrange截取字符串 语法:getrange key start end(左闭右闭)

时间复杂度是O(N)N是需要截取的长度 返回值:截取到的子串(start的理论位置>end的话会返回空)

注意:这里的start和end可以为负,比如为-1就是倒数第一个字符

eg:set key hello getstart key 0 -1那截取的就是hello 如果是-1 0的话就是返回空

引申:编程的区间要么是左闭右开,要么是左闭右闭

string在Redis中的应用场景

1.在MySQL+Redis(存热点数据)时会用到string来进行热点数据的缓存

key一般是业务名:对象名:唯一标识:属性 然后value存热点数
eg: SET user:info:1001 '{"id":1001,"name":"张三","age":25}' # 缓存热点数据:用户ID=1001的信息

2.在Redis中进行数据统计–比如:统计某个视频的播放次数

3.用Redis中的string类型来存session信息(单独一个服务器),然后来让所有服务器能够共享读取

4.在Redis中用string来存储手机验证码

用key eg: sms::code::手机号 value:验证码本身 来进行手机号的验证码验证

多久用Redis进行数据统计 多久用MySQL进行数据统计:

Redis负责是实时统计+异步方式同步给MySQL MySQL负责持久化的精准统计–比如:本月商品点击排行

hash类型

如果value是hash类型的话,一个value里面就有多个field-value

关于hash类型的内部编码:

如果哈希中的元素个数比较少或者哈希的每个value的长度都比较短,用ziplist;不然就用hashtable

–具体的量可以通过修改redis.conf里面的hash-max-ziplist-entries和hash-max-ziplist-vlaue来改动

关于ziplist跟hashtable的区别:

hashtable就是带编号的快递柜

ziplist是塞满文件的文件夹(所有文件按顺序排好,没有留空地;但是找文件需要一个一个去找)

有关hash的命令

hset:设置hash中指定的字段(field)的值(value) 语法:hset key field1 value1 [field2 value2 …]

返回值:添加的字段的个数 时间复杂度:O(N)插入N个field

hget:获取hash中指定字段的值 语法: hget key field

返回值:字段对应的值;字段不存在时返回nil 时间复杂度:O(1)

hexists:判断hash中是否存在指定字段 语法: hexists key field

返回值:1表示字段存在,0表示字段不存在 时间复杂度:O(1)

hdel:删除hash中指定的字段 语法: hdel key field [field …]

返回值:本次操作删除的字段个数 时间复杂度:O(N)N为删除字段的个数

hkeys:获取hash中的所有字段 语法: hkeys key

返回值:字段列表 时间复杂度:O(N), N为这个key中field的个数

–这个一般也是不用的,也容易阻塞

hvals:获取hash中的所有值 语法: hvals key

返回值:所有值的列表 时间复杂度:O(N), N为key中field的个数

–这个一般也是不用的,容易阻塞

hgetall:获取hash中的所有字段和对应的值 语法: hgetall key

返回值:字段和对应值的列表(成对返回) 时间复杂度:O(N), N为key中field的个数

–这个一般都是不用的,因为很容易阻塞Redis!!!

–获取hash中所有字段和对应的值一般用hscan(这个是采用的渐进式遍历)

hmget:一次获取hash中多个字段的值 语法: hmget key field [field …]

返回值:字段对应的值,字段不存在时返回nil 时间复杂度:O(N), N为查询元素个数

hlen:获取hash中的所有字段的个数 语法: hlen key

返回值:字段的个数 时间复杂度:O(1)

hsetnx:仅当字段不存在时,设置hash中的字段和值 语法: hsetnx key field value

返回值:1表示设置成功,0表示设置失败(字段已存在) 时间复杂度:O(1)

hincrby:将hash中字段对应的数值添加指定的整数值 语法: hincrby key field increment

返回值:该字段变化之后的值 时间复杂度:O(1)

hincrbyfloat:将hash中字段对应的数值添加指定的浮点数值 语法: hincrbyfloat key field increment

返回值:该字段变化之后的值 时间复杂度:O(1)

hash在Redis中的应用场景

1.Redis作为缓存时,如果存储的是结构化数据+需要频繁修改或者频繁读取单个字段,那优先用hash而不是string

关于MySQL这种关系型数据库和Redis中的hash的区别:

Redis中的hash的每个键能有不同的file;但是关系型数据库添加新的列的话,所有的行都要给它设值

关系型数据库可以进行复杂的关系查询;但是Redis的hash想要这样的话需要模拟,维护成本就特别高

缓存用户信息的三种方式的对比:

1.使用字符串类型,每个属性一个键 –这个太低内聚了

2.序列化的字符串类型 –极少改写或者读取单个字段时用

3.hash类型 –需要频繁修改或者频繁读取单个字段时用这个

list(列表)

Redis里面的List就是一个双端都可以插入和弹出的数组

在这里插入图片描述

搭配rpush和lpop用就相当于队列 搭配rpush和rpop用就相当于栈

但是Redis里面的队列一般用stream,除非特别顺便的场景才用list

引申:Redis的下标是支持负数的(比如-1就是最后一个位置)–鲁棒性

Redis的下标第一个位置也是`0`

注意:Redis那个显示结果集对的序号并不代表是下标!!!

列表类型的特点:

1.列表中的元素是有序的 2.列表中的元素是允许重复的

关于list的内部编码:

当元素个数较少且没有大元素的话,用的ziplist;如果某个元素长度一定程度(比如64字节)的话,用的linkedlist;如果元素个数超过一定程度(比如512)的话,用的linkedlist

(具体程度在redis.conf里的list-max-ziplist-entries和list-max-ziplist-value里面调)

–但是Redis3.2之后,list的默认实现改成了quicklist

关于quicklist:

这个整体是个链表,然后链表的每个节点是一个压缩列表(每个压缩列表都不能太大)

有关list的命令

lpush:将一个或多个元素从左侧放入list中 语法: lpush key element1 [element2 …]

返回值:插入后list的长度 时间复杂度:O(N), N为插入元素个数

–如果key已经存在且对应的value不是list就会报错

eg:lpush key 1 2 3 4那插入后的列表中就是4 3 2 1

lpushx:仅当key存在时,将一个或多个元素从左侧放入list中;key不存在则立马返回0–其他的跟lpush一样

rpush:将一个或多个元素从右侧放入list中–其他的跟lpush一样

rpushx:仅当key存在时,将一个或多个元素从右侧放入list中;key不存在则立马返回0–其他的跟lpush一样

lrange:获取list中从start到stop区间的所有元素(左闭右闭) 语法: lrange key start stop

返回值:指定区间内的元素列表 时间复杂度:O(N)

lpop:从list左侧取出元素 语法: lpop key

返回值:取出的元素;取出失败返回nil 时间复杂度:O(1)

rpop:从list右侧取出元素–其他的跟lpop一样

–lpop和rpop在Redis6.2只会又加了个count参数,自己这没有介绍

它俩的阻塞版本是blpop和brpop

如果list中存在元素,blpop和brpop就跟lpop和rpop的作用完全相同

如果list为空,blpop和brpop就会产生阻塞,一直阻塞到队列不空为止

–如果是同时对多个key进行操作的话,只要有一个成功了就返回

–如果多个客户端同时对同一个键执行这俩pop,最先执行的客户端最先得到,其他的继续等

blpop:从list左侧阻塞式弹出元素,列表为空时阻塞等待,直到有元素或超时 语法: blpop key1 [key2 …] timeout

返回值:返回弹出元素的key和值;超时返回nil 时间复杂度:O(1)

–timeout为0表示无线阻塞,其他的表示最多阻塞…秒(Redis6.0及以上才支持小数) brpop:从list右侧阻塞式弹出元素,列表为空时阻塞等待,直到有元素或超时–其他的跟blpop一样

lindex:获取list中从左数index位置的元素 语法: lindex key index

返回值:获取的元素;获取失败返回nil 时间复杂度:O(N)

linsert:在list中pivot的前面或后面插入元素 语法: LINSERT key <BEFORE | AFTER> pivot(不是下标,是值) 插入啥元素

返回值:插入后的list长度;pivot不存在时返回-1,key不存在时返回0 时间复杂度:O(N)

如果存在多个值等于pivot的话,会从左往右找定位到第一个符合这个值的位置

eg:linsert key before "WORLD" "HELLO"

llen:获取list的长度 语法: llen key

返回值:list的长度;key不存在时返回0 时间复杂度:O(1)

lrem:移除list中与element相等的元素 语法: lrem key count element

count>0是从列表左侧开始,删除最多count个符合条件的元素

count<0是从列表右侧开始,删除最多-count个符合条件的元素

count==0是删除列表中所有符合条件的元素

返回值:被移除元素的数量;无匹配元素时返回0 时间复杂度:O(N+M), N为list长度,M为删除元素个数

ltrim:保留list中[start,stop]的元素,删除区间外的所有元素 语法: LTRIM key start stop

返回值:执行成功时返回OK 时间复杂度:O(N), N为列表长度

lset:根据下标修改list中指定位置的元素 语法: lset key index element

返回值:执行成功时返回OK;index越界或key不存在时报错 时间复杂度:O(N)

list在Redis中的应用场景

1.Redis里面实现基础的阻塞消息队列

生产者:用lpush/rpush把消息写到list里 消费者:用brpop/blpop阻塞式从list里取消息,多个消费者同时抢信息

2.Redis里面实现分频道/主题的消息队列

生产者:按消息类型,把消息写道不同的list key里 消费者:用brpop监听自己关心的频道key

3.微博/朋友圈这种的时间线

发微博:把这篇微博的IDlpush到用户的timeline linst里 刷微博:用lrange取指定范围的微博ID 4.进行关联数据的存储

用hash存学生详细信息,用list存每个班里有哪些学生

赞(0)
未经允许不得转载:网硕互联帮助中心 » Redis核心数据类型精讲:string/hash/list 命令详解与实战场景----《Hello Redis!》(2)
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!