本次博客主要介绍 Redis 的 value 最常见的五种数据结构,它们分别是:String、Hash、List、Set、Sorted Set
redis里面的String是以字节存储的,如果你的客户端是utf-8编码,那么上传上去的字符串就是按utf-8进行编码
redis的String里面除了存储数据以外,还存储了类型和长度。类型包括:字符串、数值以及bitmap
有最基本的6种操作,它们分别是:set、get、append、setrange、getrange、strlen
# 设置字符串,以下命令执行完毕之后,hello=world set hello world # 获取字符串,获取hello变量的值 get hello # 追加字符串,以下命令执行完毕之后,hello=worldtest append hello test # 字符串修改某个位置开始的字符串,以下命令执行完毕之后,hello=tttldtest setrange hello 0 ttt # 字符串获取某个位置范围的字符串,以下命令执行完毕之后,输出 ttld getrange hello 1 4 # 获取字符串长度,以下命令执行完毕,输出9 strlen hello
redis可以将存储的字符串解析为一个数字,然后当做数值来进行处理,它只有一个操作incr
# 设置字符串 set test 9 # 使其加1,执行之后test变为10 incr test
数值类型,在抢购、秒杀、详情页、点赞、评论情况下使用,可以解决并发问题,对数据库的事务操作,完全有 redis 内存操作代替
字符串是有一个个字节组成的,所以可以进行位操作,这里一共有四个操作可供选择:setbit、bitcount、bitpos、bitop,下面演示一下这些操作
# 设置字符串 set test a0 # 设置位,a0原来是 0110 0001 0011 0000,将第7位变成0,变成 0110 0000 0011 0000,于是变成了`0 setbit test 7 0 # 获取1的个数,因为test = 0110 0000 0011 0000 返回结果是4,表示有4个1 bitcount test # 查找字符串中第一个设置为1或0的bit位。返回1 bitpos test 1 0 -1 # 将两个二进制串进行与或非操作 # test1 0110 0001 # test2 0110 0010 # test1 & test2 0110 0000 set test1 a set test2 b bitop and dest test1 test2
bitmap 有什么用呢?
用处:统计用户登录天数,且窗口随机
# 我在第1天登录了 setbit hellozjf 1 1 # 我在第7天登录了 setbit hellozjf 7 1 # 我在第364天登录了 setbit hellozjf 364 1 # 查询我整年登录了多少天,返回值是3,说明我今年登录了3天 bitcount hellozjf # 查询我最近一周登录了多少天 bitcount hellozjf -7 -1,返回值是1,说明我最近一周登录了1天
redis 里面的 List 是一个双向队列,可以从头部插入数据、弹出数据,也可以从尾部插入、弹出数据
它拥有的操作为lpush
、lpop
、rpush
、rpop
、lrange
(查询列表中的元素)、lindex
(查询列表中的元素)、lset
(更新某个索引的值)、lrem
(删除元素)
# 插入队列,k1变成 f e d c b a lpush k1 a b c d e f # 查询列表 lrange k1 0 -1 # 查询第2个元素,查出 d lindex k1 2 # 查询最后一个元素,查出 a lindex k1 -1 # 设置第三个元素 lset k1 3 xxxxx
value里面可以存储一个map,但是它只有一层。hash和sort set是两个非常常用的类型,需要重点掌握
通过在redis-cli
上面运行命令,运行help @hash,可以看到它拥有的操作为hdel
、hexists
、hget
、hgetall
、hincrby
、hincrbyfloat
、hkeys
、hlen
、hmget
、hmset
、hsetnx
、hstrlen
# 设置 k1.a=1 hset k1 a 1 # 获取 k1.a hget k1 a # 给 k1.a 增加1,之后k1.a变成2 hincrby k1 a 1 # 给 k1.a 增加0.5,之后k1.a变成2.5 hincrbyfloat k1 a 0.5 # 如果没有k1.b,则设置10,否则不设置 hsetnx k1 b 10 # 获取所有的k1下面所有的key和value hgetall k1 # 判断某个键是否存在 hexists k1 a ……
其实也挺简单的,说白了就是 key-value 里面的 value 变成了 key-value
set其实和list差不多,只不过set里面没有重复的元素,但是它有个缺点就是元素是无序的
在redis-cli上面,运行help @set,可以看到所有的set相关的操作。例如sadd
(将元素加入到set里面)、SREM
(将元素从set中移除)、smembers
(获取所有的元素)、sdiff/sdiffstore
(两个set做相减操作/相减结果记录到另一个变量)、sinter/sinterstore
(求两个set的交集/相交结果记录到另一个变量)、sunion/sunionstore
(两个set做并集/并集结果记录到另一个变量)、srandmember
(从元素中获取随机的几个元素)、spop
(从元素中获取随机的几个元素,然后从set中删除它们)
sadd k1 a b c sadd k2 b c d # 获取 k1 - k2,结果存储到 k3,k3变成a sdiffstore k3 k1 k2 # 获取 k1 与 k2 的交集,结果存储到 k4,k4变成b,c sinterstore k4 k1 k2 # 获取 k1 与 k2 的并集,结果存储到 k5,k5变成a,b,c,d sunionstore k5 k1 k2 # 买彩票,你把几个数字放进去,然后随机调出几个数字。比方说下面就是从10个数字里面随机调出3个数字 sadd k6 1 2 3 4 5 6 7 8 9 0 srandmember k6 3 # 年会抽奖,你把人的名字放进去,这个人中奖之后需要移除他的名字。 sadd k7 1 2 3 4 5 6 7 8 9 0 ## 抽出4个四等奖 spop k7 4 ## 抽出3个三等奖 spop k7 3 ## 抽出2个二等奖 spop k7 2 ## 抽出1个一等奖 spop k7 1 ## 再抽返回null
再set的基础上面,增加了排序的功能。默认情况下,它在内存中是按照权重左小右大的方式进行存储的,通过ZRANGE
和ZREVRANGE
正序获取倒序获取结果,它也有差集、并集、交集的功能,但是个人感觉没啥意义,sorted_set在底层是通过跳表实现的
在redis-cli中,通过help @sorted_set
获取所有排序set的操作方法
# 往 sorted_set 中添加元素,其中张三权重1,李四权重2 zadd k1 1 张三 2 李四 # 查看 sorted_set 中的所有记录,这里如果中文编码不正确的话,使用 redis-cli --raw,这样redis就会将utf8字符串翻译成中文 zrange k1 0 -1 withscores # 反向查看 sorted_set 中的所有记录 zrevrange k1 0 -1 withscores