Redis常用的基础数据类型及使用场景

Redis 由浅入深 (1) - Redis常用的基础数据类型及使用场景

前言

随着系统的业务和用户量的不断的增长,传统的单体应用(请求直查 DB)已经无法支撑大量的用户访问。为了提高系统的吞吐量就必须使用一些中间件去提升性能,而Redis就是提升吞吐量的核武器。Redis可以做分布式锁、应用缓存、注册中心、消息队列(不推荐使用)、发布订阅、集合计算等等功能。


一、字符串类型

String类型是Redis最基本的数据结构类型,是二进制安全的,其他几种数据结构都是在字符串类型上构建的。

在项目中一般应用在简单的键值缓存、库存计数。很多开发者图简单方便也会把对象转换成JSON String存入Redis,取的时候也会反序列化一遍。这样虽然说没有什么问题,但性能会稍微差一点,如果有存对象的需要还是尽量使用hash类型。

key:     biz:user:10002
value:  {"name": "allens", "job": "programer", ....}
复制代码

命令:

set key value [ex sec] [px mills] [nx|xx]
复制代码

REDIS命令参考 (doc.redisfans.com/index.html),可以在这份文档中查到所有redis命令的说明及细节。 在这里插入图片描述

二、列表

列表(list)类型是用来存储多个有序的字符串,如图218所示,a、b、c、d、e五个元素从左到右组成了一个有序的列表,列表中的每个字符串称为元素(element),一个列表最多可以存储2321个元素。在Redis中,可以对列表两端插入(push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素。列表是一种比较灵活的数据结构,它可以充当栈和队列的角色,在实际开发上有很多应用场景。 在这里插入图片描述

使用场景

① redis的列表可以做简单的消息队列,将消息实体转成字符串。lpush到队列左侧,然后rpop从右侧弹出数据即可简单实现一个消息队列。但使用rpop这种方式是非阻塞的,如果没有消息插入也会返回。一般使用blpop或者是brpop命令进行阻塞等待获取到消息,然后再根据获取到的消息反序列化进行处理。这种方式在并发量并不高、可以容忍丢消息的情况下能够使用。一般情况下不建议使用redis做消息队列。

② 列表还可以缓存文章,比如有一个场景是首页要默认展示10篇文章,所有的用户没有点击分页或更多button之前都是默认展示这10篇文章的,就可以把这10篇文章放在缓存中直接进行展示。也可以储存更多分页的文章,cache key 可以设计为article:1(分页):id(文章id)。

命令:

rpush key value [value...]  # 从右侧插入元素
lpush key value [value...]  # 从左侧插入元素
lindex key                  # 获取指定索引下标
llen key                    # 获取列表长度
lpop key                    # 从列表左侧弹出元素
rpop key                    # 从列表右侧弹出元素
blpop key [key ...] timeout # 阻塞获取消息
brpop key [key ...] timeout # 阻塞获取消息
复制代码

在这里插入图片描述

三、哈希

几乎所有的编程语言都提供了哈希(hash)类型,它们的叫法可能是哈希、字典、关联数组。在Redis中,哈希类型是指键值本身又是一个键值对结构,形如value={{field1,value1},...{fieldN,valueN}}。 在这里插入图片描述 使用场景

Hash类型可以用来session缓存、缓存用户信息、级联分类等等,比如项目中使用Spring-data-session-redis的话,Spring将通过Spring-data-session-redis封装的一个Filter将SpringHttpSession(tomcat servlet session)存入到redis中。获取的话直接从redis中获取到用户的信息,而不是将session存入到本地。项目本地只会缓存一个sessionid其他所有的session attr 都会到redis中进行获取。后续会有文章专门讨论spring-data-session-redis的实现原理,以及注意事项。

hset key field value # hset user:1 name tom
hget key field # hget user:1 name
hlen key # 计算field个数
hkeys user:1 # 获取所有的key field
hvals key # 获取所有的value
hget all key # 获取的field & value
hmget 
hscan
hincrby key field
hstrlen key field # 计算value的字符串长度
复制代码

在这里插入图片描述

四、集合

集合(set)类型也是用来保存多个的字符串元素,但和列表类型不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标获取元素。如图222所示,集合user:1:follow包含着"it"、"music"、"his"、"sports"四个元素,一个集合最多可以存储2321个元素。Redis除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集,合理地使用好集合类型,能在实际开发中解决很多实际问题。 在这里插入图片描述 集合可以用用在用户的标签或者是某种产品的标签上,key:user:1:tag,比如很多用户都喜欢打篮球,就可以使用集合获取所有喜欢打篮球的人,或者是喜欢某一类产品的用户都可以通过集合来快速分析获取。

sadd key element [element ...]
exists key
srem key element [element ...]
spop key # 随机弹出元素
smembers key # 获取所有元素
smembers myset
复制代码

集合间操作:

# 集合1
sadd user:1:fllow it music his sports
# 集合2
sadd user:2:fllow it news ent sports

# 求交集
sinter key [key ...]
sinter user:1:fllow user:2:follow
# sports it

# 求并集
suinon key [key ...]
sunion user:1:follow user:2:follow
# 两个集合所有的不重复元素

# 差集
sdiff key [key...]
# music his
复制代码

在这里插入图片描述

五、有序集合

有序集合相对于哈希、列表、集合来说会有一点点陌生,但既然叫有序集合,那么它和集合必然有着联系,它保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序。但是它和列表使用索引下标作为排序依据不同的是,它给每个元素设置一个分数(score)作为排序的依据。如图224所示,该有序集合包含kris、mike、frank、tim、martin、tom,它们的分数分别是1、91、200、220、250、251,有序集合提供了获取指定分数和元素范围查询、计算成员排名等功能,合理的利用有序集合,能帮助我们在实际开发中解决很多问题。
复制代码

在这里插入图片描述 sortedSet 可以用在排行榜系统上,比如按视频播放量排序,按点赞次数排序等等。

zadd video:ranking:2016_03_15 222222(视频id) 3
zincrby video:ranking:2016_03_15 222222 1 # 增加点赞数
zrem video:ranking:2016_03_15 222222 # 从排行榜中删除
# 获取点赞最多的十条视频
zrevrangebyrank video:ranking:2016_03_15 222222 10
zscore video:ranking:2016_03_15 222222 # 获取视屏分数
zrank video:ranking:2016_03_15 222222 # 获取视屏排名
复制代码

命令参考:doc.redisfans.com/index.html 在这里插入图片描述

六、Bitmaps

现代计算机用二进制(位)作为信息的基础单位,1个字节等于8位,例如“big”字符串是由3个字节组成,但实际在计算机存储时将其用二进制表示,“big”分别对应的ASCII码分别是98、105、103,对应的二进制分别是01100010、01101001和01100111。 在这里插入图片描述 在这里插入图片描述

Bitmaps本身不是一种数据结构,实际上它就是字符串,但是他可以对字符串的位进行操作。可以把Bitmaps想象成一个以位为单位的数组,数组的每个单元只能存储0和1,数组的下标在Bitmaps中叫做偏移量。

下面是使用bitmaps分析网站某个用户访问过的应用场景: 在这里插入图片描述 设置键的第offset个位的值(从0算起),假设现在有20个用户,userid=0,5,11,15,19的用户对网站进行了访问。

setbit unique:users:2022-05-30 0 1
setbit unique:users:2022-05-30 5 1
...
复制代码

很多应用的用户id以一个指定数字(例如10000)开头,直接将用户id和Bitmaps的偏移量对应势必会造成一定的浪费,通常的做法是每次做setbit操作时将用户id减去这个指定数字。在第一次初始化Bitmaps时,假如偏移量非常大,那么整个初始化过程执行会比较慢,可能会造成Redis的阻塞。

命令操作

getbit unique:users:2022-05-30 1000000 #用户不存在所以返回0
bigcount [start][end] # start ~ end 表示从start字节到 end字节范围,查询出在第start个字节到第end个字节的独立访问用户数
bigcount unique:uesrs:2022-05-30 # 算出这天独立访问的用户数量
bitop op destkey key[key...] # 可以计算多个bitmaps的交集并集
复制代码

七、HyperLogLog

HyperLogLog并不是一种新的数据结构(实际类型为字符串类型),而是一种基数算法,通过HyperLogLog可以利用极小的内存空间完成独立总数的统计,数据集可以是IP、Email、ID等。HyperLogLog提供了3个命令:pfadd、pfcount、pfmerge。

在这里插入图片描述 HyperLogLog的算法链接(en.wikipedia.org/wiki/Philip…) HyperLogLog内存占用量非常小,但是存在错误率,开发者在进行数据结构选型时只需要确认如下两条即可

  • 只为了计算独立总数,不需要获取单挑数据。
  • 可以容忍一定误差率,毕竟HyperLogLog在内存的占用量上有很大优势

八、键管理

键重命名

rename key newkey
复制代码

随机返回一个键

randomkey
复制代码

键过期

expireat
pexpire
pexpireat
pttl
persist

expire key sec # 在sec秒后键过期
expire at key timestemp # 在timestemp时间点,键过期
ttl key # 获取过期还剩余的时间
复制代码

遍历键

keys pattern # patter可以是具体值和正则
scan cursor [match pattern [count number]
复制代码
  • cursor是必需参数,实际上cursor是一个游标,第一次遍历从0开始,每次scan遍历完都会返回当前游标的值,直到游标值为0,表示遍历结束。
  • matchpattern是可选参数,它的作用的是做模式的匹配,这点和keys的模式匹配很像。
  • countnumber是可选参数,它的作用是表明每次要遍历的键个数,默认值是10,此参数可以适当增大。

在这里插入图片描述

总结

万丈高楼平地起,掌握好redis基础的数据结构,要灵活应用各种数据类型来解决不同的应用场景。下一节将会讲redis的安装,以及几种部署结构。

学习更多干货类容(JAVA、前端、Kafka、redis等等)请关注我的公众号 互联网技术专栏

猜你喜欢

转载自juejin.im/post/7108596805033525256