V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
monsterj
V2EX  ›  问与答

大佬们,那种 XX 天后过期改状态的需求,精确到秒,你们是咋设计的?

  •  
  •   monsterj · 2018-04-28 11:45:49 +08:00 · 3619 次点击
    这是一个创建于 2402 天前的主题,其中的信息可能已经有所发展或是发生改变。

    想到几种, 1:定时器,一秒扫一次,感觉太频繁了吧; 2:mysql 定时任务+存储过程; 3:消息队列;

    26 条回复    2018-04-29 11:59:04 +08:00
    nybux
        1
    nybux  
       2018-04-28 12:28:51 +08:00
    如果不涉及到查询,可以在显示的时候修改。
    monsterj
        2
    monsterj  
    OP
       2018-04-28 12:53:22 +08:00
    @nybux 后台管理肯定要涉及到查询的
    nybux
        3
    nybux  
       2018-04-28 12:59:06 +08:00
    时间是等长的嘛?
    kingname
        4
    kingname  
       2018-04-28 13:04:35 +08:00 via iPhone
    前台用 JS 做减法,后台不用频繁查,下次完全刷新的时候再更新就可以了。
    monsterj
        5
    monsterj  
    OP
       2018-04-28 14:02:08 +08:00
    @nybux 假如过期时间是 3 天
    gfreezy
        6
    gfreezy  
       2018-04-28 14:04:04 +08:00
    存在过期时间,然后状态根据过期时间算出来。
    monsterj
        7
    monsterj  
    OP
       2018-04-28 14:05:48 +08:00
    @kingname 这样只是考虑了前台用户展示的情况,有其他业务需要这个状态操作的话,就行不通
    kera0a
        8
    kera0a  
       2018-04-28 14:07:27 +08:00
    过期后
    第一个访问它的事件,触发更新操作~
    monsterj
        9
    monsterj  
    OP
       2018-04-28 14:07:55 +08:00
    @gfreezy 那就是第一种?每秒钟扫一次过期时间
    Weny
        10
    Weny  
       2018-04-28 14:08:49 +08:00 via iPhone
    延时队列 或者 定时任务 去处理
    sfree2005
        11
    sfree2005  
       2018-04-28 14:10:57 +08:00 via Android
    我的 web app 用的是 laravel 框架,用的是自带的 queue 和 schedule, 它可以将 queue 存于 Redis,每秒扫一下。因为是扫内存 所以速度快和资源占用少,感觉不错。
    monsterj
        12
    monsterj  
    OP
       2018-04-28 14:11:26 +08:00
    @kera0a 这样会代码冗余吧,还容易忘几加更新操作
    liuzelei
        13
    liuzelei  
       2018-04-28 14:12:10 +08:00
    redis ttl、mq delay exchange
    kera0a
        14
    kera0a  
       2018-04-28 14:12:31 +08:00
    @monsterj
    存过期时间的方法最好吧~
    “有其他业务需要这个状态操作的话,就行不通” ? 怎么会行不通呢? 是否过期服务器怎么用过期时间-当前时间呗,小于 0 就是过期了啊,不管什么地方都可用
    monsterj
        15
    monsterj  
    OP
       2018-04-28 14:12:38 +08:00
    @sfree2005 每秒扫内存可以接受
    monsterj
        16
    monsterj  
    OP
       2018-04-28 14:17:13 +08:00
    @kera0a 假如有一个过期时间,和一个状态,需要在过期后,修改状态,其他业务只需要查这个状态
    chenuu
        17
    chenuu  
       2018-04-28 14:25:23 +08:00
    redis 过期功能,过期会有键空间通知.
    af463419014
        18
    af463419014  
       2018-04-28 14:28:30 +08:00
    每 5 分钟扫一下
    5 分钟以内会过期的数据,每条数据启一个线程
    每个线程 sleep 对应数据的过期时间,然后修改状态为过期
    kera0a
        19
    kera0a  
       2018-04-28 14:30:28 +08:00
    @monsterj 其他业务不能查过期时间么?
    其实这个主动更新状态并不好,假如你有 N 个状态需要更新,而你的服务器运行速度慢,不能在 1 秒内更新完毕,那不就出 BUG 了。假如需求变更,需要兼容到毫秒,那就更加不好了。
    你往存过期时间这靠,如果实在靠不了,可以试试我说的懒更新,如果还靠不了
    各种定时任务框架了解一下~
    kslr
        20
    kslr  
       2018-04-28 14:31:34 +08:00
    延时队列
    watzds
        21
    watzds  
       2018-04-28 14:32:08 +08:00 via Android
    如果 Java,有定时任务 jar quartz,这点性能肯定不用担心
    msg7086
        22
    msg7086  
       2018-04-28 14:35:37 +08:00
    从面相对象的角度考虑,这个状态是由对象表达出来的,对象本身既可以从数据库中查询,也可以通过比较过期时间和当前时间得出。
    比如函数 obj.expired?,可以这样写
    def expired?
    self.expired or (self.expired = expire_date < now) and self.save
    end

    我会选择避免用面向过程的方法去思考这个问题(用第三方的线程去扫描修改状态什么的)。
    wplct
        23
    wplct  
       2018-04-28 15:36:58 +08:00
    参考 redis 过期,取值时确认该值是否过期,配合定时任务(人家 redis 的定时任务执行多久是算 cpu 时间的,学不来学不来)
    onedayonecode
        24
    onedayonecode  
       2018-04-28 16:43:54 +08:00
    数据库存储过期时间,用到的时候读出来和当前时间对比
    projectzoo
        25
    projectzoo  
       2018-04-28 18:41:15 +08:00
    我也是建议读取的时候再处理,不读取就不处理。
    liuzhaowei55
        26
    liuzhaowei55  
       2018-04-29 11:59:04 +08:00 via iPhone
    存过期时间,读取的时候判断。和 Redis 的过期判定差不多,但是没 Redis 的那么复杂。
    消息队列也有做。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   983 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 22:54 · PVG 06:54 · LAX 14:54 · JFK 17:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.