solr主從複製的原理
master的工作
對於ReplicationHandler的複製功能來說,核心的問題確定是在一個時間點要複製哪些檔案,這就用上了lucene的IndexDeletionPolicy的特性。
lucene在初始化時,會呼叫IndexDeletionPolicy.onInit(List commits)方法;
lucene在commit(觸發的時機也可以是optimize、close,solr在commit時實際上就是close了indexwriter)時,會呼叫IndexDeletionPolicy.onInit(List commits)。
IndexCommit物件中儲存了該次提交關聯的檔案列表等資訊,這使得solr中的複製過程中,slave可以從master得到檔案列表後跟本地檔案做比較,跳過不變的檔案,下載新檔案,並刪除無用的檔案。
IndexDeletionPolicy的兩個針對commits的函式,會對當前存在的commits列表做些處理,比如lucene預設的KeepOnlyLastCommitDeletionPolicy會只保留最新的IndexCommit,對那些過時的IndexCommit執行delete操作以將無用的檔案刪掉。
solr中,SolrDeletionPolicy預設也是保留最新一個IndexCommit,但可以設定maxCommitAge、maxCommitsToKeep、maxOptimizedCommitsToKeep來保留更多的IndexCommit。但solr真正使用的IndexDeletionPolicy實現是IndexDeletionPolicyWrapper,它是SolrDeletionPolicy的wrap。
在slave從master複製檔案的過程中,要保證當前正在複製的IndexCommit點不能被刪除,這就用到了IndexDeletionPolicyWrapper中的void setReserveDuration(Long indexVersion, long reserveTime)方法,該方法會在master向slave響應indexversion、filelist命令前、以及每向slave傳送5M的索引檔案內容時呼叫,而預設的reserveTime時間是10s,如果慢速網路傳輸5M資料需要10秒以上,就需要調整該值了。
ReplicationHandler複製檔案沒有采用rsync,而是使用http,它在讀一個檔案內容傳輸到slave時,預設是按照1M大小分段輸出內容到slave(http chunked?),並且預設是對每段內容做了checksum,保證傳輸的內容的正確性。上面提到的setReserveDuration點,主要就是它在packetsWritten % 5 == 0次數後觸發一次修改。
ReplicationHandler還可以備份索引檔案。由於lucene的索引檔案只是追加新檔案而不會修改已有檔案,所以只要針對一個IndexCommit點做備份,其過程還是很簡單的。
slave的工作
slave啟動時會建立SnapPuller物件,SnapPuller會啟動一個執行緒定時的(pollInterval間隔)從master複製資料(fetchLatestIndex方法)。對於一次複製過程,slave和master互動處理細節如下:
1、slave首先向master詢問最新的索引版本號(indexversion命令),slave檢查得到的latestVersion、latestGeneration有效後,和本地的IndexCommit的getVersion()、getGeneration()比較,如果不相等,則需要往下進行,否則等待下一次排程。
2、slave向master請求之前得到的indexversion下的檔案列表(filelist命令,包括索引檔案和可選的配置檔案)。如果檔案列表為空,則返回等待下一次排程。否則,就需要檢查哪些檔案需要被下載過來。這裡做的判斷有:1)如果本地的commit.getGeneration() >= latestGeneration,說明本地索引檔案被破壞(比如對slave不小心提交了修改索引的命令),需要完全將master的檔案複製過來。2)逐個檢查檔案列表中的檔案是否在本地存在,不存在就下載下來。
3、對於下載檔案內容,對應命令是filecontent。下載的檔案顯然需要放到臨時目錄中,這個臨時目錄和已有的索引目錄(預設名字index)在同一資料目錄下,只是命名為index.<時間戳>。下載完畢後,copy資料有兩種情況:
1)如果是完全下載,則不需要將臨時目錄中的檔案copy到已有目錄中,而是修改資料目錄中的index.properties,標識索引目錄為新生成的臨時目錄,而舊索引目錄並不會被刪除,可以手工刪掉,當然,通常是不應該出現slave的Generation大於master的異常情況。
2)通常就是把臨時索引目錄的檔案copy到舊索引目錄,copy時要把segments_N放到最後copy,避免copy中途出現異常造成資料被毀。
4、當新索引和可選的配置檔案copy完畢之後,slave會對solrcore的UpdateHandler做commit操作,這會close掉indexwriter並強制重啟新的indexsearcher提供服務。同時,如果solrcore的UpdateHandler是DirectUpdateHandler2(不應該不是),會強制呼叫handler.forceOpenWriter()來刪除舊的無用的索引檔案,並呼叫replicationHandler.refreshCommitpoint()來更新slave的indexCommitPoint。
5、如果索引複製失敗,slave會向資料目錄下的replication.properties輸出複製失敗的資訊。
對於ReplicationHandler的複製功能來說,核心的問題確定是在一個時間點要複製哪些檔案,這就用上了lucene的IndexDeletionPolicy的特性。
lucene在初始化時,會呼叫IndexDeletionPolicy.onInit(List commits)方法;
lucene在commit(觸發的時機也可以是optimize、close,solr在commit時實際上就是close了indexwriter)時,會呼叫IndexDeletionPolicy.onInit(List commits)。
IndexCommit物件中儲存了該次提交關聯的檔案列表等資訊,這使得solr中的複製過程中,slave可以從master得到檔案列表後跟本地檔案做比較,跳過不變的檔案,下載新檔案,並刪除無用的檔案。
IndexDeletionPolicy的兩個針對commits的函式,會對當前存在的commits列表做些處理,比如lucene預設的KeepOnlyLastCommitDeletionPolicy會只保留最新的IndexCommit,對那些過時的IndexCommit執行delete操作以將無用的檔案刪掉。
solr中,SolrDeletionPolicy預設也是保留最新一個IndexCommit,但可以設定maxCommitAge、maxCommitsToKeep、maxOptimizedCommitsToKeep來保留更多的IndexCommit。但solr真正使用的IndexDeletionPolicy實現是IndexDeletionPolicyWrapper,它是SolrDeletionPolicy的wrap。
在slave從master複製檔案的過程中,要保證當前正在複製的IndexCommit點不能被刪除,這就用到了IndexDeletionPolicyWrapper中的void setReserveDuration(Long indexVersion, long reserveTime)方法,該方法會在master向slave響應indexversion、filelist命令前、以及每向slave傳送5M的索引檔案內容時呼叫,而預設的reserveTime時間是10s,如果慢速網路傳輸5M資料需要10秒以上,就需要調整該值了。
ReplicationHandler複製檔案沒有采用rsync,而是使用http,它在讀一個檔案內容傳輸到slave時,預設是按照1M大小分段輸出內容到slave(http chunked?),並且預設是對每段內容做了checksum,保證傳輸的內容的正確性。上面提到的setReserveDuration點,主要就是它在packetsWritten % 5 == 0次數後觸發一次修改。
ReplicationHandler還可以備份索引檔案。由於lucene的索引檔案只是追加新檔案而不會修改已有檔案,所以只要針對一個IndexCommit點做備份,其過程還是很簡單的。
slave的工作
slave啟動時會建立SnapPuller物件,SnapPuller會啟動一個執行緒定時的(pollInterval間隔)從master複製資料(fetchLatestIndex方法)。對於一次複製過程,slave和master互動處理細節如下:
1、slave首先向master詢問最新的索引版本號(indexversion命令),slave檢查得到的latestVersion、latestGeneration有效後,和本地的IndexCommit的getVersion()、getGeneration()比較,如果不相等,則需要往下進行,否則等待下一次排程。
2、slave向master請求之前得到的indexversion下的檔案列表(filelist命令,包括索引檔案和可選的配置檔案)。如果檔案列表為空,則返回等待下一次排程。否則,就需要檢查哪些檔案需要被下載過來。這裡做的判斷有:1)如果本地的commit.getGeneration() >= latestGeneration,說明本地索引檔案被破壞(比如對slave不小心提交了修改索引的命令),需要完全將master的檔案複製過來。2)逐個檢查檔案列表中的檔案是否在本地存在,不存在就下載下來。
3、對於下載檔案內容,對應命令是filecontent。下載的檔案顯然需要放到臨時目錄中,這個臨時目錄和已有的索引目錄(預設名字index)在同一資料目錄下,只是命名為index.<時間戳>。下載完畢後,copy資料有兩種情況:
1)如果是完全下載,則不需要將臨時目錄中的檔案copy到已有目錄中,而是修改資料目錄中的index.properties,標識索引目錄為新生成的臨時目錄,而舊索引目錄並不會被刪除,可以手工刪掉,當然,通常是不應該出現slave的Generation大於master的異常情況。
2)通常就是把臨時索引目錄的檔案copy到舊索引目錄,copy時要把segments_N放到最後copy,避免copy中途出現異常造成資料被毀。
4、當新索引和可選的配置檔案copy完畢之後,slave會對solrcore的UpdateHandler做commit操作,這會close掉indexwriter並強制重啟新的indexsearcher提供服務。同時,如果solrcore的UpdateHandler是DirectUpdateHandler2(不應該不是),會強制呼叫handler.forceOpenWriter()來刪除舊的無用的索引檔案,並呼叫replicationHandler.refreshCommitpoint()來更新slave的indexCommitPoint。
5、如果索引複製失敗,slave會向資料目錄下的replication.properties輸出複製失敗的資訊。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15498/viewspace-2150090/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Redis 主從複製原理Redis
- MySQL主從複製原理MySql
- redis的主從複製的原理Redis
- 主從複製是啥或者主從複製的原理是什麼?
- Redis主從複製原理剖析Redis
- mysql的主從複製 原理講解MySql
- MySQL 主從複製的原理和配置MySql
- Redis 主從複製技術原理Redis
- Mysql主從複製原理及搭建MySql
- MySQL 主從複製原理不再難MySql
- MySQL(13)---MYSQL主從複製原理MySql
- 詳談Redis主從複製原理Redis
- Redis主從複製原理總結Redis
- mysql replication /mysql 主從複製原理MySql
- mysql主從複製原理及配置MySql
- 深入詳解Redis 主從複製的原理!Redis
- 深入 Redis 主從複製的原理詳解Redis
- 深入瞭解MySQL主從複製的原理MySql
- MySQL主從複製與主主複製MySql
- MySQL的主從複製與MySQL的主主複製MySql
- Redis replication主從複製原理及配置Redis
- 深入挖崛:mysql主從複製原理MySql
- mysql 5.7 主從複製搭建及原理MySql
- 主從複製面試之作用和原理面試
- MySQL的主從複製、半同步複製、主主複製詳解MySql
- MySQL主從複製、半同步複製和主主複製MySql
- mysql5.7主從複製,主主複製MySql
- MySQL主從複製、半同步複製和主主複製概述MySql
- 主從複製
- redis 深入理解redis 主從複製原理Redis
- 配置mysql5.5主從複製、半同步複製、主主複製MySql
- mysql複製--主從複製配置MySql
- MySQL的主從複製MySql
- Windows 環境下,MySQL 的主從複製和主主複製WindowsMySql
- windows環境下,Mysql的主從複製和主主複製WindowsMySql
- 主從複製、雙主複製及半同步複製、以及基於SSL的複製
- MySQL全面瓦解27:主從複製(原理 + 實踐)MySql
- 透過原始碼分析RocketMQ主從複製原理原始碼MQ