Redis应用场景实战
文章目录
Redis应用场景实战一、Redis的单线程和高性能二、应用场景分析三、案例分析五种数据结构String应用场景计数器 Hash应用场景对象存储电商购物车 List应用场景常用数据结构微博消息和微信公众号消息 Set应用场景常用操作微信小程序抽奖微信微博点赞、收藏、标签集合操作实现微博微信关注模型 zset应用场景常用操作微博热搜排行榜一、Redis的单线程和高性能
Redis是单线程吗?
不是多线程的。
Redis 的单线程主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的(即执行命令(SET key value )是由一个线程完成的),这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。
Redis 单线程为什么还能这么快?
最关键的原因是redis基于纯内存操作。 如果做强一致性持久化性能会大量下降。
因为它所有的数据都在内存中,所有的运算都是内存级别的运算,而且单线程避免了多线程的切换性能损耗问题。正因为 Redis 是单线程,所以要小心使用 Redis 指令,对于那些耗时的指令(比如keys),一定要谨慎使用,一不小心就可能会导致 Redis 卡顿。
Redis 单线程如何处理那么多的并发客户端连接?
Redis的IO多路复用:redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。
Redis底层采用全局哈希表,时间复杂度为常数,性能极高
二、应用场景分析
计数器可以对 String 进行自增自减运算,从而实现计数器功能。Redis 这种内存型数据库的读写性能非常高,很适合存储频繁读写的计数量。
分布式ID生成
利用自增特性,一次请求一个大一点的步长如 incr 2000 ,缓存在本地使用,用完再请求。
海量数据统计
位图(bitmap):存储是否参过某次活动,是否已读谋篇文章,用户是否为会员, 日活统计。
会话缓存
可以使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。
分布式队列/阻塞队列
List 是一个双向链表,可以通过 lpush/rpush 和 rpop/lpop 写入和读取消息。可以通过使用brpop/blpop 来实现阻塞队列。
分布式锁实现
在分布式场景下,无法使用基于进程的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁。
热点数据存储
最新评论,最新文章列表,使用list 存储,ltrim取出热点数据,删除老数据。
社交类需求
Set 可以实现交集,从而实现共同好友等功能,Set通过求差集,可以进行好友推荐,文章推荐。
排行榜
sorted_set可以实现有序性操作,从而实现排行榜等功能。
延迟队列
使用sorted_set,使用 【当前时间戳 + 需要延迟的时长】做score, 消息内容作为元素,调用zadd来生产消息,消费者使用zrangbyscore获取当前时间之前的数据做轮询处理。消费完再删除任务 rem key
三、案例分析
五种数据结构
String应用场景
计数器
127.0.0.1:6379> incr article:readcount:1001(integer) 1127.0.0.1:6379> incr article:readcount:1001(integer) 2127.0.0.1:6379> incr article:readcount:1001(integer) 3127.0.0.1:6379> incr article:readcount:1001(integer) 4127.0.0.1:6379> incr article:readcount:1001(integer) 5127.0.0.1:6379> incr article:readcount:1001(integer) 6127.0.0.1:6379> incr article:readcount:1001(integer) 7127.0.0.1:6379> incr article:readcount:1001(integer) 8127.0.0.1:6379> incrby article:readcount:1001 100(integer) 108
Hash应用场景
对象存储
127.0.0.1:6379> hmset user 1001:name frozenpenguin 1001:balance 1888OK127.0.0.1:6379> hmget user 1001:name 1001:balance1) "frozenpenguin"2) "1888"127.0.0.1:6379> hget user 1001:name"frozenpenguin"127.0.0.1:6379>
Hash相对于String进行对象存储,更加灵活,可以任意操作对象里面的字段,而String则需要重新设置。
电商购物车
127.0.0.1:6379> hset cart:1001 10088 1 //用户1001添加商品10088一件(integer) 1127.0.0.1:6379> hincrby cart:1001 10088 1 //再加一件(integer) 2127.0.0.1:6379> 127.0.0.1:6379> hlen cart:1001 (integer) 1127.0.0.1:6379> hset cart:1001 10089 5 //用户1001添加商品10089五件(integer) 1127.0.0.1:6379> hgetall cart:10011) "10088"2) "2"3) "10089"4) "5"127.0.0.1:6379> hdel cart:1001 10088 //移除用户1001收藏的10088商品(integer) 1
List应用场景
常用数据结构
微博消息和微信公众号消息
127.0.0.1:6379> lpush msg:1001 10018(integer) 1127.0.0.1:6379> lpush msg:1001 10086(integer) 2127.0.0.1:6379> lrange msg:1001 0 2 //获取最新两条消息1) "10086"2) "10018"
Set应用场景
常用操作
微信小程序抽奖
127.0.0.1:6379> sadd act:1001 1001 //为活动添加用户1001(integer) 1127.0.0.1:6379> sadd act:1001 1002 //为活动添加用户1002(integer) 1127.0.0.1:6379> sadd act:1001 1008(integer) 1127.0.0.1:6379> sadd act:1001 1006(integer) 1127.0.0.1:6379> smembers act:1001 //查看参加当前活动的用户1) "1001"2) "1002"3) "1006"4) "1008"127.0.0.1:6379> srandmember act:1001 2 //随机抽取2名用户(原数据不变)1) "1001"2) "1002"127.0.0.1:6379> srandmember act:1001 21) "1006"2) "1002"127.0.0.1:6379> spop act:1001 2 //随机弹出2名用户,原数据改变1) "1006"2) "1001"127.0.0.1:6379> spop act:1001 21) "1002"2) "1008"127.0.0.1:6379> smembers act:1001(empty array)127.0.0.1:6379>
微信微博点赞、收藏、标签
127.0.0.1:6379> sadd like:1002 1001 //用户1001点赞10002(integer) 1127.0.0.1:6379> srem like:1002 1001 //移除(integer) 1127.0.0.1:6379> sismember like:1002 1001(integer) 0127.0.0.1:6379> sadd like:1002 1003(integer) 1127.0.0.1:6379> sadd like:1002 1006(integer) 1127.0.0.1:6379> sadd like:1002 1008(integer) 1127.0.0.1:6379> smembers like:1002 //查看点赞用户1) "1003"2) "1006"3) "1008"127.0.0.1:6379> scard like:1002 //查看点赞用户数(integer) 3
集合操作实现微博微信关注模型
127.0.0.1:6379> sadd zhugeSet zhuangzhou xushu # zhuge关注了zhuangzhou xushu(integer) 2127.0.0.1:6379> smembers zhugeSet1) "zhuangzhou"2) "xushu"127.0.0.1:6379> sadd loulanSet zhuge baiqi zhuangzhou xushu # loulan关注了zhuge baiqi zhuangzhou xushu(integer) 4127.0.0.1:6379> sadd zhuangzhouSet zhuge loulan baiqi xushu xunyu(integer) 5127.0.0.1:6379> sinter zhugeSet loulanSet # zhuge和loulan的共同关注1) "zhuangzhou"2) "xushu"127.0.0.1:6379> sismember zhuangzhouSet loulan(integer) 1127.0.0.1:6379> sismember zhuangzhouSet loulan(integer) 1127.0.0.1:6379> sismember xushuSet loulan(integer) 0127.0.0.1:6379> sdiff loulanSet zhugeSet # 可能认识的人(他关注的人我没有关注)1) "zhuge"2) "baiqi"
zset应用场景
常用操作
微博热搜排行榜
微博热搜排序,key就可以是小时榜/天榜/月榜,member是某一条热搜词条,incrementScore就是这个词条热度增量/权重增量
127.0.0.1:6379> zincrby hotNews:0709 1 china"1"127.0.0.1:6379> zincrby hotNews:0709 1 china"2"127.0.0.1:6379> zincrby hotNews:0709 1 us"1"127.0.0.1:6379> zincrby hotNews:0709 1 germany"1"127.0.0.1:6379> zrevrange hotNews:0709 0 9 #获取前十(自动排序)1) "china"2) "us"3) "germany"