從宮廷劇看如何清洗資料
一、宮廷劇的消失
2019年1月30號,我看到了一個新聞。
大概內容是廣電總局要開始封殺宮廷劇了,衛視已經全面禁播了。
既然這樣,那網路上相關視訊網站也不遠了。
當時我在朋友圈釋出了一個狀態:好訊息 & 壞訊息。
中午才發完這個朋友圈,晚上就收到訊息,所有頁面都要下掉“宮廷”兩個字。
從此,世上再無“宮廷劇”了。
我所說的壞訊息有很多面。
由於我處於視訊行業,其中的一面就是這段時間有得忙了。
對於很多人來說,甚至晚上都睡不好覺了。
二、寫擴散與讀計算
對於一個視訊,往往需要給視訊打上一些標籤,比如偶像、宮廷、玄幻、都市、喜劇、武打、懸疑等等。
視訊的數量少則千萬,多則上億,如果每個視訊直接儲存對應的文字標籤,則存在一個寫擴散問題。
以宮廷為例,寫擴散的具體含義就是所有的宮廷劇,都會儲存“宮廷”這兩個文字。
突然有一天,我們要改名字了,那就需要將標籤是宮廷的視訊都找出來,然後改成新的名字(需要修改成千上萬的視訊)。
這個擴散是很嚴重的,稍微有點經驗的程式設計師都不會這樣設計系統。
面對這個問題,大家常見的解決方案是 ID 化。
具體來說就是預先將所有的標籤儲存在一個地方(字典表),並分配一個唯一的數字。
如果一個視訊要和這個標籤關聯起來,這個視訊儲存對應的數字即可。
這樣做後讀資料就麻煩一點,需要來計算轉換ID對應的含義。
具體是第一次只能通過視訊ID查出標籤ID,然後還需要通過標籤ID來查詢標籤對應的含義(字典表翻譯)。
當然,通過這樣一個小代價,我們就解決了上面的寫擴散問題。
再來修改標籤的含義時,我們只需要修改標籤表裡標籤ID對應的含義。
這樣只修改一個標籤字典表的一行資料,所有頁面的資料都可以瞬間生效了。
這個就對應上了一句名言:任何問題都可以通過加一層來解決。
三、讀計算與快取
上一小節中,我們看到可以把一些邏輯放在讀的時候再來計算,可以解決很多寫擴散問題。
於是越來越多的邏輯都提升到了讀服務上。
這個計算服務其實就是兩年前我寫的那篇文章《 每秒千萬每天萬億級別服務之誕生 》。
當然,經過兩年,這個服務的量級早已翻了很多倍。
目前已經到達每秒2億每天億億了。
這個服務當時主要解決兩個問題。
第一就是聚合眾多資料來源,第二就是讀時統一計算各種寫擴散的資料。
隨著訪問量越來越大,兩個問題引出了另外一個問題:撐不住了。
假設來了10萬每秒的量,資料來源那麼多,不是都可以撐得住這個量的;計算邏輯那麼多而且那麼重,也不是所有計算邏輯都計算的過來。
這就需要在計算服務之上加一個快取來抗量。
加了快取是解決了訪問量的問題,但也引入一個更大的問題:資料一致性。
作為一個資料系統,最終一致性是可以接受的,但是如果最終一致的時間太長那就不了接受了。
而儲存容量不變的話,資料的快取時間與命中率在一定範圍內是正相關的。
而命中率又和邏輯層以及資料來源息息相關,畢竟底層不能抗量。
面對日益增長的訪問量,資料一致性、儲存、命中率、透傳量這些關係變得更為複雜。
最後,通過一系列優化,初步緩解了快取問題,並寫下了一篇文章《 每秒千萬級別的量是重生還是煉獄? 》
通過這些優化,命中率得到了提高、核心資料的資料一致性得到了保障、透傳量也大大降低了。
解決資料一致性的關鍵就是通知,多做的工作只是通知帶來的問題,如資料一致性、通知量等問題。
就這樣,在讀計算之上加了一層快取,解決了面臨的新問題。
四、清洗全域性資料與區域性資料
上面可以看到,讀計算解決了寫擴散的問題,快取解決了計算量大的問題。
但是那些都是在正常情況下的一些流程,如果資料出現異常是怎麼辦呢?
之前曾遇到過底層資料全部異常的情況,還寫了一篇文章《 資料髒了怎麼辦 》。
總結來說,面對全域性資料異常,快取系統需要有重新整理全域性資料的能力。
而最優的答案就在上篇文章裡面,這個功能我當時就實現投入到生產系統中了。
這次底層字典表變更,屬於讀計算層的變更,在上層還有一層快取層。
讀計算邏輯變更,快取是無感知的,這就導致資料遲遲不能更新。
另外,上面的文章也提到,加了通知後,為了提高命中率,快取時間也變得很長很長。
字典表的變更+快取時間很長+無通知,這就導致這個變更對外遲遲不能生效。
而且這個只是一個Id的變更,並不是全域性變更,這裡導致全域性清理資料功能不起作用了。
為啥呢? 資料系統是一個三級批量系統(資料型別+資料id+欄位id),資料快取是按欄位維度儲存的。
資料型別接近上百個,id的量是上億級別,欄位是上千級別的,這樣相乘就是10億億的幾筆,這個資料量太多了。
對於全域性資料異常時,配置了洗資料功能以及頻率,慢慢洗就行了,最終所有資料都會重新整理。
而對於區域性資料異常時,這個功能就是牛刀殺雞了,另外也有點浪費。
當然,這個系統設計的時候,就支援每個欄位id單獨配置快取時間,這就使得可以做到對區域性資料來控制回源時間。
但是問題是回源時間並不能代替洗資料功能,因為我們不知道什麼時候可以把回源時間調整回來。
當然,這個時間也不是完全未知的。
假設我們的快取時間是一天時間,那至少要在一天後才能設定回來,不然就可能依舊讀到舊資料了。
讀到這裡,有心的朋友應該就猜到了,欄位維度也可以增加洗資料的能力。
這樣區域性洗資料就相當高效精確了,恩就是這樣,只是目前還沒有這個功能。
不過目前時間還算充足,走過期時間慢慢淘汰就行了。
如果真是緊急,調小快取時間就行了。
-EOF-
本文首發於公眾號:天空的程式碼世界,微訊號:tiankonguse-code。