

为什么基层平台的日志不能只当排障工具
万村乐数字乡村的功能清单里,日志统计那一栏写得很直白:访问日志和操作日志记录,责任追究到人,明确操作记录。做业务系统的人看到这句话,第一反应可能是接个日志框架就完事。真到村里跑起来会发现,这套日志承担的角色跟互联网产品完全不同。
举几个实际场景。村干部按积分规则给某一户加了 20 分家庭积分,过两个月这户人家来问凭什么是 20 分不是 30 分。三务公开发了一条财务信息,后来内容被改过,村民要看改之前是什么样。选举投票统计出来了,有人质疑票数。商城里商家审批了一笔退款,用户说没收到。这些都不是技术故障,是要拿日志当凭证的场景。所以留痕这块的设计目标,跟排障日志差别很大:可查、可证、不可悄悄改。
两类日志分开存
万村乐里访问日志和操作日志是分开记的,这个拆分很有必要。访问日志量大、价值低、留存期短;操作日志量小、价值高、留存期长。混在一张表里,清理策略没法定。
访问日志走异步批量落库,记的是谁在什么时候访问了哪个页面、来源终端、耗时。这类数据主要用于统计运营概况里的访问数,以及排查接口性能。保留 90 天,按天分区,过期直接 drop 分区。
操作日志记的是写操作,任何改变了数据状态的动作都要进来。表结构大致这样:
before_json 和 after_json 这两列争议比较大,有人觉得存全量快照太占空间。实测下来,一个村一年的操作日志在 30 万条上下,快照字段压缩后单条平均 1.2 KB,一年也就几百兆,MySQL 8.0.28 完全扛得住。相比之下,只存字段名和新值,回溯的时候经常拼不出当时的完整状态,反而更费事。
快照怎么采:别在业务代码里手写
让每个业务方法自己去写日志,写着写着一定会漏。万村乐 Java 版用的是 SpringBoot 2.5.4 加 MybatisPlus 3.5.1,比较省事的做法是切面加注解,把采集动作从业务里剥出来:
切面里在方法执行前按表达式取一次旧值,执行成功后再取一次新值,两份都序列化进日志。失败的请求也要记,只是 after_json 为空、加一个错误码字段。很多团队只记成功操作,结果有人反复尝试越权访问,日志里一片空白。

防篡改:哈希链比想象中简单
日志要当凭证用,就得能证明没被改过。上游数据库权限再严,运维手上总有账号。这里用的办法是给每条日志算一个链式哈希,把上一条的哈希当作本条的输入:
prevHash 按村庄维度各自维护一条链,存在 Redis 里,同时每天凌晨把当天的链尾哈希落一份到独立的存档表。校验的时候从某一天的链尾往回推,中间任何一条被改过,哈希就串不上。这套东西不复杂,Hutool 5.7.22 里的 DigestUtil 直接就有,加起来不到 50 行代码,但在需要出具凭证的场合很管用。
要注意哈希链只能证明日志本身没被改,证明不了写进来的内容是真的。所以采集环节必须可信,切面里取的快照要直接读数据库,不能读业务层缓存。
存储分层:热数据在库,冷数据挪走
万村乐支持私有化独立部署,客户的服务器配置差异很大,不能假设磁盘随便用。日志存储按时间分了三层。
近 3 个月的操作日志留在 MySQL 主库,按月做 RANGE 分区,走索引查询,支撑后台的日志检索页面。
3 个月到 3 年的挪到归档表,同样按月分区,查询走离线接口,不占业务库连接。Druid 1.2.8 那边给归档查询单独配一个小连接池,防止有人拉一次大范围日志把业务连接吃光。
3 年以上的导出成压缩文件,推到对象存储。万村乐的文件储存本来就支持对接本地、阿里云、腾讯云三种方式,日志归档复用同一套配置即可,客户选哪种存储,归档就落到哪儿。

敏感字段要在写入前处理
村里的数据敏感度不低。网格信息管理里有村民的身份证号、家庭成员关系、种养信息,帮扶救助模块还有收入情况。这些字段进日志快照的时候必须先脱敏,不然日志表反而成了泄露风险点。
处理规则按字段类型定死,序列化的时候统一走一遍:身份证号保留前 6 位和后 4 位,手机号保留前 3 位和后 4 位,银行卡号只留后 4 位,家庭住址截断到村组一级。金额、积分这类字段不脱敏,因为它们本身就是要核对的对象。
导出功能也要留痕。万村乐的村民管理支持批量导出或选择导出,土地信息也能批量导出,这类动作本身就是高风险操作,日志里要记清楚导出了多少条、筛选条件是什么、导出人是谁。只记一句执行了导出,出事的时候查不出范围。
检索页面别做成全表扫描
日志表大了以后,后台那个查询页面很容易把库拖垮。几条约束建议写死在代码里,不要交给使用者判断:时间范围必填且跨度不超过 31 天;不带任何条件的查询直接拒绝;分页深度限制在 100 页以内,需要更多数据走导出流程;按操作人、按业务对象这两种高频查法各自建好联合索引。
按业务对象回溯是使用率高的一种查法。村民来问家庭积分为什么是这个数,直接按 module 加 biz_id 把这户人家的全部变动拉出来,时间、操作人、加减分理由一条条摆着,比口头解释有用得多。万村乐的积分记录本身会统计所有村民积分变动记录,和操作日志两边对得上,解释起来才有底气。
收尾
审计日志这块投入产出比其实不错。整体改动集中在切面、存储分层、脱敏三处,业务代码基本不用动。跑了一段时间之后,明显的变化是村里扯皮的事少了,很多争议在后台点两下就能说清。对于承载政务公开、投票选举、积分奖惩这些职能的数字乡村平台来说,留痕做扎实,比事后补救省力太多。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。