Giter Club home page Giter Club logo

redis-lua's Introduction

redis+lua优惠券秒杀demo

说明

本质是把库存放到redis里做扣减,解决数据库更新库存的行锁瓶颈。

库存流水需要异步插入到数据库中,作为最终的业务凭证。

原理

  • 前端:采用PHP-FPM实现,但是建议生产环境使用GO/JAVA等支持redis长连接的开发语言/框架。
  • 后端:利用Redis维护优惠券库存,利用Redis Lua保障库存扣减幂等性,同时投递库存流水日志到Redis队列。
  • 任务:消费Redis中的库存流水日志,批量插入到数据库中,落地为业务凭证。(我没实现)

概念

  • 优惠券:用户看到的优惠券实体,内部包含多个批次。
  • 批次:一个优惠券由多个批次组成,一个批次内有多个券码coupon。

业务流程

1)创建优惠券
2)创建批次,上传对应的若干券码(或者随机生成)
3)将批次生效到线上,用户可以秒杀

业务取舍

业务规则 - 先验与回滚

兑换优惠券可能需要消耗用户积分,前端必须实时做一次积分查询,积分充足则立即执行Redis扣减。

在任务处理时,对用户积分做真实扣减,若此时积分不足则可以将券码归还到redis中,并站内信通知用户。

因为最终业务凭证是以数据库为准的,而任务本身是一个准实时异步过程,所以业务前端应该给予用户合理的提示,例如"稍后到卡包中查看优惠券"。

业务规则 - 前置与有损

如果业务有类似限制IP领取几次等比较复杂的规则,优先考虑在redis lua之前做前置判定。

因为lua脚本中逻辑越多,redis的TPS越低,所以尽量保证lua只做库存核心扣减。

前置规则校验的缺点,就是可能因为前置规则更新了某些计数,而后续的redis lua扣减异常,导致用户再也无法抢该券码。

但是出于折衷,暂时没有更好的办法,可以根据业务需要做让步和取舍。

性能

云主机Redis:云存在超卖问题,性能也不是很稳定,库存扣减性能在2w-4w/s。
物理机Redis:  库存扣减<=9w/s,随lua逻辑的复杂度而稍微降低,但整体远优于云Redis。

压测均采用redis长连接,采用PHP-FPM无法达到预期,需要换一个语言来实现库存前端服务。

任务入库仅做流水的select/insert操作,可以基于批量插入优化实现高吞吐。

如果业务量需要单个商品/优惠券>=9w/s的秒杀量,可以考虑限流,否则绰绰有余。

限流

因为单个优惠券的库存是单台redis执行lua来承载的,而redis是单线程程序,所以lua的TPS有限。

在单个优惠券后端处理能力已知有限的情况下,有2个解决方案:

1)限流:也就是通过前端挡住大多数流量,只透传可控的流量到redis,给予用户友好的文案即可。
2)扩展:把优惠券的库存拆成N份,存储到多个redis实例,用户按uid打散到不同的redis实例进行扣减。

但是从公司量级来说,除非做到小米和京东的秒杀量级,否则上述方案大概一辈子也用不到。

存储量

demo里直接把优惠券coupon放在redis里,为了节约存储空间可以考虑只放coupon的数据库id。

对于商品类秒杀,库存可能只是一个剩余数量,异步任务需要走商品库存服务完成真实扣减。

lua注意事项

1,不能使用带有随机性质的函数(redis会直接报错),比如time(),spop()等,否则主从同步时在从库上重放脚本,会导致主从不一致。
2,在cluster/codis下,可以使用redis的hash tags机制,实现多个key路由到同一个slot的能力,确保lua可以访问到相关数据。
3,不要使用eval,每次上传脚本到redis性能很差;应该使用evalsha,提前计算好lua脚本的sha1值,当evalsha报错时再触发一次script load上传脚本,也就是懒惰上传。

异常处理

因为最终是数据库作为业务凭证,所以当redis主从切换等数据丢失场景出现时,至多出现少发的情况,绝对不会出现超发,因为在数据库层面可以基于coupon做去重。

redis-lua's People

Contributors

owenliang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.