關於高並發
來自專欄雜談1,317 人贊了文章
高並發其實挺容易的,當你明白了一萬並發的原理,然後擴展到百萬、千萬、億萬級很easy
要點有如下幾項:
1、垂直分層:DNS層、跨機房部署、LVS+Nginx負載均衡,vanish+共享存儲實現動靜分離,Nginx後掛載N台伺服器集群,伺服器集群後掛載微服務化、微服務後掛載資料庫分庫分表+消息隊列+任務調度,最後端掛載數據集群負責數據的統一歸檔+流計算+非同步批處理
2、水平分區:根據業務劃分業務線,每個業務線中設計分區鍵,根據userNo設計用戶隔離,根據IP地址設計地區隔離,根據用戶級別設計級別隔離,根據操作日期設計時間隔離,根據關鍵key進行hash散列,然後考慮一下分區的擴容、縮容、災備、監控
3、數據同步,跨機房跨集群的困難點在於數據同步,有三種做法:
3.1)不同步,任由各子集群在自己的業務範圍內運行
3.2)匯總集群,建立一個統一的數據匯總集群(如HadoopSparkKylin等),將數據匯總到統一的大數據集群中,再進行統計、匯總、運算等。缺點是會有時間差,短須5分鐘,長須一天以上
3.3)遠程數據同步,通過開源框架實現多個資料庫的同步,例如阿里的otter,底層為canal,模擬mysql的從庫,實現日誌解析並資料庫入庫,時間差較短,如果網路沒有太大問題,可在秒級完成數據同步。數據同步衝突演算法有兩種:單向迴環補救、時間交集補救。一般推薦使用單向迴環補救,即:如果發現資料庫A與資料庫B的同步時間差大於某個數值,則根據pk查詢最新記錄同步到資料庫中。而另一種演算法時間交集補救,是根據「時間交集」的定義,獲得雙方資料庫的「時間交叉的操作」清單,然後根據此清單執行單向迴環補救。此方法缺點為:a)開源版本中僅有單向迴環補救;b)只支持mysql->mysql同步或者mysql->oracle同步。
集齊以上三件,基本上百萬級並發就輕鬆搞定了。然後需要注意一些細節:
1)集群與集群之間要實現從入口開始的嚴格隔離,即DNS層->LVS層->Nginx層完全隔離
2)資料庫的鏈接數是重要資源,一個mysql資料庫可以提供1000鏈接,也就是說,按照50鏈接/每機器來計算,最多鏈接20個實例,硬上一下超不過30台。因此資料庫層的分庫分表一定要徹徹底底的分開。子集群之間不能互相鏈接資料庫。
3)一些關鍵業務可以在緩存中操作,建議採用redis緩存。而memcache死機後數據丟失,mongodb功能尚不完善。redis的安全機制一定要做好,千萬不能丟數據。緩存到資料庫的存儲可以採用計數形式,每隔N次操作存一次資料庫,可以線性降低資料庫壓力
4)資料庫只使用簡單的存取功能,所有業務功能在代碼層實現,DBA推薦的分區、分存儲、存儲過程等功能一般在數據倉庫中是有用的,而在實時計算系統中,千萬不要採用。否則你會看到你們幾百人的開發團隊等待一個DBA給你們排期的情況。
5)前端可以做一些小的手段,例如抽獎活動,可以在頁面js中直接告訴用戶未中獎,而並不通知後台,此為「基礎不中獎率」,可以直接過濾掉90%以上的流量。(此功能請與產品團隊好好溝通,從性價比上講,這種小手段不提倡,但是性價比極高。)
6)消息隊列系統建議採用一些堆積能力較強的系統,如:rocketmq,rabbit等,建議rocketmq,消息堆積能力之強,單機堆積上億條。
7)日誌系統建議kafka,日誌系統之後可以增加storm,hdfs,logstash等配套設施
8)網卡流量問題需要嚴重關注,經常出現的問題是:在某個活動之間,redis網卡流量打滿,導致redis無法訪問,整個業務暫停。需要網路部門對公司內部的伺服器路由有準確估算,出現分值之後可以妥善定位問題並修復,日常工作中也要做好規劃,提前做好準備。
9)老生常談的:斷路器、限流、自動降級。斷路器是指在RPC的客戶端中實現如下功能:如果發現該斷路器訪問服務端在10秒內訪問超過50次且失敗率高於50%,則中斷該斷路器的訪問10秒鐘,以保護下游系統。自動降級就是:如果發生問題,自動切換到備用程序上,如報錯、如訪問redis失敗改訪問DB等。限流就是在RPC的服務端中實現如下功能:對每個IP、每個token進行限制,通過令牌桶演算法,每個時間段只允許指定數量的服務通過,否則就拒絕服務調用。一般斷路器使用hystrix,自動降級可以自行實現,也可以用hystrix的配套設施實現,限流比較簡單自行實現即可。
這麼一套下來,大概得三四百人,時間得四五年吧,估算一下:
工資成本兩個億
伺服器預算一個億
網路流量費、電費、機架費、安全監測費、域名費用、第三方採購費用......
大致可以這麼說:如果一家公司計劃三年內投入五個億,還計算搞一番事業出來的,這套框架就夠了,包你從QPS500到QPS10000到QPS1億穩定運行。
但本文主旨不是要告訴你如何搭建一個億萬計的高並發系統,我的意思是:現在高並發技術爛大街了,每當我看到一個人和我吹噓高並發多麼多麼牛,我心中總是泛起一絲憐憫。
想想戰爭年代的發報員
想想幾十年前的司機
想想十年前的站長
想想五年前的國產操作系統
想想三年前的移動端開發
想想一年前的docker
。。。。。。
高並發只是一種類似的技術:使用場景少,價格高昂,好比屠龍之技,龍就那麼幾條,還都差不多被砍死了。隨著相關資料的泛濫,將來它會是一門「出入江湖必備的手藝」,如太祖長拳一般的泛濫,不值一文。
推薦閱讀:
※為什麼說Redis是單線程的以及Redis為什麼這麼快!
※阿里巴巴開源的通用緩存訪問框架JetCache介紹
※SpringBoot集成Redis來實現緩存技術方案
※使用Spring Data Redis操作Redis(二)
※求不更學不動之Redis5.0新特性Stream嘗鮮