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

余额要不要单独弄个数据库表来记录?

  •  
  •   zjsxwc ·
    zjsxwc · 2018-01-02 20:27:21 +08:00 · 4821 次点击
    这是一个创建于 2515 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前获取用户余额是通过 sum 用户的所有账单记录表的 amount (用正负表示了收入支出)来计算的,

    考虑的用户账单记录越来越多,每次 sum 效率也很低,要不要单独弄个数据库表来记录余额( KV 结构),每个用户在这个余额表里只占一行,每次用户账单记录增加就修改这个对应行,这么做如何保证余额一定是对的。

    或者有什么更好的获取余额的方式?

    第 1 条附言  ·  2018-02-03 11:30:19 +08:00
    回来说下我们现在的解决方案:

    给账单表增加了 2 个字段 “ before_record_amount ” 与 “ after_record_amount ” 表示 添加这条记录前的余额 和 添加这条记录后的余额, 然后每天某个时间点 crontab 补全数据库中所有 before_record_amount 与 after_record_amount 的值。

    然后用户查询他余额时,先尝试获取用户最近的 before_record_amount 与 after_record_amount 都不为空的那条账单记录 K,然后在 sum 那条账单记录 K 之后发生的所有账单记录金额为 P,最好把 K 的账单记录金额加上 P 就是用户的余额。
    14 条回复    2018-01-03 17:16:04 +08:00
    pynix
        1
    pynix  
       2018-01-02 20:29:20 +08:00
    在用户表里加个字段 balance
    pynix
        2
    pynix  
       2018-01-02 20:30:04 +08:00
    注意在修改这个字段的时候需要加行锁。。
    killz
        3
    killz  
       2018-01-02 20:43:43 +08:00
    当然要 不然如何队长啊 不仅要计算静态值 还要注意川行修改 还要记录变动 log 还要一对一勾兑
    zjsxwc
        4
    zjsxwc  
    OP
       2018-01-02 20:46:22 +08:00
    目前想到的办法:

    每次在 orm 增加一条用户账单记录时,触发事件对 balance 字段进行加减更新( select for update 来阻塞同步保证一致),用户获取 balance 字段接口里一定几率(比如 5%的几率)触发使用 sum 方式获取 balance,然后对比获取的 balance 是否一致,不一致就以 sum 方式获取的为准,并更新 balance
    zealic
        5
    zealic  
       2018-01-02 20:48:47 +08:00
    CRQS
    iEverX
        6
    iEverX  
       2018-01-02 23:05:37 +08:00
    一定保证是对的,这个是通过逻辑保证的。
    4# 的方法,发现错了然后修改,这是治标不治本,bug 没找出来啊
    qiayue
        7
    qiayue  
       2018-01-02 23:32:00 +08:00
    这种东西都有约定俗成的最佳做法,没必要自己想,学习别人的经验即可
    javaluo
        8
    javaluo  
       2018-01-02 23:51:01 +08:00 via Android
    事务 实时 准实时 离线
    thxu
        9
    thxu  
       2018-01-03 09:53:16 +08:00
    我想到有两种方案,一种是在用户信息里面加余额字段,注意每次修改的时候要加锁(单独弄个 kv 结构的数据库差不多是同一个意思);另外一种是把历史数据汇总单独存放,比如把用户每个月的账单统计成一条数据,然后余额就通过当前月的账单记录求和加上统计的历史数据求和计算出来.
    soli
        10
    soli  
       2018-01-03 10:43:20 +08:00
    @qiayue 能给个关键词啥的么?
    miaoxinwei
        11
    miaoxinwei  
       2018-01-03 14:04:14 +08:00
    多弄几个余额
    roricon
        12
    roricon  
       2018-01-03 15:24:48 +08:00
    一般情况下, 余额属于不是那么频繁修改的数据, 行锁就好了.
    如果是 sum 所有账单的方法, 那可以每天生成一个前一日的加总值, 每次查询只需要加一下总值和当日产生的账单就好了. 不过实现起来有点麻烦, 不如直接增加余额行, 然后锁行进行加减操作.
    roricon
        13
    roricon  
       2018-01-03 15:27:42 +08:00
    其实我看到很多系统中都会在每一条交易记录中保存一个操作后余额, 有的还额外保存一个操作前余额.
    这是出于查询对账的便利还是为了啥? 谁来顺道解释一下?
    Keyes
        14
    Keyes  
       2018-01-03 17:16:04 +08:00 via Android   ❤️ 1
    @roricon 更多的是抗抵赖与合规上的要求,所有的交易步骤所影响的数据都应该可以被审计
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2812 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 11:54 · PVG 19:54 · LAX 03:54 · JFK 06:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.