作者:努力减肥的胖子 来自:JAVA葵花宝典
前言
用户在操作我们系统的过程中,针对一些重要的业务数据进行增删改查的时候,我们希望记录一下用户的操作行为,以便发生问题时能及时的找到依据,这种日志就是业务系统的操作日志。
本篇我们来探讨下常见操作日志的实现方案和可行性
常见的操作日志类型
用户登录日志重要数据查询日志 (但电商可能不重要的数据也做埋点,比如在淘宝上你搜索什么商品,即使不买,一段时间内首页也会给你推荐类似的东西)重要数据变更日志 (如密码变更,权限变更,数据修改等)数据删除日志......总结来说,就是重要的增删改查根据业务的需要来做操作日志的埋点。
实现方案对比
基于AOP(切面)传统的实现方案
优点:实现思路简单;缺点:增加数据库的负担,强依赖前端的传参,不方便拓展,不支持批量操作,不支持多表关联;基于数据库Binlog
优点:解除了数据新旧变化的耦合,支持批量操作,方便多表关联拓展,不依赖开发语言;缺点:数据库表设计需要统一的约定;方案实现细节
一、基于AOP切面+注解的传统方案
传统的做法就是切面+注解的方式,这种对代码的侵入性不强,通常记录ip、业务模块、操作账号、操作场景、操作来源等等,一般在注解+拦截器里这些值都拿得到,如下图所示:
这种常见的我们在通用方法都可以处理,但是在数据变更方面,一直没有较好的实现方式,比如数据在变更前是多少,变更后是多少。
以我们以前实现的一套方案来说,基于数据变更的记录方式不仅要和需求方约定好模板(上百个字段的不可能都做展示和记录),也要和前端做一些约定,比如在修改之前的值是多少,修改后的值是多少,如下代码客观请看:
@Valid @NotNull(message = "新值不能为空") @UpdateNewDataOperationLog private T newData; @Valid @NotNull(message = "旧值不能为空") @UpdateOldDataOperationLog private T oldData;存在的问题:
1.旧值如果不多查询一次数据库则需要依赖前端把旧值封装到oldData对象中,很有可能已经不是修改前的值;2.无法处理批量的List数据;3.不支持多表操作;再以一个场景为例,再删除之前需要记录删除前的值,是不是还得再查一次~
@PostMapping("/delete") @ApiOperation(value = "删除用户信息", notes = "删除用户信息") @DeleteOperationLog(system = SystemNameNewEnum.SYS_JMS_LMDM, module = ModuleNameNewEnum.LMDM_AUTH, table = LogBaseTableNameEnum.TABLE_USER, methodName = "detail")二、基于数据库Binlog 方案
系统架构图如下:
「主要分为3块:」
1:业务应用 生成每次操作的traceid,并更新到操作的业务表中,发送1条业务消息,包含当前操作的操作人相关的信息;2:日志收集应用 对业务日志和转换后的binlog日志做整合,提供对外的日志查询搜索API;3:日志处理应用利用canal采集和解析业务库的binlog日志并投递到kafka中,解析后的记录中记录了当前操作的操作类型,如属于删除、修改、新增,和新旧值的记录,格式如下:{"data":[{"id":"122158992930664499","bill_type":"1","create_time":"2020-04-2609:15:13","update_time":"2020-04-2613:45:46","version":"2","trace_id":"exclude-f04ff706673d4e98a757396efb711173"}],"database":"yl_spmibill_8","es":1587879945200,"id":17161259,"isDdl":false,"mysqlType":{"id":"bigint(20)","bill_type":"tinyint(2)","create_time":"timestamp","update_time":"timestamp","version":"int(11)","trace_id":"varchar(50)"},"old":[{"update_time":"2020-04-2613:45:45","version":"1","trace_id":"exclude-36aef98585db4e7a98f9694c8ef28b8c"}],"pkNames":["id"],"sql":"","sqlType":{"id":-5,"bill_type":-6,"create_time":93,"update_time":93,"version":4,"trace_id":12},"table":"xxx_transfer_bill_117","ts":1587879945698,"type":"UPDATE"}处理完binlon日志转换后的操作日志,如下:
{ "id":"120716921250250776", "relevanceInfo":"XX0000097413282,", "remark":"签收财务网点编码由【】改为【380000】, 签收网点名称由【】改为【泉州南安网点】,签收网点code由【】改为【2534104】,运单状态code由【204】改为【205】,签收财务网点名称由【】改为【福建代理区】,签收网点id由【0】改为【461】,签收标识,1是,0否由【0】改为【1】,签收时间由【null】改为【2020-04-24 21:09:47】,签收财务网点id由【0】改为【400】,", "traceId":"120716921250250775" }库表设计
1:所有业务系统表需要添加trace_id字段,每次操作生成一个随机字符串并保存到业务表中;2:日志收集应用库表设计 CREATE TABLE `table_config` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id', `database_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '数据库名', `table_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ' 数据库表名', PRIMARY KEY (`id`), UNIQUE KEY `unq_data_name_table_name` (`database_name`,`table_name`) USING BTREE COMMENT '数据库名表名联合索引') ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='数据库配置表';CREATE TABLE `table_field_config` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `table_config_id` bigint(20) DEFAULT NULL, `field` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '字段 数据库', `field_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '字段 中文名称', `enum_flag` tinyint(2) DEFAULT NULL COMMENT '是否枚举字段(1:是,0:否)', `relevance_flag` tinyint(2) DEFAULT NULL COMMENT '是否是关联字段(1:是,0否)', `sort` int(11) DEFAULT NULL COMMENT '排序', PRIMARY KEY (`id`), KEY `idx_table_config_id` (`table_config_id`) USING BTREE COMMENT '表ID索引') ENGINE=InnoDB AUTO_INCREMENT=2431 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='数据库字段配置表';CREATE TABLE `table_field_value` ( `id` bigint(20) NOT NULL, `field_config_id` bigint(20) DEFAULT NULL, `field_key` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ' 枚举', `filed_value` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '枚举名称', PRIMARY KEY (`id`), KEY `ids_field_config_id` (`field_config_id`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='数据字典配置表';
效果
基于binlog实现方案未来规划
优化发送业务消息的实现,使用切面拦截减少对业务代码的侵入;目前暂时不支持对多表关联操作日志记录,需要拓展;总结
本文以操作日志为题材讨论了操作日志的实现方案和可行性,并且都已经在功能上进行实现,其中使用aop方案也是大部分中小企业的首选实现方案,但是在一些金融领域以及erp相关系统,对操作日志记录明细要求极高,常见技术方案很难满足,即使能够满足也会带来一些代码强侵入以及性能问题,所以我们又讨论了基于binlog实现的方案,该方案虽然比对aop来说增强了技术的复杂性,但是对于有一定技术积累的团队来说不算什么难事,并且该方案我们都实现了上线,并且解决了代码层面上的侵入,属于跨语言级别的,相信对读者还是有一定的启发。
原网址: 访问
创建于: 2020-12-10 11:45:47
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
java windows火焰图_mob64ca12ec8020的技术博客_51CTO博客 - 在windows下不可行,不知道作者是怎样搞的 监听SpringBoot 服务启动成功事件并打印信息_监听springboot启动完毕-CSDN博客 SpringBoot中就绪探针和存活探针_management.endpoint.health.probes.enabled-CSDN博客 u2u转换板 - 嘉立创EDA开源硬件平台 Spring Boot 项目的轻量级 HTTP 客户端 retrofit 框架,快来试试它!_Java精选-CSDN博客 手把手教你打造一套最牛的知识笔记管理系统! - 知乎 - 想法有重合-理论可参考 安宇雨 闲鱼 机械键盘 客制化 开贴记录 文本 linux 使用find命令查找包含某字符串的文件_beijihukk的博客-CSDN博客_find 查找字符串 ---- mac 也适用 安宇雨 打字音 记录集合 B站 bilibili 自行搭建 开坑 真正的客制化 安宇雨 黑苹果开坑 查找工具包maven pom 引用地 工具网站 Dantelis 介绍的玩轴入坑攻略 --- 关于轴的一些说法 --- 非官方 ---- 心得而已 --- 长期开坑更新 [本人问题][新开坑位]关于自动化测试的工具与平台应用 机械键盘 开团 网站记录 -- 能做一个收集的程序就好了 不过现在没时间 -- 信息大多是在群里发的 - 你要让垃圾佬 都去一个地方看难度也是很大的 精神支柱 [超级前台]sprinbboot maven superdesk-app 记录 [信息有用] [环境准备] [基本完成] [sebp/elk] 给已创建的Docker容器增加新的端口映射 - qq_30599553的博客 - CSDN博客 [正在研究] Elasticsearch, Logstash, Kibana (ELK) Docker image documentation elasticsearch centos 安装记录 及 启动手记 正式服务器 39 elasticsearch 问题合集 不断更新 6.1.1 | 6.5.1 两个版本 博客程序 - 测试 - bug记录 等等问题 laravel的启动过程解析 - lpfuture - 博客园 OAuth2 Server PHP 用 Laravel 搭建带 OAuth2 验证的 RESTful 服务 | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区 利用Laravel 搭建oauth2 API接口 附 Unauthenticated 解决办法 - 煮茶的博客 - SegmentFault 思否 使用 OAuth2-Server-php 搭建 OAuth2 Server - 午时的海 - 博客园 基于PHP构建OAuth 2.0 服务端 认证平台 - Endv - 博客园 Laravel 的 Artisan 命令行工具 Laravel 的文件系统和云存储功能集成 浅谈Chromium中的设计模式--终--Observer模式 浅谈Chromium中的设计模式--二--pre/post和Delegate模式 浅谈Chromium中的设计模式--一--Chromium中模块分层和进程模型 DeepMind 4 Hacking Yourself README.md update 20211011
Laravel China 简书 知乎 博客园 CSDN博客 开源中国 Go Further Ryan是菜鸟 | LNMP技术栈笔记 云栖社区-阿里云 Netflix技术博客 Techie Delight Linkedin技术博客 Dropbox技术博客 Facebook技术博客 淘宝中间件团队 美团技术博客 360技术博客 古巷博客 - 一个专注于分享的不正常博客 软件测试知识传播 - 测试窝 有赞技术团队 阮一峰 语雀 静觅丨崔庆才的个人博客 软件测试从业者综合能力提升 - isTester IBM Java 开发 使用开放 Java 生态系统开发现代应用程序 pengdai 一个强大的博主 HTML5资源教程 | 分享HTML5开发资源和开发教程 蘑菇博客 - 专注于技术分享的博客平台 个人博客-leapMie 流星007 CSDN博客 - 舍其小伙伴 稀土掘金 Go 技术论坛 | Golang / Go 语言中国知识社区
最新评论