Redis+lua进行类似秒杀的实现-创新互联
Redis+lua进行类似秒杀的实现
由于项目需要,需要多线程去获取和修改数据库的库存,考虑到给数据库加锁效率低,所以采用redis+lua来进行实现 。
成都创新互联公司专注于柯桥企业网站建设,成都响应式网站建设公司,商城开发。柯桥网站建设公司,为柯桥等地区提供建站服务。全流程定制网站,专业设计,全程项目跟踪,成都创新互联公司专业和态度为您提供的服务redis的单线程操作特性来执行lua脚本,通过lua脚本来保证原子性。如果通过单纯的redis指令来进行更改,在读和写之间会存在多线程并发更新的问题。
1.首先定义redis数据结构
goodId:
{
"total":100,
"released":0;
}
- 其中goodId为商品id号,可根据此来查询相关的数据结构信息,total为总数,released为发放出去的数量,可使用数为total-released
2.编写lua脚本local n = tonumber(ARGV[1]) if not n or n == 0 then return 0 end local vals = redis.call("HMGET", KEYS[1], "total", "released"); local total = tonumber(vals[1]) local blocked = tonumber(vals[2]) if not total or not blocked then return 0 end if blocked + n <= total then redis.call("HINCRBY", KEYS[1], "released", n) return n; end return 0
- 执行脚本命令`EVAL script_string 1 goodId apply_count`
- 若库存足够则返回申请的数量,否则返回0,不返回可满足的剩余数
3.spring boot 调用
- pom dependency
- java code
```java
long count = redisHelper.getStrCache().execute(new RedisCallback() {
@Nullable
@Override
public Long doInRedis(RedisConnection redisConnection) throws DataAccessException {
long ret = redisConnection.eval(script.getScriptAsString().getBytes(), ReturnType.INTEGER, 1, key.getBytes(), String.valueOf(count).getBytes());
return ret;
}
});
4.redis->database
针对redis到databases的更新,思考了很久,没有找到较好的解决办法,先采用定时任务异步更新。至于数据是否丢失的问题,如果redis挂了,重启后redis会恢复数据,等下次定时任务就可以将数据库中的数据保持一致,缺点是redis挂了秒杀活动会失败。
至于redis到database更新的如何驱动,列出两种愚见:
- redis存一份相关hash键名单表,通过读取名单表来读取更新
- 通过流式读取databases中的表来读取更新。
欢迎各位提出问题,谢谢您的阅读
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
新闻名称:Redis+lua进行类似秒杀的实现-创新互联
文章链接:http://scgulin.cn/article/dheehg.html