文章目录
- 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存每个班里有哪些学生
网硕互联帮助中心





评论前必须登录!
注册