深入解析Redis五种数据结构及其应用场景

发表时间: 2022-02-13 19:34

前言

Redis作为缓存数据库,目前在市场上占有很大的使用率,大部分人在工作中都使用到其string格式的存储,对于剩下的数据结构却很少使用到,Redis 基本数据结构包含:字符串(string)、 散列(hash)、 列表(list)、 集合(set)、 有序集合(sorted set)五种。这五种数据结构在我们工作中不同的场景中经常使用到,面试过程中经常被问到,因此熟练掌握这5种基本数据结构的使用和应用场景是Redis知识最基础也是最重要的部分

一、5种基本数据结构

二、字符串String

2.1、常用操作

SET  key  value 			//存入字符串键值对MSET  key  value [key value ...] 	//批量存储字符串键值对SETNX  key  value 		//存入一个不存在的字符串键值对GET  key 			//获取一个字符串键值MGET  key  [key ...]	 	//批量获取字符串键值DEL  key  [key ...] 		//删除一个键EXPIRE  key  seconds 		//设置一个键的过期时间(秒)INCR  key 			//将key中储存的数字值加1DECR  key 			//将key中储存的数字值减1INCRBY  key  increment 		//将key所储存的值加上incrementDECRBY  key  decrement 	//将key所储存的值减去decrement

2.2、应用场景

2.2.1、单值缓存(最常用)

2.2.2、对象缓存

将对象转为json存储 或者将对象的每个字段作为可以存储

SET  user:1  value(json格式数据)MSET  user:1:name  zhuge   user:1:balance  1888

2.2.3、分布式锁

SETNX  product:10001  true 		//返回1代表获取锁成功SETNX  product:10001  true 		//返回0代表获取锁失败。。。执行业务操作DEL  product:10001			//执行完业务释放锁SET product:10001 true  ex  10  nx //设置过期时间防止程序意外终止导致死锁


2.2.4、计数器

  • 文章的阅读量、点赞量

  • 分布式系统全局序列号,每个系统如果每次使用序号就从redis获取,影响性能,所以每个系统每次可以批量申请N个序号供当前系统使用,使用完毕后再继续获取,可以提升性能

三、哈希hash

3.1、常用操作

HSET  key  field  value 			//存储一个哈希表key的键值HSETNX  key  field  value 		//存储一个不存在的哈希表key的键值HMSET  key  field  value [field value ...] 	//在一个哈希表key中存储多个键值对HGET  key  field 				//获取哈希表key对应的field键值HMGET  key  field  [field ...] 		//批量获取哈希表key中多个field键值HDEL  key  field  [field ...] 		//删除哈希表key中的field键值HLEN  key				//返回哈希表key中field的数量HGETALL  key				//返回哈希表key中所有的键值HINCRBY  key  field  increment 		//为哈希表key中field键的值加上增量increment


3.2、应用场景

3.2.1、对象缓存

3.2.2、 电商购物车

以用户id为key, 商品id为field,商品数量为value,添加购物车操作

HSET cart:1  10001 2   //用户1:商品10001  数量2HSET cart:1  10002 1   //用户1:商品10002  数量1HINCRBY cart:1 10001 1 //用户1:商品10001 数量+1HINCRBY cart:1 10001 -2 //用户1:商品10001 数量-2HLEN cart:1  //获取用户1购物车商品数量HGETALL cart:1  //获取用户1购物车商品以及数量hdel cart:1 10001  //删除用户1的10001商品


优点

  • 同类数据归类整合储存,方便数据管理
  • 相比string操作消耗内存与cpu更小
  • 相比string储存更节省空间

缺点

  • 过期功能不能使用在field上,只能用在key上
  • Redis集群架构下不适合大规模使用(key相同的经过hash后只会落在其中一台机器上)

四、列表list

4.1、常用操作

LPUSH  key  value [value ...] 		//将一个或多个值value插入到key列表的表头(最左边)RPUSH  key  value [value ...]	 	//将一个或多个值value插入到key列表的表尾(最右边)LPOP  key			//移除并返回key列表的头元素RPOP  key			//移除并返回key列表的尾元素LRANGE  key  start  stop		//返回列表key中指定区间内的元素,区间以偏移量startstop指定LINSERT key  BEFORE|AFTER pivot element  // 在元素element前后插入pivotLREM key count element  //根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素 count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT //count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。//count = 0 : 移除表中所有与 VALUE 相等的值。BLPOP  key  [key ...]  timeout	//从key列表表头弹出一个元素,若列表中没有元素,阻塞等待 timeout秒,如果timeout=0,一直阻塞等待BRPOP  key  [key ...]  timeout 	//从key列表表尾弹出一个元素,若列表中没有元素,阻塞等待 timeout秒,如果timeout=0,一直阻塞等待

4.2、应用场景

Stack(栈FILO) = LPUSH + LPOP  Queue(队列FIFO)= LPUSH + RPOPBlocking MQ(阻塞队列)= LPUSH + BRPOP

4.2.1 微博和微信公号消息

如上图公众号:我订阅了阿里云云栖号(id10001)、新华网(id10002)、infoQ(id10003)等

1、首先在msg:1列表中增加10001、10002、10003 ,以及各个用户对应的消息

LPUSH sub:1 10001 10002 10003LPUSH msg:10001 1 2 3LPUSH msg:10002 4 5 6LPUSH msg:10003 8 9


2、此时10002发送一条消息 id : 11 ,首先在我订阅的集合中移除10002,然后在最前面加入10002,然后在msg中加入11

LREM sub:1 0 10002LPUSH sub:1 10002 LPUSH msg:10002 11

五、 集合set

5.1 常用操作

SADD  key  member  [member ...]			//往集合key中存入元素,元素存在则忽略,若key不存在则新建			SREM  key  member  [member ...]			//从集合key中删除元素SMEMBERS  key					//获取集合key中所有元素SCARD  key					//获取集合key的元素个数SISMEMBER  key  member			//判断member元素是否存在于集合key中SRANDMEMBER  key  [count]			//从集合key中选出count个元素,元素不从key中删除SPOP  key  [count]				//从集合key中选出count个元素,元素从key中删除SINTER  key  [key ...] 				//交集运算SINTERSTORE  destination  key  [key ..]		//将交集结果存入新集合destination中SUNION  key  [key ..] 				//并集运算SUNIONSTORE  destination  key  [key ...]		//将并集结果存入新集合destination中SDIFF  key  [key ...] 				//差集运算SDIFFSTORE  destination  key  [key ...]		//将差集结果存入新集合destination中

5.2 应用场景

5.2.1 抽奖

1. 参与抽奖

SADD luck:1001 100001 //将用户100001 加入商品1001 的参与池子中

2. 查看参与抽奖所有用户

SMEMBERS luck:1001

3. 抽取1名中奖者

SPOP luck:1001 1

5.2.2 微博点赞,收藏,标签

- 点赞

SADD like:1 1001

- 取消点赞

SREM like:1 1001

- 检查用户是否点过赞

SISMEMBER  like:1 1001

5.2.3 微博微信关注模型

  • 刘昊然关注:张杰、刘涛、王宝强
SADD follow:lhr zj lt wbq
  • 张杰关注:刘昊然、刘涛、王宝强、王泷正、谢娜、胡歌
SADD follow:zj  lhr lt wbq wlz xl hg
  • 刘涛关注:刘昊然、张杰、陈奕迅、许嵩
SADD follow:lt  lhr zj cyx xs


模型1:【共同关注 】 刘昊然和张杰关注的人

SINTER  follow:lhr  follow:zj

模型2:【我关注的人中也有关注某人】刘昊然关注的人也在关注胡歌

SISMEMBER follow:zj hgSISMEMBER follow:lt hgSISMEMBER follow:wbq hg

模型3:【可能感兴趣的人】刘昊然访问张杰主页,会推荐感兴趣的人,张杰关注的人去且不在刘昊然关注中可以推荐

SDIFF follow:zj  follow:lhr


5.2.4 购物网站商品筛选

SADD  brand:huawei  P30  //华为品牌集合中  p30SADD  brand:xiaomi  mi-6X //小米品牌集合中  mi-6X SADD  brand:iPhone iphone8 //苹果品牌集合中  iphone8  SADD os:android  P30  mi-6X  //安卓系统集合中  P30  mi-6XSADD cpu:brand:intel  P30  mi-6X //cpu 英特尔集合中  P30  mi-6XSADD ram:8G  P30  mi-6X  iphone8 //8G内存集合中 P30  mi-6X  iphone8

查找内存为8G,英特尔CPU和安卓系统的手机:

SINTER  os:android  cpu:brand:intel  ram:8G


六、有序集合sorted set

6.1 常用操作

ZADD key score member [[score member]…]	//往有序集合key中加入带分值元素ZREM key member [member …]		//从有序集合key中删除元素ZSCORE key member 			//返回有序集合key中元素member的分值ZINCRBY key increment member		//为有序集合key中元素member的分值加上increment ZCARD key				//返回有序集合key中元素个数ZRANGE key start stop [WITHSCORES]	//正序获取有序集合key从start下标到stop下标的元素ZREVRANGE key start stop [WITHSCORES]	//倒序获取有序集合key从start下标到stop下标的元素ZUNIONSTORE destkey numkeys key [key ...] 	//并集计算ZINTERSTORE destkey numkeys key [key …]	//交集计算

6.2 应用场景

6.2.1 微博热搜榜

  • 以每天热搜新闻为一个集合,当天当一个用户点击一个话题后,分值+1
ZINCRBY hotnews:20220201 1 dawmll //2022-02-01 点击冬奥我们来了+1ZINCRBY hotnews:20220201 1 gtljp //2022-02-01 点击高亭宇金牌+1
  • 展示当日排行前十
ZREVRANGE hotnews:20220201 0 10 WITHSCORES 


  • 2日搜索榜单计算
ZUNIONSTORE newhots 2 hotnews:20220201 hotnews:20220202 //将2个几个中的相同的值的分数相加,将结果放到newhots 中

  • 展示2日排行前十
ZREVRANGE newhots 0 10 //从上面统计的新的集合中取出前10


总结

通过本文,大家对Redis五种数据结构有了更多的了解,包括在实际场景中的使用,希望能帮助大家解决实际工作中的问题,后续也会更新Redis架构相关的文章。

如有帮助,感谢关注