V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
zzzmh
V2EX  ›  Java

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

  •  
  •   zzzmh · Oct 30, 2023 · 5719 views
    This topic created in 910 days ago, the information mentioned may be changed or developed.

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

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

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

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

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

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

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

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