UUID5升级方案
建站
0 字 / 约 0 分钟
UUID5升级方案
问题背景
在项目运行过程中发现 UUID5 存在重复问题,具体表现为:
- 发现重复的 UUID5:
e78b7和b7a6f - 原因:5位十六进制字符的冲突概率在 400+ 文件的项目中已经不可忽视
- 影响:导致不同页面使用相同的 permalink,造成路由冲突
冲突概率分析
原始方案
- UUID长度:5位十六进制字符
- 可能组合:16^5 = 1,048,576 种
- 冲突概率:在 400+ 文件的项目中,根据生日悖论,冲突概率显著增加
升级方案
- UUID长度:6位十六进制字符
- 可能组合:16^6 = 16,777,216 种
- 冲突概率:降低到原来的 1/16
技术实现
1. 改进的 UUID 生成算法
javascript
// 生成UUID5的函数(改进版,降低重复概率)
function generateUuid5(filePath = '') {
const timestamp = Date.now().toString()
const random = Math.random().toString(36).substring(2)
const processId = process.pid.toString()
const fileInfo = filePath.replace(/\\/g, '/').replace(/\.md$/, '')
// 组合更多信息来降低重复概率
const combined = timestamp + random + processId + fileInfo
const hash = createHash('md5').update(combined).digest('hex')
// 增加到6位以进一步降低冲突概率
return hash.substring(0, 6)
}2. 关键改进点
增加输入信息
- 时间戳:
Date.now().toString()- 确保时间唯一性 - 随机数:
Math.random().toString(36).substring(2)- 增加随机性 - 进程ID:
process.pid.toString()- 避免多进程环境冲突 - 文件路径:
filePath- 确保不同文件生成不同 UUID
增加输出长度
- 从 5 位增加到 6 位十六进制字符
- 冲突概率降低 16 倍
更新正则表达式
javascript
// 检查当前permalink是否包含UUID5格式(5位或6位字符)
const uuid5Pattern = /\/[a-z0-9]{5,6}$/
const hasUuid5 = uuid5Pattern.test(currentPermalink)3. 调用方式更新
所有调用 generateUuid5() 的地方都需要传入文件路径:
javascript
// 更新前
const uuid = generateUuid5()
// 更新后
const uuid = generateUuid5(fileInfo.relativePath)实施步骤
1. 代码修改
- ✅ 更新
generateUuid5()函数 - ✅ 更新所有函数调用
- ✅ 更新正则表达式匹配规则
2. 重复问题修复
- ✅ 修复
docs/70.建站/52.本站主题/自动索引.md中的错误 permalink - ✅ 移除文档示例中的重复 frontmatter 块
3. 重新生成
- ✅ 运行 AutoFrontmatter 重新生成所有 permalink
- ✅ 验证无重复 UUID 存在
验证结果
升级前
bash
# 发现重复的 UUID5
Count Name Group
----- ---- -----
2 e78b7 {e78b7, e78b7}
2 b7a6f {b7a6f, b7a6f}升级后
bash
# 无重复 UUID 存在
# 输出为空,表示没有重复兼容性处理
向后兼容
- 正则表达式支持 5 位和 6 位 UUID 格式
- 现有 5 位 UUID 的 permalink 保持不变
- 新生成的 UUID 使用 6 位格式
迁移策略
- 已有 UUID 的 permalink 不强制更新
- 新文件或缺少 permalink 的文件使用新算法
- 前缀不匹配的 permalink 会被更新为新格式
性能影响
计算开销
- 增加文件路径处理:轻微
- 增加哈希计算输入:轻微
- 增加输出长度:无影响
存储开销
- 每个 permalink 增加 1 个字符
- 对整体存储影响可忽略
最佳实践
1. 定期检查
建议定期运行以下命令检查重复:
bash
Get-ChildItem -Path "docs" -Recurse -Filter "*.md" | Select-String "permalink:" | ForEach-Object { $_.Line -replace ".*permalink: /[^/]+/", "" } | Sort-Object | Group-Object | Where-Object { $_.Count -gt 1 }2. 监控日志
关注 AutoFrontmatter 运行时的日志输出,特别是指示重复的警告信息。
3. 测试验证
在添加大量新文件后,建议重新运行 AutoFrontmatter 并检查是否有新的重复。
总结
通过将 UUID5 从 5 位升级到 6 位,并结合文件路径、时间戳、随机数和进程ID等信息,成功解决了 permalink 重复问题。新方案在保持向后兼容的同时,大幅降低了冲突概率,提高了系统的稳定性和可靠性。
关键收益:
- ✅ 消除 UUID 重复问题
- ✅ 降低冲突概率 16 倍
- ✅ 保持向后兼容性
- ✅ 提高系统稳定性