今天給大家帶來的討論主題是透過實戰經驗來對百億資料量下的多表資料查詢進行最佳化,俗話說的好,一切脫離業務的架構都是耍流氓,接下來我就整理一下今天早上微信群裡石頭哥給大家分享的百億資料量多表查詢架構以及最佳化思路。由於本文內容整理自微信群,爬樓不易,整理更不易,如果有遺漏,歡迎大家在評論區留言。
舉例:比如我們的CzarCms系統許可權系統設計中的兩張表:使用者表以及角色表,這兩張表有關聯關係。這時候如果我要取一萬個使用者的資料,然後使用者資料又需要關聯角色表來查詢對應的角色名稱,這時候你會怎麼做呢?
按照以往我們的經驗我們會對大表進行盡可能的拆分,能分表就分表。我們在取資料的時候使用下join查詢即可實現。
可是,當我們的系統變得足夠大的時候,假設我們的使用者表有一百萬的使用者了,角色表也有近10萬的資料,這個時候我們如果還繼續使用Join進行查詢的時候就會變得非常慢了!
這時候我們可以改變下思路:就是先把一萬條使用者資料取出來,然後取所有角色id後再去重的組合,然後用一個查詢把所有的角色資訊取出來,再在記憶體中進行相應的拼接處理。這種思路勉強能夠支撐。
可是如果資料量變得越來越大,這時候我們應該如何來進行處理呢?且看下麵來自百億資料實操的經典訪談。
場景介紹
這裡,石頭哥就以他們公司的實際情況為例來進行了相關的實體闡述:
我們的主要表,都是幾億到幾十億行,一個join不小心就可以弄死資料庫,
而且每天1億包裹在路上,產生3億多掃描資料
資料儲存最少T+1,儲存完整的一個月,也就是30到60天
資料量90到180億
這裡面,最常見的就是省,市,區,網點,人員,這5個欄位
很久以前,我們只有三五百萬業務量的時候,大家都是join五次
後來為了省事,用了10個欄位,提前把名稱寫進去
再後來,發現虧大了
多花了好多空間,並且join不一定是隻需要名稱欄位
於是,進入了新時代,所有資料表都有那基本的5個欄位,不許join
查詢出來資料後,在記憶體中再關聯省,市,區,網點,人員等資訊
地區5萬行,網點3萬行,人員100萬,全部提前載入到記憶體,加起來不到100M
我們小部門有100臺伺服器,絕大部分用到這些基礎資料
不僅僅上百億的掃描表,其它業務表,幾乎都會帶有這些欄位,所以,快取基礎資料,不吃虧
互動環節
1. 多大的資料量,才不能用join?
答:一般來說,從表100萬以內,我們都建議記憶體快取,10萬以內必須用行程內快取,沒得商量,記憶體中進行關聯即可。
2. 我們刪資料只能一條條刪。不允許批刪除,這個怎麼辦?
答:你們DBA可以辭退了,這麼簡單的事情都不會。
大資料分析的時候,每個月幾個億資料,一條條刪,刪到何年何月啊,當然是整個分割槽幹掉啦
3. 可以分享一下你們的快取方案嗎?
這個就不用了吧,我覺得很多大佬關於快取的文章就寫得非常好!
我這裡只補充一些量化的數字:記憶體速度是Redis速度100倍,Redis快取速度是資料庫至少10倍。
10萬以內資料量必須快取在行程內,100萬~1億資料快取在Redis,10萬~100萬可以上下商量,超高查詢量(比如每天10億次)時放記憶體。
很多文章真的寫得挺好的,就是少了點經驗資料支撐,讀者搞不清楚什麼時候該用這個,什麼時候該用那個。
4. 吉吉:以下場景:假設快取了地區,比如查詢人員檔案資訊串列是1萬行 以前是關聯查詢 現在快取地區不能關聯查詢 只能查出一萬條然後迴圈拼接地區顯示 ,因為一萬行顯示本身這場景就不可能,所以增加翻頁 一頁顯示20行 完全不會效能問題 這樣做對嗎 求教?
答:是的,查詢一頁20行,理論上要去匹配20次地區,但是地區資料少,省市區才四五千行,省市區加上鄉鎮街道也不過5萬行,可以全量快取到記憶體。
吉吉:明白 謝謝 只是舉例 這種思路真的很正確 我們總是從技術考慮全部場景卻不考慮產品本身根本不能一勞永逸的搞。
5. 真是太牛逼了!感謝分享
答:這麼Low的辦法,大家都可以想得到,只是可能缺少一個遇到這個資料量的機會罷了,這是咱們.net的際遇,遇到問題可以見招拆招.
6. 你說的快取到行程內,那多個行程內資料怎麼保持一致?
答:不保持一致,因為行程級快取,可以定時更新的,我們方案是預設10秒非同步更新快取,然後也可以按照添刪改隨時更新。
7. 我的記憶體資料以哪個為準?如果我機器是負載均衡,那麼幾個副本記憶體不一樣啊!
答:以本機為準,沒關係,每臺伺服器上都有一份快取。快取10萬使用者資訊,一共也就10M左右記憶體,你還在意?
8. 資料怎麼進行儲存呢?
答:記憶體字典進行儲存,最常用的就是並行字典 ConcurrentDictionary。
9. 假設你說的人員資料,那就必然存在 某一時刻 A行程10000人,B行程10002人,可能十秒可能八秒,但你們體量這麼大,這個問題不需要處理嗎
答:沒錯,的確存在這樣的問題,我們公司有100萬人員,但是全公司都知道,新加一個帳號,往往要兩三天才能在100多個內部系統全部生效,甚至新簽約一家網點,也要兩三天以後,各個系統才會認它,等你有那個體量的時候,就可以接受更長的不一致時間,我們在淘寶開店,釋出商品,有時候釋出成功了,跳轉到詳情頁卻是看不到的,等幾秒就好了。
另外,
我再說一句噁心一點的情況,大家別拍磚啊,在百億級資料量之下,就算我算錯個幾百幾千,那又怎麼樣???又怎麼樣??
對內,我會嚴格要求部門人員,務必追求準確;
對外,我會反覆提醒部門人員,我們提供的資料精度,最高99.99%,你要敢浪費大量時間在0.01%上,我就敢給你績效C
不用太死板嘛,把整體工作搞定,讓系統穩定工作,那才是咱們的主要工作
使用者有萬分之一的機會看到不正確的資料,只要再掃清一次能夠正確,就一定不是bug
萬分之一看到不正確的資料,並且只是萬分之一的偏差而已
由此換取的好處是,我們再也不用擔心各種該死的“資料一致性。
1
有想進一步瞭解石頭哥的可以這篇文章《[論一個程式員的自我修養-從一張圖片說起](https://www.cnblogs.com/yilezhu/p/10249547.html)》
最後為石頭哥的XCode打個廣告:
NewLife.XCode是一個有10多年曆史的開源資料中介軟體,支援nfx/netstandard,由新生命團隊(2002~2019)開發完成並維護至今,以下簡稱XCode。
xcode在2018年已經完成對大資料場景的特殊最佳化改造,2019年的標的是是針對分散式資料場景的最佳化。
最近石頭哥也在為XCode編寫系列教程:
整個系列教程會大量結合示例程式碼和執行日誌來進行深入分析,蘊含多年開發經驗於其中,代表作有百億級大資料實時計算專案。
開源地址:[https://github.com/NewLifeX/X ](https://github.com/NewLifeX/X)(求star, 670+)