为什么这个错误发生 #
retention_lease_invalid_retaining_sequence_number_exception 表示尝试更新保留租约时,新的保留序列号小于现有租约的序列号。保留租约用于确保软删除的文档不会被过早清理。
这个错误可能由以下原因引起:
- 序列号递减:尝试用更小的序列号更新租约
- 旧副本请求:来自旧副本的恢复请求
- 时序混乱:操作的时序混乱导致序列号不正确
- 并发操作冲突:并发操作导致序列号冲突
- 节点重启后:节点重启后使用旧的序列号
- 跨集群复制:跨集群复制时序列号不同步
- 分片恢复:分片恢复时序列号不匹配
如何修复这个错误 #
1. 查看现有租约 #
# 查看索引的保留租约信息
GET /<index>/_stats?filter_path=**.retention_leases
# 查看特定分片的租约
GET /<index>/_stats?level=shards&filter_path=**.retention_leases
2. 使用更大的序列号 #
// 确保使用大于当前序列号的值
// 在更新租约前先检查当前序列号
long currentSeqNo = getCurrentRetainingSequenceNumber(leaseId);
long newSeqNo = Math.max(currentSeqNo, proposedSeqNo);
renewRetentionLease(leaseId, newSeqNo, ...);
3. 检查操作顺序 #
# 确保操作的时序正确
# 检查操作日志
grep -i "retention.*lease\|sequence.*number" /path/to/easysearch/logs/easysearch.log | tail -100
4. 同步集群状态 #
# 确保集群状态同步
GET /_cluster/state?filter_path=**.retention_leases
# 等待集群稳定
GET /_cluster/health?wait_for_status=green&timeout=50s
5. 删除并重建租约 #
# 如果租约状态混乱,可能需要删除并重建
# 注意:这可能导致数据丢失
6. 重启节点 #
# 如果节点状态异常,重启可能清理状态
sudo systemctl restart easysearch
# 等待节点启动
GET /_cat/nodes?v
7. 检查跨集群复制 #
# 对于跨集群复制,确保序列号同步
# 查看复制统计
GET /_ccr/stats
8. 使用正确的序列号 #
// 获取当前最大的序列号
long maxSeqNo = getMaxSeqNo();
long newRetainingSeqNo = maxSeqNo + 1;
// 使用新序列号更新租约
retentionLeases.renew(leaseId, newRetainingSeqNo, ...);
9. 实现序列号检查 #
// 在更新租约前检查序列号
long existingSeqNo = getExistingRetainingSequenceNumber(leaseId);
if (proposedSeqNo < existingSeqNo) {
// 使用现有序列号而非提议的序列号
proposedSeqNo = existingSeqNo;
}
10. 查看错误日志 #
# 查看租约相关错误日志
grep -i "invalid.*retaining\|sequence.*number" /path/to/easysearch/logs/easysearch.log | tail -100
11. 等待分片恢复完成 #
# 如果分片正在恢复,等待恢复完成
GET /_cat/recovery?v&active_only=true
# 等待恢复完成后再更新租约
12. 验证分片状态 #
# 确保分片状态正常
GET /_cat/shards?v&h=index,shard,prirep,state
# 查看分片统计信息
GET /<index>/_stats?level=shards
13. 处理并发更新 #
// 使用乐观锁处理并发更新
// 或使用同步机制确保更新的原子性
synchronized (leaseLock) {
long currentSeqNo = getCurrentRetainingSequenceNumber(leaseId);
if (proposedSeqNo >= currentSeqNo) {
retentionLeases.renew(leaseId, proposedSeqNo, ...);
}
}
14. 增加序列号 #
// 如果序列号必须递增,使用增量的方式
long increment = 1000; // 或根据实际需求
long newSeqNo = ((currentSeqNo / increment) + 1) * increment;
15. 联系支持 #
# 如果问题持续存在,可能需要检查:
# - 集群配置
# - 节点版本兼容性
# - 数据完整性
预防措施 #
- 确保序列号单调递增
- 检查现有序列号再更新
- 处理并发更新冲突
- 监控租约状态
- 同步集群状态
- 使用正确的序列号生成策略
- 实现序列号验证
- 避免使用旧副本请求
- 监控跨集群复制状态
- 测试租约更新逻辑





