专栏名称: 石杉的架构笔记
专注原创、用心雕琢!十余年BAT一线大厂架构经验倾囊相授
目录
相关文章推荐
成都发布  ·  通知!考试时间定了 ·  昨天  
成都本地宝  ·  终于官宣!成都多场大型演唱会定档! ·  3 天前  
成都发布  ·  早安,成都!新闻来了 ·  2 天前  
成都本地宝  ·  即将上线!成都5000万消费券来了! ·  4 天前  
51好读  ›  专栏  ›  石杉的架构笔记

4次优化,我把 Redis 性能 “压榨” 到极致!

石杉的架构笔记  · 公众号  ·  · 2020-12-23 09:52

正文


我的新课 《C2C 电商系统微服务架构120天实战训练营》 在公众号 儒猿技术窝 上线了,感兴趣的同学,可以长按扫描下方二维码了解课程详情:

课程大纲请参见文末


本文来源:阿飞的博客


我们有个这样的需求:每天每一个抢购商品只能买一次,并且全场抢购商品总购买次数不允许超过5次。

那么,整个商品限购的流程大概如下图所示:

那么,在每次购买成功商品成功后,发送的MQ大概是这样的(假设当前这笔订单有两件抢购商品):

  1. [{

  2. "orderId": "2020020622000001",

  3. "orderTime": "1581001673012",

  4. "productId": "599055114591",

  5. "userId": "860000000000001",

  6. "merchantCode": "A045"

  7. }, {

  8. "orderId": "2020020622000001",

  9. "orderTime": "1581001673012",

  10. "productId": "599055114592",

  11. "userId": "860000000000001",

  12. "merchantCode": "A045"

  13. }]

这条消息表示860000000000001这个用户在1581001673012这个时间点(北京时间为2020/02/06 23:07:53)在A045这个商户分别购买了商品ID为599055114591和599055114592两样商品。

那么,当消费这条信息后,更新频控的几条关键Redis命令如下(上面的需求不是重点, 优化下面5条命令才是本文的重点 ):

  1. 命令1hset mall:sale:freq:ctrl:860000000000001 599055114591 1 hash结构,field表示购买的商品IDvalue表示购买次数)

  2. 命令2hset mall:sale:freq:ctrl:860000000000001 599055114592 2

  3. 命令3expire mall:sale:freq:ctrl:860000000000001 3127(设置过期时间)


  4. 命令4set mall:total:freq:ctrl:860000000000001 3

  5. 命令5expire mall:total:freq:ctrl:860000000000001 3127(设置过期时间)

我们首先了解一下执行一条Redis命令耗时由哪几部分组成:

发送命令网络传输时间,命令在Redis服务端队列中等待的时间,命令执行的时间(Redis中的slowlog只是检测这一步骤的时间),结果返回的Redis客户端的时间。

如下图所示:

上面的业务总计涉及5条Redis命令,每条命令都需要经过这些步骤,可想而知性能真的弱爆了(可能整个执行过程还不需要10ms,但还是弱爆了)。

  • 第1次优化

第一次优化非常简单,稍微有点经验就能看出来,利用hmset命令将两条hmset命令合二为一,优化后的Redis命令如下:

  1. hmset mall:sale:freq:ctrl:860000000000001 599055114591 1 599055114592 2

  2. expire mall:sale:freq:ctrl:860000000000001 3127


  3. set mall:total:freq:ctrl:860000000000001 3

  4. expire mall:total:freq:ctrl:860000000000001 3127


  • 第2次优化

第二次优化将set和expire命令合二为一,这个一般对Redis有点了解的也知道如何优化:

  1. hmset mall: sale:freq:ctrl:860000000000001 599055114591 1 599055114592 2

  2. expire mall:sale:freq:ctrl:860000000000001 3127


  3. setex mall:total:freq:ctrl:860000000000001 3127 3


  • 第3次优化

第3次优化需要借助pipeline,简直就是Redis优化的一大杀器。

不过,需要注意的是在 RedisCluster中使用pipeline时必须满足pipeline打包的所有命令key在RedisCluster的同一个slot上

如果打包命令的key不在同一个slot上,就会报错。所以我们需要分两批打包:

  1. -- 这两条命令的key都是一样的,肯定在同一个slot

  2. pipeline(

  3. hmset mall:sale:freq:ctrl:860000000000001 599055114591 1 599055114592 2

  4. expire mall:sale:freq:ctrl:860000000000001 3127

  5. )


  6. -- mall:total:freq:ctrl:860000000000001mall:







请到「今天看啥」查看全文