ES里有一個叫做gateway的東西,今天抽空理一下,前面翻譯ES的一篇博文叫做“搜索引擎與時間機器”,既然里面談到了時間機器,就免不了需要穿越時空的的門咯,I guess,也許gateway這名字就是這么來的,其實在ES里面,gateway的主要職責是用來對數據進行長持久化(持久化了之后加上版本信息,不就可以自由的往還於過去未來之間了嗎?),另外,整個集群重啟之后可以通過gateway重新恢復數據。
由於ElasticSearch是專為分布式環境而設計的,所以怎么去對所有節點的索引信息進行持久化是個問題,除了索引信息之外,還有ClusterState(集群信息),mapping,索引碎片信息,以及transaction log等信息也是需要進行持久化的,0.11之后的版本新加了LocalGateway(並且是默認配置),加上之前的fs(使用共享文件系統)、hdfs(hadoop 分布式文件系統)、cloud(ec2之類的雲存儲),0.11之前默認的是None,也就是不進行持久化,這樣的話如果服務器都掛了,就會造成數據丟失,local gateway這種模式顧名思義就是節點各自保存其狀態,節點直接從本地存儲來恢復節點狀態和索引信息,localgateway有如下幾個選項:
gateway.recover_after_nodes: 1 (or gateway.recovery_after_master_nodes) gateway.recover_after_time: 5m (m分鍾、s秒) gateway.expected_nodes: 2
當你的節點出現故障或者集群重啟的時候,這些配置很重要,你應該盡量保證有了足夠多的節點來執行故障恢復,確保得到最終的集群狀態,可能存放最新版本的狀態信息的節點還未起來,否則可能會丟失數據。
至於索引碎片的恢復則只需用達到足夠恢復的數目即可,如果你沒有設置備份,或者剛好某個碎片偏偏都丟了,那估計只能是沒戲咯,
另外,在我的測試中,2台機器,其中一台網絡不穩定,經常斷開,(ip沖突造成),造成集群中的節點各種為戰,這里有一些參數可配:
discovery.zen.fd.connect_on_network_disconnect : true discovery.zen.initial_ping_timeout : 10s discovery.zen.fd.ping_interval : 2s discovery.zen.fd.ping_retries : 10
如果使用是共享文件系統的gateway,默認是每隔10s將數據異步的復制到共享的文件系統中(這是ES里一個叫gateway snapshot的概念),想想如果集群很大,共享文件系統就需要保存很大的數據量,並且維護以及設備本身成本都很高,而使用local方式則可以做到各個節點自治,確實很方便啊。
有關存儲
說了這么半天,還有一個問題就是es工作的存儲目錄,具體來說就是es服務的索引工作目錄,gateway只是做持久化和恢復,不會直接使用,所以還有一個工作目錄是用來查詢操作的,具體來說就是通過Store模塊來完成的(es的每個功能都是一個模塊,結構非常好),es的存儲設置是per index級別的,所以你可以為每個index指定它存儲的位置,既然持久化的工作已經完畢了,本地操作的索引一般只放在兩個地方:內存和本地文件系統,主要是性能上考慮的,如果內存很大,那就全部放內存咯,值得一提的是,在ES里,所有存放work目錄下(或內存)的東西假定能被丟失的和臨時性的,另外你有多個副本存放在不同的節點上,每個索引又拆成了多個碎片位於不同的節點上,假設一台節點上的數據丟了,那也只是整個索引少了其中的一個碎片的一個副本而已,並且es會馬上進行碎片的重新分配(allocate),確保數據的完整。
還有一個重要特點就是es可以直接使用jvmheap之外的內存。
下面是一個配置inex使用內存來進行存儲的例子(更多配置細節):
index : store: fs: memory: enabled: true
還有一個就是關於索引碎片數和副本數的配置問題,你不能夠對已經存在的索引修改碎片數,也就是有了數據之后就不能修改了,因為目前es只是簡單的哈希取模[hash(_id) MOD number_of_shards],如果以后支持一致性哈希,那就很好了,不過副本數目是可以隨時動態更改的,如果你要對全局進行設置,參照如下:
gateway: type: local index: gateawy: snapshot_interval: 30s number_of_shards: 3 number_of_replicas: 2 path: logs: /path/to/logs
新創建一個索引並設置:
PUT http://localhost:9200/myindex/
{ "index" : { "number_of_replicas" :3, "number_of_shards" :7 } }
動態設置索引副本數量:
PUT: http://localhost:9200/myindex/_settings
{ "index" : { "numberOfReplicas" :2 } }