這是這個系列的最後一篇了,實在沒精力寫了,本來還想寫一下hbck的,這個東西很常用,當hbase的meta表出現錯誤的時候,它能夠幫助我們進行修複,無奈看到3000多行的代碼時,退卻了,原諒我這點自私的想法吧。
這裡我們知道,在打開這些scanner之後,就對他們進行了一下seek操作,它們就已經調整到最佳位置了。
我們看看keyvalueheap的構造函數裡面去看看吧。
它内部有一個叫heap的priorityqueue<keyvaluescanner>隊列,它會對所有的scanner進行排序,排序的比較器是kvscannercomparator, 然後current又調用了pollrealkv通過比較獲得目前的scanner,後面會講。
那好,我們直接進去kvscannercomparator看看它的compare方法就能知道怎麼回事了。
額,從上面代碼看得出來,把left和right各取出一個kv來進行比較,如果一樣就比較sequenceid,sequenceid越大說明這個檔案越新,傳回-1,在升序的情況下,這個scanner就跑到前面去了。
這樣就實作了heap裡面拿出來的第一個就是最小的kv的最新版。
在繼續将之前,我們看一下在keyvalue是怎麼被調用的,這樣我們好理清思路。
接着看populateresult方法。
我們對keyvalueheap的使用,就是先peek,然後再next,我們接下來就按這個順序看吧。
先從peek取出來一個,peek就是從heap隊列取出來的current的scanner取出來的目前的keyvalue。
然後我們看next方法。
1、通過currentasinternal.next繼續擷取kv,它是隻針對通過通過檢查的目前行的剩下的keyvalue,這個過程在之前那篇文章講過了。
2、如果後面沒有值了,就關閉這個scanner。
3、然後還有,就把這個scanner放回heap上,等待下一次調用。
4、使用pollrealkv再去一個新的scanner出來。
鑒于它每次都要比較的情況,如果一個列族下的hfile比較多的話,它的比較次數也會增大,會影響查詢效率,查詢時間和hfile的數量成線性關系。
另外補充點内容,是前面寫scan的時候拉下的:
由于寫入同一個rowkey相關的keyvalue的時候時間戳在前的先寫入,查詢的時候又需要總是讀該rowkey最新的keyvalue,是以在查詢的時候會先seek到該rowkey的時間戳最大的位置,具體查的時候,不斷的向前seekbefore,直到這個rowkey的keyvalue全部查完位置,然後再向前定位到一個rowkey的位置。
<b>簡而言之:</b>
不同rowkey的向前查,從rowkey小的查到rowkey大的;查相同rowkey的向後查,從最新的時間戳到查到最久的時間戳。
<b>總結:</b>
這就把如何查詢出來下一個keyvalue的過程講完了,它的peek方法、next方法、比較的方法,希望對大家有幫助,這個系列的文章到此也就結束了,下個目标是跟随超哥學習spark源碼,感謝廣大讀者的支援,覺得我寫得好的,可以關注一下我的部落格,謝謝!