V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zzzmh
V2EX  ›  Java

Java 实现一个类似拍卖的系统 有个地方实现不了

  •  
  •   zzzmh · 114 天前 · 3291 次点击
    这是一个创建于 114 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题 spring 全家桶用习惯了 换个东西反而写不出来了
    后来学了一段时间 socket 实现了前后端通信
    现在还有一个问题卡了很久没解决,请教各位大佬

    一场拍卖假如说一共有 5 个阶段,其中每个阶段都有倒计时,有些操作会影响倒计时,比如出价加 5 秒,之类的。然后我要从 socket 里实时的读取到当前是什么阶段的什么状态,倒计时还剩多少秒。 其实一开始感觉不复杂,就到了实现的时候发现,线程也已经忘了怎么写了。。。百度也找不到合适的框架什么的能刚好合适这个需求。
    今天就只想求个思路,比如说用 MQ 好,还是自己手搓线程好,还是怎么实现最合理。Thanks♪(・ω・)ノ 谢谢

    34 条回复    2023-10-30 16:56:04 +08:00
    yumenawei
        1
    yumenawei  
       114 天前
    搜一下 websocket 看下,我也没具体了解过,好像可以解决你的问题
    doublestart
        2
    doublestart  
       114 天前
    一个用户出价, 然后通过发送消息给其他用户就行了, 用户量不大, 没必要用 MQ
    bigLinux
        3
    bigLinux  
       114 天前
    当发生一些会影响倒计时的操作时,让前端发一个 UDP 的消息给后端,发消息的同时前端加上 5 秒,然后服务器收到这个消息也加上 5 秒。
    doublestart
        4
    doublestart  
       114 天前
    先学习下网络编程, 游戏服务端开发相关的, 找个开源项目看看
    kujio
        5
    kujio  
       114 天前
    如果是会影响倒计时的操作,任何用户发送了这些操作,就同步发送给所有用户,通知他们重新倒计时,并带上倒计时开始时间
    awalkingman
        6
    awalkingman  
       114 天前
    要实时,不就是 websocket 双工通信或者高频 http 定时轮询吗,这个语言框架有啥关系?
    要定时,redis 或者别的中间件设置一下过期时间。就一台机子一个服务的话在应用里自己设置过期时间也行。
    总之和语言没关系。
    banmuyutian
        7
    banmuyutian  
       114 天前   ❤️ 3
    janwarlen
        8
    janwarlen  
       114 天前
    @banmuyutian #7 啊?
    darkengine
        9
    darkengine  
       114 天前
    客户端只负责发起 ’我要出价‘ 这个动作

    当前时间能不能出价,出价之后加 5 秒这些操作都在服务器端做,完成后把结果告诉客户端
    c2const
        10
    c2const  
       114 天前
    @banmuyutian
    啊?
    lsk569937453
        11
    lsk569937453  
       114 天前   ❤️ 1
    把倒计时的时间设计成 redis 的 key 的过期时间,所有的前后端通信只走 http 。

    1.拍卖人员点击"开始拍卖",则写入 redis 中一个 key ,并且过期时间为 1 分钟。
    购买人员打开网页,则前端以每 0.5 秒一个的定时任务去请求这个 key 的剩余时间。如果购买人员点击加价,则将 redis 的 key 的过期时间加 5 秒。

    这个方案还有一些细节,比如想要记录一个购买阶段的截止时间,而 redis 中的 key 过期就删除了,则需要配合数据库一起完成。
    zzzmh
        12
    zzzmh  
    OP
       114 天前
    我好像没描述准确,现在是用 springboot websocket ,实现了前后端交互,现在缺流程控制,比如说后端在 19.00 分给前端发启动拍卖,并给前端一个初始倒计时,然后中间加入的人,也会在初始化的时候,得到一个与其他人同步的倒计时。然后进入下一阶段,也会给前端发进入下一阶段,倒计时剩余多少时间。然后有人出价就会增加倒计时秒数,并同步给其他人。以此类推。现在就是这个倒计时怎么实现我很蛋疼,可能是网站写多了,游戏没学过,现在思路转变不过来。
    zzzmh
        13
    zzzmh  
    OP
       114 天前
    @lsk569937453 多谢,感觉合适
    lsk569937453
        14
    lsk569937453  
       114 天前   ❤️ 1
    技术方案 2:

    在数据库/redis 中记录最终的时间,然后前端去计算秒数,所有的前后端通信只走 http 。

    1.拍卖人员点击"开始拍卖",则写入 redis 中一个 key ,且 value 值为当前时间+1 分钟后的时间。
    购买人员打开网页,则前端以每 0.5 秒一个的定时任务去请求这个 key 的时间,然后计算出剩余的倒计时。如果购买人员点击加价,则将 redis 的 key 的过期时间加 5 秒。
    lsk569937453
        15
    lsk569937453  
       114 天前
    @lsk569937453 如果购买人员点击加价,则将 redis 的 key 的 value 的时间加 5 秒。
    banmuyutian
        16
    banmuyutian  
       114 天前
    @zzzmh
    一个一秒的定时任务往 websocket 推送剩余时间,一个接口每次收到出价增加剩余时间,记得用 volatile 修饰
    asmoker
        17
    asmoker  
       114 天前 via Android
    这不就是在线答题差不多
    aibx01
        18
    aibx01  
       114 天前
    如果仅仅是定时这个需求。
    把结束时间存 redis 中,前端也记录一个时间,5s ~10s 去跟后端进行同步即可。每次加时,后端拿到锁之后,去更新 redis 的即可,redis 到期时间设置为 实际的结束时间。如果加时判断 redis 已不存在,则为拍品时间已结束。
    xianyv
        19
    xianyv  
       114 天前   ❤️ 1
    @zzzmh 倒计时用 redis 的 key 的过期时间,等 redi 的这个 key 过期了,就通过 websocket 通知其他用户拍卖结束.
    zhazi
        20
    zhazi  
       114 天前
    while true 每秒检查一次就行了
    FawkesV
        21
    FawkesV  
       114 天前
    初始设置是 redis 唯一 key ,value 存最后出价的人,到期时间存为结束时间。
    点击加价就加锁来更新 出价人 value 和 结束时间吧 .
    ---
    前端每次出价时,前端也自动更新页面的时间。再用高频轮训 http 请求去获取当前商品的结束竞拍时间,
    conjane
        22
    conjane  
       114 天前
    可以看看 akka
    sunjiayao
        23
    sunjiayao  
       114 天前
    加价 http 请求-> 锁 {redis 加价}-> 加价成功 -> 通过 ws 向所有客户端推送最新价格和时间
    dengji85
        24
    dengji85  
       114 天前
    前端轮循,后台返回拍卖的属性,拍卖阶段,剩余倒计时;
    relsoul
        25
    relsoul  
       114 天前
    如果是小项目不要走 websocket ,如果要走 可以试试 socket.io ,我的建议是 直接前端轮询就行( 1s ),减少前后端的心智负担。所有的计算后端放 redis 处理。后端做延迟/定时任务更新 redis 的 key 即可。拍卖完成后落 db 。
    如果是大型项目估计也不用我说 架构层应该已经评估了时间与开发量得出了解决方案。
    hush3
        26
    hush3  
       114 天前
    后端每秒定时向所有前端发一次消息,当有客户端改价,那计时器肯定要在后端这个改价接口里有变动,但是不影响每秒发给所有前端的逻辑,所有前端也能在下一秒收到改价后的新倒计时。
    感觉剩余时间存内存一个变量就行吧
    Keppel
        27
    Keppel  
       114 天前
    上半年实现了一个类似的拍卖功能,需求都类似
    magicfield
        28
    magicfield  
       114 天前
    实时的要求就用长连接嘛,实现一般就是 http 轮询或 websocket ,邪道点还能用 hook 。
    真实时间由后端控制,放数据库/redis ,小系统直接放缓存都行。
    前端时间仅作为显示时间,定期 http 轮询同步或 websocket 同步
    rev1si0n
        29
    rev1si0n  
       114 天前
    没试过,redis 的 pubsub 应该可以解决这个问题吧,每个客户连上对应的端点后,自动监听频道,客户端发价后后端验证处理并向频道广播。如果使用 web 框架的话应该也不需要单独开线程直接每个请求对应上去。
    rev1si0n
        30
    rev1si0n  
       114 天前
    @rev1si0n 其他长链接的东西,socket 、websocket 看你怎么选了
    coderxy
        31
    coderxy  
       114 天前
    你这需求根本不需要 websocket ,倒计时写到 redis 里, 客户端每 200ms 轮询一下当前倒计时并展示出来就完事了。 这种拍卖的业务不可能有多高的并发的。 不然你得自己写一套类似于长连接通讯的东西,对你来说开发量和熟练度都是问题。
    cvbnt
        32
    cvbnt  
       114 天前 via Android
    1 ,开始拍卖后写入 redis 设置倒计时
    2 ,用户点击按钮后发送 http 请求到后端,后端对时间进行扣减
    3 ,重点:后端要创建一个 server-sent events 接口,拍卖开始后所有用户通过 SSE 接口建立长连接,由 SSE 接口定时返回倒计时时间,用户前端显示倒计时(长连接避免轮询创建 http 请求降低服务器压力,相比 websocket ,sse 改造成本低且所有现代化浏览器都支持 sse )
    Seulgi
        33
    Seulgi  
       114 天前
    实际上不就是一个时间戳,一些动作触发+x 秒的操作,socket 同步给各个用户,页面实现时间戳转倒计时。
    1Q1
        34
    1Q1  
       114 天前
    @coderxy 正解
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   917 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 21:10 · PVG 05:10 · LAX 13:10 · JFK 16:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.