背景
Redis作为非关系型内存数据库,已经成为各大厂的标配.在我们的日常开发中,除了String类型外,redis还提供了其他几种数据结构,比如hash(哈希)
、list(列表)、set(集合)、zset(有序集合),新版本还支持基于地理位置的Geo存储,本文将依次介绍一下这几种数据类型在实际场景中的落地.
1. 五种数据结构存储模型
2. String类型应用场景
2.1 String类型说明
字符串类型是Redis存储的基本数据类型也是我们平常应用最为广泛的数据类型,String类型在Redis存储中是二进制的也是安全的,所以它可以接受任何格式的数据,即使是图像数据。但是在Redis中字符串类型的值最大容纳数据大小512M,有时候我们会往redis存储一个json对象,这个当然是可以的,但是一当这个对象很大的时候,要考虑将其换成其他的数据类型,因为大对象和反序例化性能开销很大.
2.2 微信公众号中文章阅读量、抖音中的城市访问量
Redis提供了基于原子的加减操作,
这里面我们可以用计数器功能,
运用INCR对feild进行加加操作统计数据,
INCR article:readcount:{articleId}.
3. Hash类型应用场景
3.1 Hash类型说明
Hash不太适合在redis集群当中使用,这个我前面文章中讲过了,这里就不在详细谈了.
3.2 电商购物车
//思路:
//1)以用户id为key;
//2)商品id为field;
//3)商品数量为value
//hash表里面set数据商品数据
hset cart:1001 10099 1
//原子减商品库存
hincrby cart:1001 10099 1
//查询用户购买的指定的商品库存
hget cart:1001 10099
//hlen获取用户购买的商品总数
hlen cart:1001
//hlen删除用户购买的商品
hdel cart:1001 10099
//返回哈希表 key 中域的数量。
hlen cart:1001
//返回哈希表 key 中,所有的域和值。
hgetall cart:1001
4. List类型应用场景
4.1 List类型说明
这里的List不是你认识的数组,而是LinkedList这种结构,这里我将说几个我们不是经常使用的骚操作,我们可以运用LPUSH和LPOP实现Stack的功能;运用LPUSH和RPOP可以实现简单的队列;运用LPUSH和BRPOP可以实现Blocking MQ的功能.
Stack(栈) =LPUSH+LPOP FILO(先进后出)
Queue(队列)=LPUSH+RPOP FIFO(先进先出)
Blocking MQ(阻塞队列)=LPUSH+BRPOP.
什么是BRPOP:
从key列表表尾弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0,一直阻塞等待.所以可以用它来实现消息队列的监听.
4.2 微博和微信公众号消息流
LPUSH msg:{id} 10086
4.3 查看最新的微博消息
//LRANGE:返回列表key中指定区间内的元素,区间以偏移量start和stop指定
LRANGE msg:{id} 0 5
4.3 微信、微博在线用户抽奖
楼主年初的时候给公司做了抽宝马和万元大奖的一个抽奖活动,当时由于时间紧急只有两天时间,从前端到后端都要撸一遍,现在回想起来当时的设计方案其实可以做的更简洁.其中我记得有一个点就是,前面抽中的用户,隔日参加抽奖的时候,我们不希望他继续参与中奖,也是为了防止奖项一直被同一个用户抽中,减少这种所谓的“黑幕”,回归到redis里面我们就可以用SPOP去操作.
//思路
1)点击参与抽奖加入集合
SADD key {userID}
2)查看参与抽奖所有用户
SMEMBERS key
3)抽count名中奖者
如果希望中奖用户依然保留在抽奖池里面
SRANDMENMBER key [count]
SRANDMENMBER 从集合key中选出count个元素,元素不从key中删除
如果不希望中奖用户依然保留在抽奖池里面
SPOP key [count]
SPOP从集合key中选出count个元素,元素从key中删除
4.4 微信、微博、抖音点赞、收藏标签
//思路
1)抖音大V视频点赞量
SADD like:{messageId} {userId}
2)取消点赞
SREM like:{messageId} {userId}
移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略
3)检查用户是否点过赞
SISMEMBER like:{messageId} {userId}
4)获取点赞的用户列表
SISMEMBER like:{messageId}
5)获取点赞用户数
返回集合 key 的基数(集合中元素的数量)
SCARD like:{messageId}
4.5 微博、QQ共同关注的人,我关注的人也关注他,可能认识的人
//思路
共同关注的人:
//两个集合的交集
SINTER simaSet yanguoSet
我关注的人也关注他
//我关注的人在他的集合里面,可以运用SISMENBER
SISMENBER simaSet yanguo
我可能认识的人
//他关注的人,不在我的集合里面,但是在我的朋友集合里面
SDIFF simaSet yanguoSet
5. Zset类型应用场景
5.1 Zset类型说明
Zset是有序集合
5.2 微博热搜、排行榜
//思路
1)热搜
//新闻点击量
ZINCRBY HOTNEWS:20191115 1 李小璐离婚
为有序集合key中元素member的分值加上increment
2)展示当日排行版前十
ZREVRANGE hotNews:20191115 0 10 WITHSCORES
ZREVRANGE倒序获取有序集合key中start下标到stop下标的元素
3)七日搜索榜单计算
ZUNIONSTORE hotNews:20190722 7
并集计算
4)展示七日排行前十
ZREVRANGE hotNews:20190716-20190722 0 10 WITHSCORES
交集计算
6. Geo类型应用场景
5.1 Geo类型说明
基于地理位置的数据,这个主要运用在出行领域比较多
5.2 微信附近的人
//思路
微博、微信、默默<附近的人>
滴滴打车、哈啰单车、美团单车<附近的车>
美团和饿了吗<附近的餐馆>
基于地理位置
比如GEORADIUS
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEORADIUS Sicily 15 37 200 km WITHDIST
1) 1) "Palermo"
2) "190.4424"
2) 1) "Catania"
2) "56.4413"
redis> GEORADIUS Sicily 15 37 200 km WITHCOORD
1) 1) "Palermo"
2) 1) "13.361389338970184"
2) "38.115556395496299"
2) 1) "Catania"
2) 1) "15.087267458438873"
2) "37.50266842333162"
redis> GEORADIUS Sicily 15 37 200 km WITHDIST WITHCOORD
1) 1) "Palermo"
2) "190.4424"
3) 1) "13.361389338970184"
2) "38.115556395496299"
2) 1) "Catania"
2) "56.4413"
3) 1) "15.087267458438873"
2) "37.50266842333162"