Elasticsearch 通過多種機制確保數據在分布式環境中的一致性,但由于其分布式和近實時(Near Real-Time, NRT)的特性,它提供的是最終一致性(Eventual Consistency),而非強一致性。以下是核心機制和策略:
一、寫入一致性控制(Write Consistency)
在寫入操作(如索引/更新文檔)時,可通過參數 consistency
控制最小副本數要求:
PUT my-index/_doc/1?consistency=quorum
{"field": "value"
}
可選值:
quorum
(默認):多數分片副本可用(公式:int( (primary + number_of_replicas) / 2 ) + 1
)。all
:所有分片副本必須可用。one
:僅主分片可用即可。
👉 作用:防止網絡分區時數據寫入不一致。
二、主分片機制(Primary Shard)
- 所有寫操作僅由主分片處理,再同步到副本分片。
- 寫操作順序性:主分片按收到請求的順序執行寫入,確保操作序列一致。
三、樂觀并發控制(Optimistic Concurrency Control)
使用 _version
或 if_seq_no/if_primary_term
避免并發沖突:
PUT my-index/_doc/1?if_seq_no=5&if_primary_term=1
{"field": "new_value"
}
👉 如果版本號不匹配,操作失敗(返回 409 Conflict
),由客戶端決定重試或合并數據。
四、事務日志(Translog, Write-Ahead Log)
- 寫入操作首先存入內存緩沖區,同時追加到磁盤事務日志(Translog)。
- 故障恢復:節點重啟時,通過重放 Translog 恢復未刷新的數據。
- 刷新(Refresh):默認每秒將內存緩沖區數據生成新的 Lucene 段(可搜索,但尚未持久化)。
- 刷盤(Flush):定期(或 Translog 達到閾值)將 Lucene 數據持久化到磁盤,并清空 Translog。
📌 關鍵點:Translog 確保即使宕機,已確認的寫入操作不會丟失。
五、副本同步(Replication)
- 主分片寫入成功后,并行將操作轉發到副本分片。
- 同步要求:
- 主分片等待所有副本分片的成功響應(可通過
wait_for_active_shards
參數調整)。 - 若副本失敗,主分片通知主節點將副本標記為失效,并在其他節點重建副本。
- 主分片等待所有副本分片的成功響應(可通過
六、讀一致性(Read Consistency)
- 默認近實時(NRT):寫入后約 1 秒(可調整 refresh_interval)才可被搜索到。
- 指定刷新:可通過
?refresh=true
強制立即刷新,但影響性能。 - 搜索參數控制:
preference
:控制查詢路由(如_local
優先本地分片)。wait_for_active_shards
:搜索時等待指定數量分片可用。
七、腦裂防護(Split-Brain Protection)
通過配置 discovery.zen.minimum_master_nodes
(舊版)或 cluster.initial_master_nodes
(新版)避免網絡分區時出現多主節點,導致數據分裂。
八、最終一致性的體現場景
場景 | 表現 |
---|---|
寫入后立即查詢 | 可能查不到(因未刷新)/ 可能查到主分片但副本未同步 |
副本分片故障期間寫入 | 數據寫入主分片,副本恢復后自動同步 |
節點宕機恢復 | 通過 Translog 恢復未持久化數據,副本從主分片重新同步 |
九、生產環境建議
- 合理設置副本數:至少
1
(允許單節點故障)。 - 調整刷新間隔:對實時性要求高的場景可縮短
refresh_interval
(代價:資源消耗增加)。 - 關鍵寫入操作:使用
?refresh=wait_for
或手動刷新。 - 監控分片狀態:通過
GET _cluster/health
關注active_shards_percent_as_number
。
// 創建索引時優化配置示例
PUT my-index
{"settings": {"number_of_replicas": 2,"refresh_interval": "500ms", // 降低刷新延遲"translog.durability": "request" // 每次請求后刷寫Translog(更強持久化)}
}
💡 權衡提示:更高的一致性保證往往以犧牲寫入吞吐量和延遲為代價,需根據業務需求調整參數。
通過上述機制,Elasticsearch 在分布式、高并發的場景下,平衡了性能與數據一致性的需求。