做者:閒魚技術——長明算法
在內容社區中,內容標籤用來輔助說明內容,內容標籤對內容分發和理解具備重要做用,可以幫助內容社區將對的內容分發到對的人。目前閒魚會玩社區的標籤分爲分類和屬性標籤兩種,兩種標籤的用法不一樣,可是目前兩者都是存在於同一個標籤系統中,目前會有以下問題:markdown
•易出錯,靠人爲去辨別分類標和屬性標,不免會出錯,出現漏打,錯打分佈式
•難拓展,屬性和分類屬於不一樣的業務域,有各自獨有的特性,現狀沒法讓兩者獨立拓展工具
爲了解決以上問題,如今要將原標籤系統拆分爲分類系統和屬性系統,具體來講,會將屬性標從原標籤系統中拆分到屬性系統,而後將原標籤系統做爲新分類系統。整個過程,不只須要遷移底層數據,還須要將屬性服務從原標籤系統遷移到新屬性系統。阿里雲
以下圖所示,閒魚會玩社區對屬性標籤依賴很是之多,除了自身的業務系統以外,還有圖中標藍的算法、搜索、數據等也會依賴。遷移過程當中須要保證這些上層依賴不受影響。另外,業務方但願可以儘早啓用屬性系統,儘快提升打標效率。總結起來,遷移過程當中面臨了以下的挑戰。spa
•快,短期內遷移完成,儘早使用新屬性系統3d
•穩,依賴衆多,在遷移時須要保證屬性服務可用,不影響上層業務,用戶無感知code
•準,遷移最最最基本的要求就是要保證數據正確orm
咱們按照影響面從小到大的順序,制定了 1.底層存儲同步、2.建設隔離層、3.業務讀寫遷移、4.依賴遷移、5.啓用新屬性系統共五步。其中依賴是指搜索、算法和數據,這些依賴影響面較廣,遷移須要更加慎重,須要有己方業務遷移正確這個前提做爲保證。所以依賴遷移須要單獨列爲一部分,且放在己方業務遷移完成後進行。遷移中的每一步遷移須要保證上一步正確,且出現問題,每一步均可以回滾回上一個正確狀態。爲了保證數據的一致性,咱們全程都有數據校對服務。接口
整個遷移過程,咱們首先先從底層存儲開始同步,爲了保證原標籤系統和屬性系統中的屬性標籤相同。實現這個目標須要從兩方面作起,一方面是全量同步,就是將所有數據同步一遍。一方面是實時增量同步,一旦有新的屬性標籤被寫入原標籤系統中,那麼屬性系統中也要同步一份。這個套路比較固定。下面是咱們全量同步的數據處理過程。
其中同步任務咱們直接使用了 阿里雲 提供的 scheduleX 分佈式任務工具。全量同步過程當中要注意,控制同步速率、配置告警、作好異常記錄和完成進度記錄。控制同步速率是須要避免把依賴服務系統打掛,影響其餘正常業務。配置告警是爲了及時發現異常,及時排查。其中異常記錄是爲了排查問題的,必然要記錄的。完成進度記錄也是很是重要的,一旦出現問題,修復完了要繼續時,能夠直接從上次記錄的同步位點開始同步。
講完了全量同步,下面講一下實時增量拆分的過程,數據流過程以下圖所示。即一旦觸發了原標籤系統變動,會實時將屬性標的變化同步到屬性系統。
屏蔽遷移細節
作了存儲遷移,那麼如今屬性系統和原標籤系統中的屬性標相同了,下面能夠作業務讀遷移了。業務遷移,這是遷移過程當中工做量最大最複雜的地方,須要梳理清楚依賴不少。通過梳理髮現,多個應用多個業務場景都在使用原標籤系統。假如逐個遷移改造,一方面重複性工做比較多,須要重複驗證的功能點多,另外一方面,遷移細節沒法統一管理,一旦有問題,須要逐個應用修改。因此在作業務遷移以前,咱們作了一件事情,就是將散落在多個應用的讀寫原標籤系統的操做都收歸到了一個 jar 包中,而後在該 jar 中統一控制讀寫切換。jar 包至關於一個隔離層,隔離了上層業務和屬性標籤的存儲邏輯。這樣上層業務系統沒必要關心屬性標是從原標籤系統讀取的抑或是從屬性系統中讀取的,只管從隔離層提供的方法中讀取便可。有了隔離層統一管理,能夠同時統一遷移,減小沒必要要的重複工做。具體的變化從 a 圖變換到 b 圖。
接口適配
因爲分類系統和屬性系統兩種標籤的業務語義和功能不一樣,內容中臺對這兩個系統的領域建模也不一樣,對應的數據服務接口能力也不一樣,爲了讓上層業務對此無感知,咱們保持原服務接口不變,在隔離層作了對於分類系統和屬性系統兩個系統的適配。
讀遷移
前置工做作完以後,咱們開始具體的讀遷移。讀遷移是最好作的,能夠先按照比例切流,逐步放量從屬性系統中讀取屬性標,一旦發現有問題,那麼直接將流量切回讀原標籤系統 ,沒有問題,就直至全量。
寫遷移
寫遷移是很難一刀切的,一方面,即便是通過了梳理,仍是可能會有遺漏的地方。另外一方面,還有部分依賴方的寫入(好比內容中臺的標籤寫入)不在咱們這邊,暫時沒法遷移。假如己方業務的寫遷移了,那麼己方業務只會寫到屬性系統 ,而沒遷移的依賴方只會寫到原標籤系統。這會形成原標籤系統和屬性系統的屬性標數據不一致。這致使兩方面的問題,一方面,影響依賴方讀,依賴方讀的仍是原標籤系統,讀取不到屬性系統上的屬性標。另外一方面,兩方不一致的話,若是屬性系統出現問題,那麼寫沒法即時回滾到原標籤系統。
所以在遷移過程當中,還須要保證原標籤系統和屬性系統上的屬性標時刻是相同的,在存儲拆分中,已經有了 原標籤系統-> 屬性系統的同步鏈路,如今還須要將只寫入屬性系統的屬性標同步回原標籤系統。
那麼如今有 原標籤系統->屬性系統 和 屬性系統 -> 原標籤系統 兩條同步鏈路。若是不作任何控制的話,明顯會出現同步死循環原標籤系統->屬性系統->原標籤系統。解決這種雙向同步死循環的通常辦法是加標誌,用標誌標識此次數據變動是源自哪一方,當發現本身的更新消息迴流到了本身這裏,那麼就再也不更新,這樣就切斷了更新的死循環。
當己方業務可以保證無誤的時候,那麼能夠作依賴遷移了。依賴方通常爲算法、搜索和數據等。鏈路分爲實時鏈路和離線鏈路。對於實時鏈路,這部分工做由於有了前面的業務讀遷移,能夠複用;對於離線鏈路,提供好離線數據表給到相關依賴方,讓他們按時遷移完成便可。
依賴方也遷移完成後,通過一段時間的觀察,沒有問題,即可以使用新的屬性標籤系統來打標了。啓用新系統打標的以後,便再也不須要 原標籤系統->屬性系統 的同步鏈路了,能夠中止。後續再觀察一段時間後,確認使用屬性系統無問題後,便再也不有將讀寫切回原標籤系統的必要了,能夠再切斷 屬性系統 -> 原標籤系統 的同步鏈路,至此遷移完成。
在整個同步過程當中,還要有對帳任務來實時查看同步的數據是否正確。若是發現數據不正確,要及時找到緣由,修正,而後作好數據矯正。
本次遷移排除依賴方遷移所用時間外,共計兩週。
遷移過程當中屬性服務正常。零客訴輿情。
遷移後,數據零差別。
最後捋一下本次遷移中的經驗點
遷移過程當中,若是服務依賴衆多,能夠用隔離層來隔離依賴對遷移的感知。
雙寫,過程當中避免出現同步死循環,能夠經過給更新消息加標誌避免。