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

请教,如何根据时间生成有序号码?

  •  
  •   franklinre · 2022-07-12 11:38:22 +08:00 · 2838 次点击
    这是一个创建于 875 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我有一个需求:就是关于排队号的生成。生成记录的时候,给这条记录指定一个号码,当天从 1 号开始递增,隔天后重置。。。 这样就会带来并发问题,多个请求抢某个指定的号码。 所以, 能否有一个根据记录创建时间生成有序号码的方式呢?或者有其他更好的方案? 技术栈:angular + webflux + MongoDB

    18 条回复    2022-07-15 16:03:48 +08:00
    linyinma
        1
    linyinma  
       2022-07-12 11:56:20 +08:00   ❤️ 3
    redis 自增 日期作为 KEY
    Rocketer
        2
    Rocketer  
       2022-07-12 12:06:01 +08:00 via iPhone
    这么简单的算法,可以做个单线程服务来专门生成 ID 。
    westoy
        3
    westoy  
       2022-07-12 12:10:35 +08:00
    拿 zeromq 或者 redis 做一个生成器。 有些数据库支持自定义 sequence 也可以做, 就是生成成本会比较高。
    VeryZero
        4
    VeryZero  
       2022-07-12 13:33:17 +08:00
    加锁呗,单机应用单机锁,分布式应用分布式锁
    THESDZ
        5
    THESDZ  
       2022-07-12 14:09:47 +08:00
    单线程,按时间切割,批量生成等待获取。
    issakchill
        6
    issakchill  
       2022-07-12 14:18:06 +08:00
    感觉可以用雪花 id?
    haoliang
        7
    haoliang  
       2022-07-12 14:21:52 +08:00
    根据并发数量选用 second/millisecond/nanosecond 级别的时间戳 - 今天 00:00:00 的时间戳,不考虑号码的连续性且不强制要求不能重复
    lmshl
        8
    lmshl  
       2022-07-12 14:43:00 +08:00
    盲狗递币上没了解过,我说下我在 postgres 上的经验
    PostgreSQL 有个函数可以直接用,SELECT nextval( seq_name );
    就可以拿到全局唯一的自增序列号。

    你这个场景需要考虑两个问题
    1. 多实例并行拿 ID 怎么解决
    2. 错误重启怎么恢复

    单线程是解决不了问题的,考虑到你将来可能部署多个 webflux 进程 /容器做水平扩展。同时服务崩溃后重启的时候计数不能忘了从头开始吧。
    盲狗递币可能可以通过触发器或其他手段达成类似效果?这需要懂行的来贴一下文档了
    SaulLawliet
        9
    SaulLawliet  
       2022-07-12 14:43:36 +08:00   ❤️ 4
    @issakchill 请第 28149676972703744 号下单的顾客前来取餐. lol
    Jooooooooo
        10
    Jooooooooo  
       2022-07-12 14:44:46 +08:00
    1 楼正解了. 跨天新的日期自增自动从 1 开始.
    lmshl
        11
    lmshl  
       2022-07-12 15:06:07 +08:00
    Redis 开 AOF 持久化可以满足要求,只开 RDB 的话可能会造成生成重复 ID 。
    但是 AOF 可能对性能影响大,建议放弃 Redis 方案
    lmshl
        12
    lmshl  
       2022-07-12 15:20:04 +08:00
    https://www.mongodb.com/basics/mongodb-auto-increment
    文档里给了一种新开一个 counters collection 的方案,来模拟 rdbms 提供的 sequence ,可以参考
    shower
        13
    shower  
       2022-07-12 18:00:47 +08:00
    @lmshl 盲狗递币 剖思格瑞
    cyaki
        14
    cyaki  
       2022-07-13 07:21:19 +08:00
    ULID, 包含了时间信息, 但不符合你需要的重置需求
    qile1
        15
    qile1  
       2022-07-13 23:34:14 +08:00 via Android
    楼主排队是怎么实现的,能不能详细说说?年月日时分秒后面加原子时钟可以不?
    franklinre
        16
    franklinre  
    OP
       2022-07-14 08:45:14 +08:00
    @qile1 用 redis 自增 或者 提前生成号码,还没确定。
    加原子时钟?好高级,不懂。
    qile1
        17
    qile1  
       2022-07-15 00:30:08 +08:00 via Android
    @franklinre 我也想了好久,遇到现在核酸检测预约,5000 个预约号,一分钟内抢光,不好处理,所以咨询下你怎么处理,我们是直接网络限流
    franklinre
        18
    franklinre  
    OP
       2022-07-15 16:03:48 +08:00
    @qile1 你看下抢号时 cpu 的负载,如果超过 80%,应该只能加配置了吧?
    也可以把抢号改成非同步,用消息队列慢慢处理请求,处理完再发消息给用户。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1004 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 21:02 · PVG 05:02 · LAX 13:02 · JFK 16:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.