高併發場景案例分享(二)count實時查詢之坑

2022-09-19 08:39:12 字數 1711 閱讀 2620

因軟體系統有其複雜性和多樣性,不同的場景、架構下,系統的瓶頸各不相同。

文章裡的一些想法和設計並不通用,主要針對的是高併發場景下海量資料的實時查詢。

這次再分享乙個更貼近生活的案例。

有時看似簡單的邏輯,往往隱藏了最深的坑,甚至成為系統的效能瓶頸。

微博使用者主頁

這個頁面應該都不陌生,業務也並不複雜。

乍一看很簡單,再一看還是很簡單。

根據條件,從相關的業務表統計數量就好了呀。

比如, 從好友關係表count所有關注作者的人( type = 2 代表被關注)。

select

count(1) from user_relation where uid =

'***

'and type =

2

沒毛病啊,十分合理。這麼簡單的東西難道還能玩出花來?

我就是這麼做的,結果整個服務直接掛掉了。

看了下監控,發現量變竟然引發了質變。

在系統資料量不大或流量不高時,使用count查詢來處理此業務沒有任何問題。

當資料達到一定量級時,比如圖中的粉絲量300w+,如果查詢的結果集數量過大,即便根據索引查詢,正常耗時也會達到幾秒、十幾秒,更別說在高併發下頻繁查詢。

再加上微博上億的使用者量,超高的併發,此處若實時地使用count查詢,將輕鬆get以下異常:

the last packet sent successfully to the server was 5,652 milliseconds ago

因為mysql伺服器所有的執行緒都用來執行這些count慢查詢了,導致後面的請求全部阻塞。

此時,資料庫效能監控面板會有一些顯著的指標特徵:cpu負載達到100%,執行執行緒數異常高。

查詢時直接從此表讀取數量,避免count查詢。

解決方法雖簡單了些,能搞定效能上的瓶頸即可。

但當時並沒理解為什麼要做計數器?什麼數這麼吊還要專門做個服務來計算?

朋友圈的設計,就完全不用展示數量。

直接避開了很多可能給系統帶來效能瓶頸的坑。

在mysql進行實時查詢時,應該避免查詢出的結果集數量過大。

否則,即使像count這樣最簡單的查詢語句,也可能帶來效能問題。

當然,最終還是要看具體的使用場景。

比如,乙個用來彙總每**表的查詢語句,使用了 union,group by  等效能不佳的子句,整個查詢耗時5秒。

但它每天只執行一次,且查詢的資料表並不頻繁使用。即便這是一條慢查詢,對效能的影響也是微乎其微。

而像案例中的count語句,即便耗時只有1秒,如果每秒請求1000次,那它對資料庫cpu的消耗就是前者的200倍。

Redis高併發場景應用

步驟1 先登入你的京東賬號,清空以前購物車,然後新增一件商品a,保證你的購物車只有一件商品a。步驟2 退出登入,購物車新增商品b,然後關閉瀏覽器再開啟。請問 購物車的商品b是否存在?步驟3 再次登入你的京東賬號。請問 你的購物車有幾件商品?往購物車加入2件商品 採用hash資料結果,key cart...

高併發 秒殺業務場景詳解

一 秒殺場景的特點 秒殺的商品具有 低 庫存有限 定時開始的特點,因此秒殺場景最大的特點就是高併發。數以千萬的使用者的流量集中在某個時間點上 即秒殺開始時 給後端伺服器造成很大壓力,如果不能進行有效削峰 限流,所有請求一次性打到某一台伺服器或資料庫上,必然造成服務的不可用,給使用者造成不良體驗。二 ...

使用redis 處理高併發場景

1.原理 當同乙個使用者獲取鎖之後,會讓該使用者一直持有鎖。同樣 的使用者再次獲取,會根據原子性 lock返回true。獲取鎖 非公平鎖 預設獲取超時為2分鐘 public boolean lock 獲取鎖 非公平鎖 獲取超時為timeoutseconds秒 public boolean lock ...