--- title: "保留租约未找到异常 (retention_lease_not_found_exception) 错误排查与解决" date: 2026-01-03 lastmod: 2026-01-03 description: "retention_lease_not_found_exception 表示尝试操作不存在的保留租约,需要验证租约 ID 或创建新租约。" tags: ["保留租约", "软删除"] summary: "为什么这个错误发生 # retention_lease_not_found_exception 表示尝试操作一个不存在的保留租约。保留租约用于确保软删除的文档不会被过早清理。 这个错误可能由以下原因引起: 租约已被删除:租约已被删除但操作仍尝试访问 租约 ID 错误:使用了错误的租约 ID 分片恢复后:分片恢复后租约信息丢失 节点重启:节点重启后租约状态未持久化 租约过期:租约已过期被自动清理 跨集群复制:跨集群复制时租约 ID 不匹配 快照恢复:从快照恢复时租约不存在 并发删除:并发操作导致租约被删除 如何修复这个错误 # 1. 查看现有租约 # # 查看索引的保留租约信息 GET /<index>/_stats?filter_path=**.retention_leases # 查看特定分片的租约 GET /<index>/_stats?level=shards&filter_path=**.retention_leases 2. 验证租约 ID # # 确保使用正确的租约 ID # 查看所有租约的 ID GET /<index>/_stats?filter_path=**.retention_leases.**.id 3. 创建新租约 # // 如果租约不存在,创建新租约 if (!retentionLeases.contains(leaseId)) { retentionLeases.add(leaseId, retainingSequenceNumber, ...); } else { // 更新现有租约 retentionLeases.renew(leaseId, retainingSequenceNumber, ...); } 4." --- ## 为什么这个错误发生 `retention_lease_not_found_exception` 表示尝试操作一个不存在的保留租约。保留租约用于确保软删除的文档不会被过早清理。 这个错误可能由以下原因引起: 1. **租约已被删除**:租约已被删除但操作仍尝试访问 2. **租约 ID 错误**:使用了错误的租约 ID 3. **分片恢复后**:分片恢复后租约信息丢失 4. **节点重启**:节点重启后租约状态未持久化 5. **租约过期**:租约已过期被自动清理 6. **跨集群复制**:跨集群复制时租约 ID 不匹配 7. **快照恢复**:从快照恢复时租约不存在 8. **并发删除**:并发操作导致租约被删除 ## 如何修复这个错误 ### 1. 查看现有租约 ```bash # 查看索引的保留租约信息 GET //_stats?filter_path=**.retention_leases # 查看特定分片的租约 GET //_stats?level=shards&filter_path=**.retention_leases ``` ### 2. 验证租约 ID ```bash # 确保使用正确的租约 ID # 查看所有租约的 ID GET //_stats?filter_path=**.retention_leases.**.id ``` ### 3. 创建新租约 ```java // 如果租约不存在,创建新租约 if (!retentionLeases.contains(leaseId)) { retentionLeases.add(leaseId, retainingSequenceNumber, ...); } else { // 更新现有租约 retentionLeases.renew(leaseId, retainingSequenceNumber, ...); } ``` ### 4. 重新创建租约 ```bash # 如果租约丢失,可以重新创建 # 注意:序列号可能需要重新计算 ``` ### 5. 检查分片状态 ```bash # 确保分片状态正常 GET /_cat/shards?v&h=index,shard,prirep,state # 查看分片统计信息 GET //_stats?level=shards ``` ### 6. 重启节点 ```bash # 如果租约状态异常,重启可能恢复持久化的租约 sudo systemctl restart easysearch # 等待节点启动 GET /_cat/nodes?v ``` ### 7. 从快照恢复 ```bash # 如果租约丢失,从快照恢复可能包含租约信息 POST /_snapshot///_restore { "indices": "", "include_global_state": false } ``` ### 8. 检查错误日志 ```bash # 查看租约相关错误日志 grep -i "retention.*lease\|lease.*not.*found" /path/to/easysearch/logs/easysearch.log | tail -100 ``` ### 9. 验证集群状态 ```bash # 确保集群状态一致 GET /_cluster/state?filter_path=**.retention_leases # 等待集群稳定 GET /_cluster/health?wait_for_status=green&timeout=50s ``` ### 10. 实现幂等操作 ```java // 在客户端实现幂等操作 // 如果租约不存在则创建,如果存在则更新 try { retentionLeases.renew(leaseId, ...); } catch (RetentionLeaseNotFoundException e) { // 租约不存在,创建新租约 retentionLeases.add(leaseId, ...); } ``` ### 11. 检查租约持久化 ```bash # 确保租约信息被正确持久化 # 检查事务日志 ls -la /path/to/easysearch/data/nodes/0/indices//0/translog/ ``` ### 12. 处理过期租约 ```bash # 租约可能已过期被清理 # 检查租约的过期时间配置 ``` ### 13. 重建租约 ```bash # 如果无法恢复,需要重建租约 // 获取当前最大序列号 long maxSeqNo = getMaxSeqNo(); // 重新创建租约 retentionLeases.add(leaseId, maxSeqNo + 1, ...); ``` ### 14. 检查跨集群复制配置 ```bash # 对于跨集群复制,确保租约配置正确 GET /_ccr/stats ``` ### 15. 等待分片恢复 ```bash # 如果分片正在恢复,等待恢复完成 GET /_cat/recovery?v&active_only=true # 恢复完成后租约信息应该可用 ``` ### 预防措施 - 验证租约是否存在再操作 - 实现幂等操作 - 确保租约正确持久化 - 监控租约状态 - 配置合适的租约过期时间 - 使用正确的租约 ID - 定期检查租约完整性 - 监控跨集群复制状态 - 测试租约创建和更新逻辑 - 文档化租约管理流程