feat: 新增数据库持久化模块(Persistence),实现 Cursor + Retry 双层架构
## 核心功能 ### 1. 数据库持久化支持 - 新增完整的 Persistence 模块 (api/persistence/) - 支持三种持久化策略: * StrategyDBOnly - 仅落库,不存证 * StrategyDBAndTrustlog - 既落库又存证(推荐) * StrategyTrustlogOnly - 仅存证,不落库 - 支持多数据库:PostgreSQL, MySQL, SQLite ### 2. Cursor + Retry 双层架构 - CursorWorker:第一道防线,快速发现新记录并尝试存证 * 增量扫描 operation 表(基于时间戳游标) * 默认 10 秒扫描间隔,批量处理 100 条 * 成功更新状态,失败转入重试队列 - RetryWorker:第二道防线,处理失败记录 * 指数退避重试(1m → 2m → 4m → 8m → 16m) * 默认最多重试 5 次 * 超限自动标记为死信 ### 3. 数据库表设计 - operation 表:存储操作记录,支持可空 IP 字段 - trustlog_cursor 表:Key-Value 模式,支持多游标 - trustlog_retry 表:重试队列,支持指数退避 ### 4. 异步最终一致性 - 应用调用立即返回(仅落库) - CursorWorker 异步扫描并存证 - RetryWorker 保障失败重试 - 完整的监控和死信处理机制 ## 修改文件 ### 核心代码(11个文件) - api/persistence/cursor_worker.go - Cursor 工作器(新增) - api/persistence/repository.go - 数据仓储层(新增) - api/persistence/schema.go - 数据库 Schema(新增) - api/persistence/strategy.go - 策略管理器(新增) - api/persistence/client.go - 客户端封装(新增) - api/persistence/retry_worker.go - Retry 工作器(新增) - api/persistence/config.go - 配置管理(新增) ### 修复内部包引用(5个文件) - api/adapter/publisher.go - 修复 internal 包引用 - api/adapter/subscriber.go - 修复 internal 包引用 - api/model/envelope.go - 修复 internal 包引用 - api/model/operation.go - 修复 internal 包引用 - api/model/record.go - 修复 internal 包引用 ### 单元测试(8个文件) - api/persistence/*_test.go - 完整的单元测试 - 测试覆盖率:28.5% - 测试通过率:49/49 (100%) ### SQL 脚本(4个文件) - api/persistence/sql/postgresql.sql - PostgreSQL 建表脚本 - api/persistence/sql/mysql.sql - MySQL 建表脚本 - api/persistence/sql/sqlite.sql - SQLite 建表脚本 - api/persistence/sql/test_data.sql - 测试数据 ### 文档(2个文件) - README.md - 更新主文档,新增 Persistence 使用指南 - api/persistence/README.md - 完整的 Persistence 文档 - api/persistence/sql/README.md - SQL 脚本说明 ## 技术亮点 1. **充分利用 Cursor 游标表** - 作为任务发现队列,非简单的位置记录 - Key-Value 模式,支持多游标并发扫描 - 时间戳天然有序,增量扫描高效 2. **双层保障机制** - Cursor:正常流程,快速处理 - Retry:异常流程,可靠重试 - 职责分离,监控清晰 3. **可空 IP 字段支持** - ClientIP 和 ServerIP 使用 *string 类型 - 支持 NULL 值,符合数据库最佳实践 - 使用 sql.NullString 正确处理 4. **完整的监控支持** - 未存证记录数监控 - Cursor 延迟监控 - 重试队列长度监控 - 死信队列监控 ## 测试结果 - ✅ 单元测试:49/49 通过 (100%) - ✅ 代码覆盖率:28.5% - ✅ 编译状态:无错误 - ✅ 支持数据库:PostgreSQL, MySQL, SQLite ## Breaking Changes 无破坏性变更。Persistence 模块作为可选功能,不影响现有代码。 ## 版本信息 - 版本:v2.1.0 - Go 版本要求:1.21+ - 更新日期:2025-12-23
This commit is contained in:
361
api/persistence/sql/README.md
Normal file
361
api/persistence/sql/README.md
Normal file
@@ -0,0 +1,361 @@
|
||||
# Trustlog 数据库建表脚本
|
||||
|
||||
本目录包含 go-trustlog 数据库持久化模块的建表 SQL 脚本。
|
||||
|
||||
---
|
||||
|
||||
## 📁 文件列表
|
||||
|
||||
| 文件 | 数据库 | 说明 |
|
||||
|------|--------|------|
|
||||
| `postgresql.sql` | PostgreSQL 12+ | PostgreSQL 数据库建表脚本 |
|
||||
| `mysql.sql` | MySQL 8.0+ / MariaDB 10+ | MySQL 数据库建表脚本 |
|
||||
| `sqlite.sql` | SQLite 3+ | SQLite 数据库建表脚本 |
|
||||
| `test_data.sql` | 通用 | 测试数据插入脚本 |
|
||||
|
||||
---
|
||||
|
||||
## 📊 表结构说明
|
||||
|
||||
### 1. operation 表
|
||||
|
||||
操作记录表,用于存储所有的操作记录。
|
||||
|
||||
**关键字段**:
|
||||
- `op_id` - 操作ID(主键)
|
||||
- `client_ip` - **客户端IP(可空,仅落库,不存证)**
|
||||
- `server_ip` - **服务端IP(可空,仅落库,不存证)**
|
||||
- `trustlog_status` - **存证状态(NOT_TRUSTLOGGED / TRUSTLOGGED)**
|
||||
- `timestamp` - 操作时间戳
|
||||
|
||||
**索引**:
|
||||
- `idx_operation_timestamp` - 时间戳索引
|
||||
- `idx_operation_status` - 存证状态索引
|
||||
- `idx_operation_doid` - DOID 索引
|
||||
|
||||
### 2. trustlog_cursor 表
|
||||
|
||||
游标表,用于跟踪处理进度,支持断点续传。
|
||||
|
||||
**关键字段**:
|
||||
- `id` - 游标ID(固定为1)
|
||||
- `last_processed_id` - 最后处理的操作ID
|
||||
- `last_processed_at` - 最后处理时间
|
||||
|
||||
**特性**:
|
||||
- 自动初始化一条记录(id=1)
|
||||
- 用于实现最终一致性
|
||||
|
||||
### 3. trustlog_retry 表
|
||||
|
||||
重试表,用于管理失败的存证操作。
|
||||
|
||||
**关键字段**:
|
||||
- `op_id` - 操作ID(主键)
|
||||
- `retry_count` - 重试次数
|
||||
- `retry_status` - 重试状态(PENDING / RETRYING / DEAD_LETTER)
|
||||
- `next_retry_at` - 下次重试时间(指数退避)
|
||||
- `error_message` - 错误信息
|
||||
|
||||
**索引**:
|
||||
- `idx_retry_status` - 重试状态索引
|
||||
- `idx_retry_next_retry_at` - 下次重试时间索引
|
||||
|
||||
---
|
||||
|
||||
## 🚀 使用方法
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
```bash
|
||||
# 方式1: 使用 psql 命令
|
||||
psql -U username -d database_name -f postgresql.sql
|
||||
|
||||
# 方式2: 使用管道
|
||||
psql -U username -d database_name < postgresql.sql
|
||||
|
||||
# 方式3: 在 psql 中执行
|
||||
psql -U username -d database_name
|
||||
\i postgresql.sql
|
||||
```
|
||||
|
||||
### MySQL
|
||||
|
||||
```bash
|
||||
# 方式1: 使用 mysql 命令
|
||||
mysql -u username -p database_name < mysql.sql
|
||||
|
||||
# 方式2: 在 mysql 中执行
|
||||
mysql -u username -p
|
||||
USE database_name;
|
||||
SOURCE mysql.sql;
|
||||
```
|
||||
|
||||
### SQLite
|
||||
|
||||
```bash
|
||||
# 方式1: 使用 sqlite3 命令
|
||||
sqlite3 trustlog.db < sqlite.sql
|
||||
|
||||
# 方式2: 在 sqlite3 中执行
|
||||
sqlite3 trustlog.db
|
||||
.read sqlite.sql
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 验证安装
|
||||
|
||||
每个 SQL 脚本末尾都包含验证查询,执行后可以检查:
|
||||
|
||||
### PostgreSQL
|
||||
```sql
|
||||
-- 查询所有表
|
||||
SELECT tablename FROM pg_tables WHERE schemaname = 'public'
|
||||
AND tablename IN ('operation', 'trustlog_cursor', 'trustlog_retry');
|
||||
```
|
||||
|
||||
### MySQL
|
||||
```sql
|
||||
-- 查询所有表
|
||||
SHOW TABLES LIKE 'operation%';
|
||||
SHOW TABLES LIKE 'trustlog_%';
|
||||
```
|
||||
|
||||
### SQLite
|
||||
```sql
|
||||
-- 查询所有表
|
||||
SELECT name FROM sqlite_master
|
||||
WHERE type='table'
|
||||
AND name IN ('operation', 'trustlog_cursor', 'trustlog_retry');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 字段说明
|
||||
|
||||
### operation 表新增字段
|
||||
|
||||
#### client_ip 和 server_ip
|
||||
|
||||
**特性**:
|
||||
- 类型: VARCHAR(32) / TEXT (根据数据库而定)
|
||||
- 可空: YES
|
||||
- 默认值: NULL
|
||||
|
||||
**用途**:
|
||||
- 记录客户端和服务端的 IP 地址
|
||||
- **仅用于数据库持久化**
|
||||
- **不参与存证哈希计算**
|
||||
- **不会被序列化到 CBOR 格式**
|
||||
|
||||
**示例**:
|
||||
```sql
|
||||
-- 插入 NULL 值(默认)
|
||||
INSERT INTO operation (..., client_ip, server_ip, ...)
|
||||
VALUES (..., NULL, NULL, ...);
|
||||
|
||||
-- 插入 IP 值
|
||||
INSERT INTO operation (..., client_ip, server_ip, ...)
|
||||
VALUES (..., '192.168.1.100', '10.0.0.50', ...);
|
||||
```
|
||||
|
||||
#### trustlog_status
|
||||
|
||||
**特性**:
|
||||
- 类型: VARCHAR(32) / TEXT
|
||||
- 可空: YES
|
||||
- 可选值:
|
||||
- `NOT_TRUSTLOGGED` - 未存证
|
||||
- `TRUSTLOGGED` - 已存证
|
||||
|
||||
**用途**:
|
||||
- 标记操作记录的存证状态
|
||||
- 用于查询未存证的记录
|
||||
- 支持最终一致性机制
|
||||
|
||||
---
|
||||
|
||||
## 🔄 常用查询
|
||||
|
||||
### 1. 查询未存证的操作
|
||||
|
||||
```sql
|
||||
SELECT * FROM operation
|
||||
WHERE trustlog_status = 'NOT_TRUSTLOGGED'
|
||||
ORDER BY timestamp ASC
|
||||
LIMIT 100;
|
||||
```
|
||||
|
||||
### 2. 查询待重试的操作
|
||||
|
||||
```sql
|
||||
SELECT * FROM trustlog_retry
|
||||
WHERE retry_status IN ('PENDING', 'RETRYING')
|
||||
AND next_retry_at <= NOW()
|
||||
ORDER BY next_retry_at ASC
|
||||
LIMIT 100;
|
||||
```
|
||||
|
||||
### 3. 查询死信记录
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
o.op_id,
|
||||
o.doid,
|
||||
r.retry_count,
|
||||
r.error_message,
|
||||
r.created_at
|
||||
FROM operation o
|
||||
JOIN trustlog_retry r ON o.op_id = r.op_id
|
||||
WHERE r.retry_status = 'DEAD_LETTER'
|
||||
ORDER BY r.created_at DESC;
|
||||
```
|
||||
|
||||
### 4. 按 IP 查询操作
|
||||
|
||||
```sql
|
||||
-- 查询特定客户端IP的操作
|
||||
SELECT * FROM operation
|
||||
WHERE client_ip = '192.168.1.100'
|
||||
ORDER BY timestamp DESC;
|
||||
|
||||
-- 查询未设置IP的操作
|
||||
SELECT * FROM operation
|
||||
WHERE client_ip IS NULL
|
||||
ORDER BY timestamp DESC;
|
||||
```
|
||||
|
||||
### 5. 统计存证状态
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
trustlog_status,
|
||||
COUNT(*) as count
|
||||
FROM operation
|
||||
GROUP BY trustlog_status;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗑️ 清理脚本
|
||||
|
||||
### 删除所有表
|
||||
|
||||
```sql
|
||||
-- PostgreSQL / MySQL
|
||||
DROP TABLE IF EXISTS trustlog_retry;
|
||||
DROP TABLE IF EXISTS trustlog_cursor;
|
||||
DROP TABLE IF EXISTS operation;
|
||||
|
||||
-- SQLite
|
||||
DROP TABLE IF EXISTS trustlog_retry;
|
||||
DROP TABLE IF EXISTS trustlog_cursor;
|
||||
DROP TABLE IF EXISTS operation;
|
||||
```
|
||||
|
||||
### 清空数据(保留结构)
|
||||
|
||||
```sql
|
||||
-- 清空重试表
|
||||
DELETE FROM trustlog_retry;
|
||||
|
||||
-- 清空操作表
|
||||
DELETE FROM operation;
|
||||
|
||||
-- 重置游标表
|
||||
UPDATE trustlog_cursor SET
|
||||
last_processed_id = NULL,
|
||||
last_processed_at = NULL,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = 1;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 注意事项
|
||||
|
||||
### 1. 字符集和排序规则(MySQL)
|
||||
- 使用 `utf8mb4` 字符集
|
||||
- 使用 `utf8mb4_unicode_ci` 排序规则
|
||||
- 支持完整的 Unicode 字符
|
||||
|
||||
### 2. 索引长度(MySQL)
|
||||
- `doid` 字段使用前缀索引 `doid(255)`
|
||||
- 避免索引长度超过限制
|
||||
|
||||
### 3. 自增主键
|
||||
- PostgreSQL: `SERIAL`
|
||||
- MySQL: `AUTO_INCREMENT`
|
||||
- SQLite: `AUTOINCREMENT`
|
||||
|
||||
### 4. 时间类型
|
||||
- PostgreSQL: `TIMESTAMP`
|
||||
- MySQL: `DATETIME`
|
||||
- SQLite: `DATETIME` (存储为文本)
|
||||
|
||||
### 5. IP 字段长度
|
||||
- 当前长度: 32 字符
|
||||
- IPv4: 最长 15 字符 (`255.255.255.255`)
|
||||
- IPv4 with port: 最长 21 字符 (`255.255.255.255:65535`)
|
||||
- **IPv6: 最长 39 字符** - 如需支持完整 IPv6,建议扩展到 64 字符
|
||||
|
||||
---
|
||||
|
||||
## 🔧 扩展建议
|
||||
|
||||
### 1. 如果需要支持完整 IPv6
|
||||
|
||||
```sql
|
||||
-- 修改 client_ip 和 server_ip 字段长度
|
||||
ALTER TABLE operation MODIFY COLUMN client_ip VARCHAR(64);
|
||||
ALTER TABLE operation MODIFY COLUMN server_ip VARCHAR(64);
|
||||
```
|
||||
|
||||
### 2. 如果需要分区表(PostgreSQL)
|
||||
|
||||
```sql
|
||||
-- 按时间分区
|
||||
CREATE TABLE operation_partitioned (
|
||||
-- ... 字段定义 ...
|
||||
) PARTITION BY RANGE (timestamp);
|
||||
|
||||
CREATE TABLE operation_2024_01 PARTITION OF operation_partitioned
|
||||
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
|
||||
```
|
||||
|
||||
### 3. 如果需要添加审计字段
|
||||
|
||||
```sql
|
||||
-- 添加创建人和更新人
|
||||
ALTER TABLE operation ADD COLUMN created_by VARCHAR(64);
|
||||
ALTER TABLE operation ADD COLUMN updated_by VARCHAR(64);
|
||||
ALTER TABLE operation ADD COLUMN updated_at TIMESTAMP;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- [PERSISTENCE_QUICKSTART.md](../../PERSISTENCE_QUICKSTART.md) - 快速入门
|
||||
- [README.md](../README.md) - 详细技术文档
|
||||
- [IP_FIELDS_USAGE.md](../IP_FIELDS_USAGE.md) - IP 字段使用说明
|
||||
|
||||
---
|
||||
|
||||
## ✅ 检查清单
|
||||
|
||||
安装完成后,请检查:
|
||||
|
||||
- [ ] 所有3个表都已创建
|
||||
- [ ] 所有索引都已创建
|
||||
- [ ] trustlog_cursor 表有初始记录(id=1)
|
||||
- [ ] operation 表可以插入 NULL 的 IP 值
|
||||
- [ ] operation 表可以插入非 NULL 的 IP 值
|
||||
- [ ] 查询验证脚本能正常执行
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2025-12-23
|
||||
**版本**: v1.0.0
|
||||
|
||||
Reference in New Issue
Block a user