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