我的新课
《C2C 电商系统微服务架构120天实战训练营》
在公众号
儒猿技术窝
上线了,感兴趣的同学,可以长按扫描下方二维码了解课程详情:
课程大纲请参见文末
本文来源:阿飞的博客
我们有个这样的需求:每天每一个抢购商品只能买一次,并且全场抢购商品总购买次数不允许超过5次。
那么,整个商品限购的流程大概如下图所示:
那么,在每次购买成功商品成功后,发送的MQ大概是这样的(假设当前这笔订单有两件抢购商品):
[{
"orderId": "2020020622000001",
"orderTime": "1581001673012",
"productId": "599055114591",
"userId": "860000000000001",
"merchantCode":
"A045"
}, {
"orderId": "2020020622000001",
"orderTime": "1581001673012",
"productId": "599055114592",
"userId": "860000000000001",
"merchantCode": "A045"
}]
这条消息表示860000000000001这个用户在1581001673012这个时间点(北京时间为2020/02/06 23:07:53)在A045这个商户分别购买了商品ID为599055114591和599055114592两样商品。
那么,当消费这条信息后,更新频控的几条关键Redis命令如下(上面的需求不是重点,
优化下面5条命令才是本文的重点
):
命令1:hset mall:sale:freq:ctrl:860000000000001 599055114591 1(
hash结构,field表示购买的商品ID,value表示购买次数)
命令2:hset mall:sale:freq:ctrl:860000000000001 599055114592 2
命令3:expire mall:sale:freq:ctrl:860000000000001 3127(设置过期时间)
命令4:set mall:total:freq:ctrl:860000000000001 3
命令5:expire mall:total:freq:ctrl:860000000000001 3127(设置过期时间)
我们首先了解一下执行一条Redis命令耗时由哪几部分组成:
发送命令网络传输时间,命令在Redis服务端队列中等待的时间,命令执行的时间(Redis中的slowlog只是检测这一步骤的时间),结果返回的Redis客户端的时间。
如下图所示:
上面的业务总计涉及5条Redis命令,每条命令都需要经过这些步骤,可想而知性能真的弱爆了(可能整个执行过程还不需要10ms,但还是弱爆了)。
第一次优化非常简单,稍微有点经验就能看出来,利用hmset命令将两条hmset命令合二为一,优化后的Redis命令如下:
hmset mall:sale:freq:ctrl:860000000000001 599055114591 1 599055114592 2
expire mall:sale:freq:ctrl:860000000000001 3127
set mall:total:freq:ctrl:860000000000001 3
expire mall:total:freq:ctrl:860000000000001 3127
第二次优化将set和expire命令合二为一,这个一般对Redis有点了解的也知道如何优化:
hmset mall:
sale:freq:ctrl:860000000000001 599055114591 1 599055114592 2
expire mall:sale:freq:ctrl:860000000000001 3127
setex mall:total:freq:ctrl:860000000000001 3127 3
第3次优化需要借助pipeline,简直就是Redis优化的一大杀器。
不过,需要注意的是在
RedisCluster中使用pipeline时必须满足pipeline打包的所有命令key在RedisCluster的同一个slot上
。
如果打包命令的key不在同一个slot上,就会报错。所以我们需要分两批打包:
-- 这两条命令的key都是一样的,肯定在同一个slot上
pipeline(
hmset mall:sale:freq:ctrl:860000000000001 599055114591 1 599055114592 2
expire mall:sale:freq:ctrl:860000000000001 3127
)
-- mall:total:freq:ctrl:860000000000001和mall: