一、项目背景
快驴生鲜作为B2B生鲜供应链平台,需要记录用户操作日志以满足审计、安全分析和业务追踪需求。本开发记录详细描述了用户操作日志系统的设计与实现过程。
二、需求分析
核心需求
1. 记录所有关键用户操作(登录、下单、修改订单、权限变更等)
2. 支持日志查询与导出
3. 满足合规性要求(如等保2.0)
4. 对系统性能影响最小化
功能需求
- 自动记录操作时间、操作者、操作类型、操作对象、操作结果
- 支持敏感数据脱敏
- 日志分级存储(热数据、温数据、冷数据)
- 日志审计与分析接口
三、系统设计
架构设计
```
用户操作
↓
AOP切面拦截
↓
日志处理器(LogProcessor)
↓
日志存储(ES+MySQL+OSS)
↓
日志查询与分析服务
```
技术选型
- 日志收集:Spring AOP + 自定义注解
- 存储方案:
- 实时查询:Elasticsearch
- 结构化存储:MySQL(分表策略)
- 长期归档:阿里云OSS
- 异步处理:RabbitMQ消息队列
- 脱敏处理:自定义脱敏算法
四、核心实现
1. 日志注解定义
```java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationLog {
String operation() default "";
String businessType() default "";
boolean isSaveRequestData() default true;
boolean isSaveResponseData() default false;
DataScopeType dataScope() default DataScopeType.NONE;
}
```
2. AOP切面实现
```java
@Aspect
@Component
public class OperationLogAspect {
@Autowired
private LogService logService;
@Around("@annotation(operationLog)")
public Object around(ProceedingJoinPoint point, OperationLog operationLog) throws Throwable {
// 1. 获取操作信息
String operation = operationLog.operation();
// 2. 记录请求开始时间
long startTime = System.currentTimeMillis();
try {
// 3. 执行原方法
Object result = point.proceed();
// 4. 构建日志对象
SysOperLog operLog = new SysOperLog();
// 设置操作人、时间、IP等基础信息
// ...
// 5. 异步保存日志
logService.saveAsync(operLog);
return result;
} catch (Exception e) {
// 异常处理
// ...
throw e;
}
}
}
```
3. 异步日志处理服务
```java
@Service
public class LogServiceImpl implements LogService {
@Autowired
private RabbitTemplate rabbitTemplate;
@Override
public void saveAsync(SysOperLog log) {
// 发送到消息队列
rabbitTemplate.convertAndSend("log.exchange", "log.save", log);
}
@RabbitListener(queues = "log.save.queue")
public void handleLogMessage(SysOperLog log) {
// 1. 敏感数据脱敏
desensitize(log);
// 2. 存入ES(热数据)
esLogRepository.save(convertToESLog(log));
// 3. 存入MySQL(温数据)
if (shouldSaveToMySQL(log)) {
mysqlLogMapper.insert(log);
}
// 4. 归档策略(冷数据)
archiveLogIfNeeded(log);
}
}
```
4. 日志查询接口
```java
@RestController
@RequestMapping("/monitor/operlog")
public class OperLogController {
@GetMapping("/list")
public TableDataInfo list(SysOperLog operLog) {
startPage();
List list = operLogService.selectOperLogList(operLog);
return getDataTable(list);
}
@GetMapping("/export")
public void export(HttpServletResponse response, SysOperLog operLog) {
List list = operLogService.selectOperLogList(operLog);
ExcelUtil util = new ExcelUtil<>(SysOperLog.class);
util.exportExcel(response, list, "操作日志");
}
}
```
五、关键技术点
1. 性能优化方案
- 采用异步非阻塞方式记录日志
- 对高频操作采用批量写入
- 实现日志分级存储策略
- 使用本地缓存减少数据库访问
2. 敏感数据脱敏
```java
public class DesensitizationUtils {
public static String desensitizePhone(String phone) {
if (StringUtils.isEmpty(phone) || phone.length() < 7) {
return phone;
}
return phone.substring(0, 3) + "" + phone.substring(7);
}
// 其他脱敏方法...
}
```
3. 日志归档策略
```java
public class LogArchiveService {
@Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行
public void archiveLogs() {
// 1. 查询30天前的日志
Date thirtyDaysAgo = DateUtils.addDays(new Date(), -30);
// 2. 从MySQL迁移到OSS
List oldLogs = logMapper.selectBeforeDate(thirtyDaysAgo);
ossService.uploadLogs(oldLogs);
// 3. 从MySQL删除已归档日志
logMapper.deleteBeforeDate(thirtyDaysAgo);
}
}
```
六、测试与验证
测试用例
1. 正常操作日志记录
2. 异常操作日志记录
3. 高并发场景下的日志性能
4. 敏感数据脱敏验证
5. 日志查询与导出功能
性能测试结果
- 单机QPS:5000+(日志记录)
- 查询响应时间:<200ms(90%请求)
- 存储空间节省:30%(通过脱敏和压缩)
七、部署与运维
部署方案
- 日志服务独立部署,与主业务解耦
- 采用容器化部署,支持横向扩展
- 监控指标:
- 日志记录延迟
- 存储空间使用率
- 查询响应时间
运维接口
```
GET /api/log/stats 获取日志系统统计信息
POST /api/log/reindex 触发ES重新索引
GET /api/log/config 获取日志配置
```
八、后续优化方向
1. 引入日志采样机制,减少非关键操作日志量
2. 实现基于机器学习的异常操作检测
3. 增加多维度日志分析看板
4. 支持跨系统日志关联分析
九、总结
本日志系统实现了快驴生鲜业务操作的全链路追踪,通过分级存储、异步处理和脱敏技术,在保证系统性能的同时满足了合规性要求。系统上线后有效支持了运营分析和安全审计工作。