springboot项目创建笔记21 之《redis应用场景》--不断更新

一、incr命令统计访问量
1)用于统计文章、用户的访问量和点击率
2)incr命令
redis incr命令将key中储存的数字值增一。
如果key不存在,那么key的值会先被初始化为0,然后再执行INCR操作。
如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。
本操作的值限制在64位(bit)有符号数字表示之内。
3)redis内部采用整数形式(Integer representation)来存储对应的整数值
4)缺点是用户每操作一次,就向redis服务器发送一个incr命令,如果并发量很大,会对服务器造成压力,耗费CPU
5)如何把统计的访问量同步到mysql数据库?

二、使用hash结构存储商品的库存、价格、关注数、评价数

三、使用hash结构实现短链接转换器
1)长链接转换为短链接:长链接转换为短链接加密串key,存储在redis的hash结构中
2)重定向到原始url:通过加密串key到redis里找到原始url,然后重定向出去

四、使用hash结构实现购物车场景
1)登录状态下添加商品到购物车
在高并发情况下,登录用户添加购物车,购物车服务先把数据存储在redis,然后发消息给rabbitmq写入数据库。这种高并发情况,就能保证所有的查询操作都能落在redis上,从而减少db的操作。
2)未登录状态下添加商品到购物车
未登录用户添加购物车,购物车服务为该用户生成唯一id:cartid,并把该cartid作为key,把购物车的数据保存进redis(有效期3个月)。
购物车服务把该cartid会写进用户的cookies。
这个环节不保存数据库,因为没有对应的用户。
以后用户操作购物车,都带上这个cartid就行。
3)登录后发起合并购物车请求
用户登录时,如何把已登录的购物车历史数据和未登录的购物车历史数据合并?
用户登录成功后,客户端把cookies里面的cartid和userid发给购物车系统,购物车系统通过cartid把redis未登录的数据合并插入到该userid的数据库里面。
重新刷新添加到登录userid的redis数据。
删除未登录cartid的redis数据。
4)采用hash数据结构
往购物车加入商品,key=cart:user:用户id
hset cart:user:1000 101 1
hset cart:user:1000 102 1
hgetall cart:user:1000
修改购物车数据,为某件商品添加数量
hincrby cart:user:1000 101 1
hincrby cart:user:1000 102 2
hgetall cart:user:1000
统计购物车有多少件商品
hlen cart:user:1000
删除购物车某件商品
hdel cart:user:1000 102
hgetall cart:user:1000

五、解决分布式系统session一致性问题
session是客户端与服务端通讯会话跟踪技术,服务器与客户端保持整个通讯会话基本信息。
客户端在第一次访问服务端的时候,服务端会响应一个sessionId并且将它存入到本地cookie中。
在之后的访问会将cookie中的sessionId放入到请求头中去访问服务器。
分布式session会有什么问题?
用户第一次访问nginx,请求落到服务器A,服务器A生成了一个sessionId,并保存在用户的cookie中。
用户第二次再来访问nginx,他这次把cookie里面的sessionId加入到http请求头中,这时请求落到了服务器B,服务器B发现没有找到sessionId,于是创建了一个新的sessionId并保存在用户cookie中。
解决办法:
分布式系统统一将sessionId保存在redis中

六、热门商品抢购查询
1、需求和特点:
1)数据量少
2)高并发,请求量大
2、技术方案:
像这种高并发的功能,绝对不可能用数据库
一般的做法是先把数据库中的数据抽取到redis里面。采用定时器,来定时缓存
还有要支持分页查询
redis list数据结构天然支持这种高并发的分页查询功能
具体技术方案采用list的lpush和lrange来实现
3、什么是缓存击穿?
在高并发系统中,大量的请求同时查询一个key时,如果这个key正好失效或删除,就会导致大量的查询都打到数据库上。
如当QPS=1000的时候,这时定时器更新redis,先删除再添加就会出现缓存击穿的问题。就必定导致大量的请求都打到数据库上面,从而把数据库打垮。
4、如何解决缓存击穿的问题?
针对这种定时更新的特定场景,解决方案:采用主从轮询的原理来实现
步骤1:定时更新原理
开辟2块缓存,A和B,定时器在更新缓存的时候,先更新B缓存,然后再更新A缓存,记得要按照这个顺序来。
步骤2:查询原理
用户先查询缓存A,如果缓存A查询不到(例如,更新缓存的时候删除了),再查询缓存B。
以上两个问题,由原来的一块缓存,开辟出2块缓存,最终解决了缓存击穿的问题。

七、高并发的微信抢红包
1、微信抢红包的并发场景分析
微信抢红包的高峰期一般是在年底公司开年会和春节2个时间段,高峰的并发量是在几千万以上
高峰的枪红包有3大特点:
1)包红包的人多:也就是创建红包的任务比较多,即红包系统是以单个红包的任务来区分,特点就是在高峰期红包任务多
2)抢红包的人更多:当你发红包出去后,是几十甚至几百人来抢你的红包,即单红包的请求并发量大
3)抢红包体验:当你发现红包时,要越快抢到越开心,所以要求抢红包的响应速度要快,一般1秒响应
2、微信抢红包的技术实现原理
2-1、包红包
1)先把金额拆解为小金额的红包,例如总金额100元,发20个,用户在点保存的时候,就自动拆解为20个随机小红包
2)这里的存储就是个难题,多个金额(例如20个小金额的红包)如何存储?采用set?list?hash?
2-2、抢红包
高并发的抢红包时核心的关键技术,就是控制各个小红包的原子性
例如:20个红包在500人的群里被抢,20个红包被抢走一个的同时要把红包的库存减1,即剩下19个
在整个过程中抢走一个和红包库存减1个是一个原子操作
那数据类型符合“抢走一个 和 红包库存减1个 是一个原子操作”采用set?list?hash?
2-3、list比较合适
list的pop操作弹出一个元素的同时会自动从队列里面剔除该元素,它是一个原子性操作

猜你喜欢

转载自blog.csdn.net/csj50/article/details/112185055