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