设计思路
设计要点
缓存机制
采用本地缓存 + Redis 分布式通知实现字典数据的高效访问:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 管理后台 │────▶│ Redis │◀────│ 服务实例 A │
│ (修改字典) │ │ (通知通道) │ │ (本地缓存) │
└─────────────┘ └─────────────┘ └─────────────┘
│
│ 定时检查
▼
┌─────────────┐
│ 服务实例 B │
│ (本地缓存) │
└─────────────┘- 本地缓存:减少数据库查询,提高访问性能
- Redis 通知:字典变更时通知所有实例刷新
- 定时检查:定期检查字典变更,确保数据一致性
数据模型
字典类型 (MdmDict)
| 字段 | 说明 |
|---|---|
| dictType | 字典类型编码(唯一) |
| dictName | 字典类型名称 |
| description | 描述 |
| status | 状态(启用/禁用) |
| sort | 排序 |
字典项 (MdmDictItem)
| 字段 | 说明 |
|---|---|
| dictType | 字典类型编码 |
| dictKey | 字典项编码 |
| dictValue | 字典项值 |
| description | 描述 |
| status | 状态(启用/禁用) |
| sort | 排序 |
REST 接口设计
公共接口
/common/dict/list- 单字典查询(不分页)/common/dicts/list- 多字典查询(逗号分隔)
管理接口
/dict/list- 字典类型列表/dict/save- 保存字典类型/dict/delete- 删除字典类型/dict-item/list- 字典项列表/dict-item/save- 保存字典项/dict-item/delete- 删除字典项
缓存设计
缓存结构
DictCache {
// 本地缓存
Map<String, List<MdmDictItem>> dictCache; // key: dictType, value: items
// 缓存版本
Long version; // 缓存版本号
// 刷新机制
void clearCache(); // 手动刷新
void checkAndRefresh(); // 定时检查刷新
}缓存键设计
- 字典缓存键:
dict:{dictType} - 版本缓存键:
dict:version
缓存更新策略
- 实时更新:字典修改时,通过 Redis 发布通知
- 定时检查:定期检查版本号,发现变更自动刷新
- 手动刷新:支持手动触发缓存刷新
字典查询流程
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 客户端请求 │────▶│ 缓存检查 │────▶│ 缓存命中? │────▶│ 返回缓存数据 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
│ │
│ 否 │
▼ │
┌─────────────┐ ┌─────────────┐ │
│ 数据库查询 │────▶│ 更新缓存 │─┘
└─────────────┘ └─────────────┘多字典查询优化
- 批量查询:一次性查询多个字典类型
- 缓存合并:将多个字典结果合并返回
- 限制保护:限制单次查询的字典数量(默认最多 50 个)
最佳实践
字典命名规范
- 字典类型:使用大写字母和下划线,如
USER_STATUS - 字典项:使用有意义的编码,如
ACTIVE、INACTIVE
性能优化
- 合理使用缓存:优先使用缓存查询接口
- 批量查询:多字典查询使用
/common/dicts/list - 避免频繁刷新:字典变更后等待缓存自动刷新
- 监控缓存:监控缓存命中率和更新频率
安全考虑
- 权限控制:管理接口需要权限验证
- 输入验证:对字典类型和键进行验证
- SQL 注入防护:使用参数化查询