今天給你們帶來的討論主題是經過實戰經驗來對百億數據量下的多表數據查詢進行優化,俗話說的好,一切脫離業務的架構都是耍流氓,接下來我就整理一下今天早上微信羣裏石頭哥給你們分享的百億數據量多表查詢架構以及優化思路。因爲本文內容整理自微信羣,爬樓不易,整理更不易,若是有遺漏,歡迎你們在評論區留言。html
做者:依樂祝
原文地址:http://www.javashuo.com/article/p-dvtcfhqq-ee.htmlgit
這裏咱們先舉個簡單的例子,來個開胃菜,而後再引出今天的訪談主題。程序員
舉例:好比咱們的CzarCms系統權限系統設計中的兩張表:用戶表以及角色表,這兩張表有關聯關係。這時候若是我要取一萬個用戶的數據,而後用戶數據又須要關聯角色表來查詢對應的角色名稱,這時候你會怎麼作呢?github
按照以往咱們的經驗咱們會對大表進行儘量的拆分,能分表就分表。咱們在取數據的時候使用下join查詢便可實現。數據庫
但是,當咱們的系統變得足夠大的時候,假設咱們的用戶表有一百萬的用戶了,角色表也有近10萬的數據,這個時候咱們若是還繼續使用Join進行查詢的時候就會變得很是慢了!xcode
這時候咱們能夠改變下思路:就是先把一萬條用戶數據取出來,而後取全部角色id後再去重的組合,而後用一個查詢把全部的角色信息取出來,再在內存中進行相應的拼接處理。
這種思路勉強可以支撐。緩存
但是若是數據量變得愈來愈大,這時候咱們應該如何來進行處理呢?且看下面來自百億數據實操的經典訪談。服務器
這裏,石頭哥就以他們公司的實際狀況爲例來進行了相關的實例闡述:
咱們的主要表,都是幾億到幾十億行,一個join不當心就能夠弄死數據庫,
並且天天1億包裹在路上,產生3億多掃描數據
數據存儲最少T+1,保存完整的一個月,也就是30到60天
數據量90到180億
這裏面,最多見的就是省,市,區,網點,人員,這5個字段
好久之前,咱們只有三五百萬業務量的時候,你們都是join五次
後來爲了省事,用了10個字段,提早把名稱寫進去
再後來,發現虧大了
多花了好多空間,而且join不必定是隻須要名稱字段
因而,進入了新時代,全部數據表都有那基本的5個字段,不準join
查詢出來數據後,在內存中再關聯省,市,區,網點,人員等信息
地區5萬行,網點3萬行,人員100萬,所有提早加載到內存,加起來不到100M
咱們小部門有100臺服務器,絕大部分用到這些基礎數據
不只僅上百億的掃描表,其它業務表,幾乎都會帶有這些字段,因此,緩存基礎數據,不吃虧微信
能夠分享一下大家的緩存方案嗎?
這個就不用了吧,我以爲不少大佬關於緩存的文章就寫得很是好!
我這裏只補充一些量化的數字:內存速度是Redis速度100倍,Redis緩存速度是數據庫至少10倍。
10萬之內數據量必須緩存在進程內,100萬~1億數據緩存在Redis,10萬~100萬能夠上下商量,超高查詢量(好比天天10億次)時放內存。
不少文章真的寫得挺好的,就是少了點經驗數據支撐,讀者搞不清楚何時該用這個,何時該用那個。架構
吉吉:如下場景:假設緩存了地區,好比查詢人員檔案信息列表是1萬行 之前是關聯查詢 如今緩存地區不能關聯查詢 只能查出一萬條而後循環拼接地區顯示 ,由於一萬行顯示自己這場景就不可能,因此增長翻頁 一頁顯示20行 徹底不會性能問題 這樣作對嗎 求教?
答:是的,查詢一頁20行,理論上要去匹配20次地區,可是地區數據少,省市區才四五千行,省市區加上鄉鎮街道也不過5萬行,能夠全量緩存到內存。
吉吉:明白 謝謝 只是舉例 這種思路真的很正確 咱們老是從技術考慮所有場景卻不考慮產品自己根本不能一勞永逸的搞。
真是太牛逼了!感謝分享
答:這麼Low的辦法,你們均可以想獲得,只是可能缺乏一個遇到這個數據量的機會罷了,這是我們.net的際遇,遇到問題能夠見招拆招.
你說的緩存到進程內,那多個進程內數據怎麼保持一致?
答:不保持一致,由於進程級緩存,能夠定時更新的,咱們方案是默認10秒異步更新緩存,而後也能夠按照添刪改隨時更新。
數據怎麼進行存儲呢?
答:內存字典進行存儲,最經常使用的就是並行字典 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+)