我使用延迟队列实现商品的竞拍成交功能

发布时间 - 2025-07-15 00:00:00    点击率:

背景

我们平时开发可能要求实现这样的需求:用户可以在有效的时间内进行商品竞拍,当有效时间过了之后,取竞拍价最高的用户成交。我们一般可以使用定时任务每5s定时扫描数据库,获取有效时间大于当前时间的商品列表,然后取每个商品中竞价最高的用户存入商品成交表中。

商品成交

如果使用定时任务,这里会有一个问题,定时任务每5s执行一次,就会查询一次数据库,这样对系统,对数据库压力会有一定的压力,并且时间精确度不是很高。个人觉得不是最好的方法。

对于上面的需求,我决定使用延迟对列实现。实现的逻辑为:

当系统启动时,扫描已经发布的商品,并将商品id存放入Redis的延迟队列如果有新商品发布,将新商品id存入延迟队列启动一个常驻线程,扫描延迟队列,获取已到竞拍时间结束的商品,并获取对应商品的竞拍信息,存入用户商品成交表中使用一个兜底的定时任务,每晚执行一次步骤1

延迟队列

这样我们将原来数据库的压力转移到了Redis上,并且Redis本身的Zset也可实现延迟队列,性能会更好。

关于RedisZset实现延迟队列,有兴趣的同学可以看看我写的这篇文章:

代码实现

我们先来写一个Redis的工具类RedisDelayingQueue,用于将数据放入Zset中。

上面代码中queueKeyRediskeymsgkey对应的值,endDate为结束时间,即消费的时间。我们将msg信息封装成TaskItem对象,以便存取。

TaskItem的id可以使用id生成器生成唯一id。

将数据存入Redis后。我们需要延迟消费它。

上面代码是将指定score的数据从Redis中取出,即当前时间小于Redis存入的时间时,我们将这个数据传给handleMsg方法执行。

handleMsg方法具体如下:

这里每一个queueKey对应一个消费类,map中存入的是queueKey和对应的消费类。

代码语言:javascript代码运行次数:0运行复制
Map map = Maps.newHashMap();

当实例化RedisDelayingQueue时,实例化DelayHandler所有的实现类。

代码语言:javascript代码运行次数:0运行复制
public RedisDelayingQueue(List delayHandlers) {    delayHandlers.forEach(delayHandler -> map.put(delayHandler.getQueueKey(), delayHandler));}

所以当我们执行map.get(queueKey)时,获取到的就是queueKey和对应的消费类。因此消费后的业务代码,我们只需要写一个类实现DelayHandler,并重写handler(msg)

这里我们重写一个商品消费类。

接下来我们就是将业务中的数据塞入Redis中。

这里我们使用异步的方式将数据推入Redis中,将符合条件的数据消费出来。

启动系统时需要执行delayxxxDealResult方法用于向Redis中推送数据。

如果我们需要新发布商品时,也需要向Redis中推送数据。

当然如果你不放心,还可以用定时任务每天执行一次数据的推送。

为了保证我们消费的数据不重复,在将消费的数据入库时需要做一下去重判断哦。

测试

如上图,我们将其中一个商品竞拍结束时间设置为比当前时间大,另一个商品为比当前时间小。启动系统控制台打印了如下日志:

状态为DOING的商品为竞拍中的商品,因此都进入了延迟队列。

启动系统后我们发现结束时间小于当前时间的商品已经被消费,因为没有人竞拍,而竞拍时间到了,这里显示为流拍UNSETTLE。

时间一到,延迟队列准时消费满足条件的数据。

看数据库中商品的状态也改变了。

交易结果也插入了相关的商品信息。

到这里我们就实现了商品竞拍成交功能。

如果你有更好的想法,欢迎评论给出意见。如果这篇文章对你有帮助,欢迎点赞转发。


# linux  # redis  # 工具  # red  # JavaScript  # 封装  # 线程  # map  # 对象  # 异步  # 数据库  # 竞拍  # 你有  # 重写  # 可以使用  # 这篇文章  # 结束时间  # 时需  # 的是  # 就会  # 如果你 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Windows10如何删除恢复分区_Win10 Diskpart命令强制删除分区  手机网站制作与建设方案,手机网站如何建设?  JavaScript如何操作视频_媒体API怎么控制播放  如何在香港服务器上快速搭建免备案网站?  免费网站制作appp,免费制作app哪个平台好?  Android 常见的图片加载框架详细介绍  Laravel辅助函数有哪些_Laravel Helpers常用助手函数大全  iOS中将个别页面强制横屏其他页面竖屏  香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化  Laravel怎么自定义错误页面_Laravel修改404和500页面模板  JavaScript Ajax实现异步通信  如何用IIS7快速搭建并优化网站站点?  Laravel如何使用Blade组件和插槽?(Component代码示例)  如何在七牛云存储上搭建网站并设置自定义域名?  Python高阶函数应用_函数作为参数说明【指导】  C语言设计一个闪闪的圣诞树  Win11怎样安装网易有道词典_Win11安装词典教程【步骤】  如何为不同团队 ID 动态生成多个独立按钮  nodejs redis 发布订阅机制封装实现方法及实例代码  Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】  php读取心率传感器数据怎么弄_php获取max30100的心率值【指南】  Laravel如何部署到服务器_线上部署Laravel项目的完整流程与步骤  长沙企业网站制作哪家好,长沙水业集团官方网站?  Win11任务栏卡死怎么办 Windows11任务栏无反应解决方法【教程】  Laravel Blade模板引擎语法_Laravel Blade布局继承用法  Laravel如何实现API速率限制?(Rate Limiting教程)  Laravel如何实现一对一模型关联?(Eloquent示例)  JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)  如何生成腾讯云建站专用兑换码?  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  java获取注册ip实例  Laravel storage目录权限问题_Laravel文件写入权限设置  JS中页面与页面之间超链接跳转中文乱码问题的解决办法  php485函数参数是什么意思_php485各参数详细说明【介绍】  laravel怎么通过契约(Contracts)编程_laravel契约(Contracts)编程方法  JS碰撞运动实现方法详解  免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?  Laravel如何实现多对多模型关联?(Eloquent教程)  高性能网站服务器部署指南:稳定运行与安全配置优化方案  百度浏览器如何管理插件 百度浏览器插件管理方法  Laravel如何配置任务调度?(Cron Job示例)  微信h5制作网站有哪些,免费微信H5页面制作工具?  如何在景安云服务器上绑定域名并配置虚拟主机?  如何自定义建站之星网站的导航菜单样式?  魔方云NAT建站如何实现端口转发?  广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?  阿里云高弹*务器配置方案|支持分布式架构与多节点部署  Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤  如何在阿里云服务器自主搭建网站?  JS实现鼠标移上去显示图片或微信二维码