美文网首页
业务系统记录操作日志的几种方式

业务系统记录操作日志的几种方式

作者: littlersmall | 来源:发表于2017-09-27 12:16 被阅读2623次

    最近的一个业务系统,需要实现一套操作日志的记录方式。这篇日志算是对各种实现的一个思考。

    一 每个操作记录流水
    这种方式非常适合每一步操作都非常重要的系统。比如常见的金融操作系统。在一般的场景下,我们只会对涉及金钱的操作记录这种流水日志,比如转账,扣款等。
    在设计账户流水表的时候,需要有以下几个必须的字段:
    (1) instruction_id 流水号
    (2) amount 金额
    (3) operation_type 操作类型(转账or扣款)
    (4) before_balance 操作前账户余额
    (5) after_balance 操作后账户余额
    (6) time 操作时间
    第一个字段,流水号,是主键。这个字段的必要性在于,它能维护该记录修改的幂等性。简单的实现,流水号可以使用uuid。
    当前端发起一个充值的操作时,首先在前端产生一个流水号,然后将其他的用户填写的参数通过rpc请求发送到后端。后端的处理流程如下:
    (1) 开启事务
    (2) 从db中查询账户余额
    (3) 修改账户余额
    (4) 记录流水
    (5) 提交事务
    假设在执行过程中,出现了网络问题,该执行结果处于未知状态,那么前端可以通过刚才的uuid反复重试,直到得到一个确定的结果为止。
    我们可以对流水表稍做改进,以适应普遍的情况。字段如下:
    (1) instruction_id 流水号(在对可靠性要求不太高的场景下,可使用数据库自增id)
    (2) operation_type 操作类型
    (3) before (一个json,描述修改前的该行记录)
    (4) after (json, 描述修改后的该行记录)
    (5) time
    还有一些可选的字段,比如 input_param(输入参数),操作人等等。
    这种基于流水的方式优点有:
    1 可靠性很高
    2 实现方式确定,可以基于接口做注解实现
    3 可以基于该流水,实现业务层的操作回滚
    但是它的缺点也很明显:
    1 增加开发量,需要额外增加记录写入
    2 降低运行效率,需要多一到两次查询(before, after)
    3 和业务绑定的比较紧

    二 基于数据库的binlog实现
    第二种方式是基于mysql的binlog来实现。这种方式最大的好处是可以和业务完全的解耦,而且统计的结果是完全准确的(相比于有些完全基于业务代码的实现来说,这类实现一般是对执行前后查询两次)。
    关于binlog的定义及获取,可以参考

    http://www.jianshu.com/p/1f7889273845

    binlog可以描述为下面这种model:

    @Data
    public class RowDiffModel {
        long timestamp;
        String tableName;
        List<String> pkColumnName = new ArrayList<>();  //主键列
        List<Object> pk = new ArrayList<>();
        int type;  //1 新建 //2 更新 //3 删除
        List<String> diffColumns = new ArrayList<>();
        Map<String, Object> preValue = new HashMap<>();
        Map<String, Object> newValue = new HashMap<>();
    }
    

    基于binlog的实现还有一个小问题。如何获得用户的操作id?在一些涉及权限授权及权限分离的系统中,操作id非常重要。但由于这个字段完全隶属于业务层,和数据库的设计关联度并不大。
    为了解决这个问题,我们需要在每个涉及用户操作的表中增加一个新的字段operator_id。
    还有一种情况是,用户的某一步操作涉及多个表的修改,这个时候可以按事务id将binlog聚集起来。
    之后,我们需要将binlog转换为一条操作记录,记录到库里,操作记录的字段如下:
    (1) operator_id (操作人id)
    (2) operation_type (操作类型,可根据表及binlog类型(insert,update,delete)确定)
    (3) before (一个json,描述本行记录修改前的值)
    (4) after (描述本行记录修改后的值)
    (5) timestamp (时间戳)

    现在,用户操作日志的生成及查询,整体流程如下:
    1 用户操作修改表
    2 开启异步服务获取binlog
    3 根据事务id将binlog做一定的聚合处理
    4 将binlog转换为一条原始的操作日志,并记录到库里
    5 当用户查询操作日志时,根据条件检索操作日志
    6 将操作日志转换为一个用户可读的view返回

    相关文章

      网友评论

          本文标题:业务系统记录操作日志的几种方式

          本文链接:https://www.haomeiwen.com/subject/yvbtextx.html