查詢使用者名次。
查詢topn(即查詢前n名的使用者)
實時排名(很多專案是可選的)
當排序的資料量不大的時候,這個需求很容易滿足,但是如果資料量很大的時候比如百萬級、千萬級甚至上億的時候,或者有實時排名需求;這個時候要滿足效能、低成本等需求,在設計上就變得複雜起來了。
這裡列舉下日常對於排名的常規做法和缺陷。
1. 資料庫解決方案
這是最簡單的做法,資料儲存在資料庫裡面,然後利用資料庫做排序處理。
這裡分兩種情況:
1.1單庫/單錶
參與排名的資料量小的時候的做法,所有資料儲存在一張表上。
查詢操作示例:
查詢使用者名次:
select count(*) as rank from 積分表 where 積分 > (select 積分 from 積分表 where uid=』使用者id』)
查詢前n名:
select uid, 積分 from 積分表 order by 積分 desc limit 0,n
1.2 分庫/分表
對於這種情況資料不在一塊,在查詢操作上跟上面單錶情況的區別就是,分庫/分表需要做,查詢任務切割和查詢結果合併處理。
缺陷:查詢排名效率低,會造成掃瞄大量的記錄,甚至全表掃瞄,效能低,在資料量大、高併發的情況下這種方案是不可用的。
2. 採用常規排序演算法
思路上就是把積分排序處理從資料庫轉移出來,自己實現排序和查詢處理。
實際排名業務的特點:
常見的幾種排序演算法大家都熟知這裡就不列舉了。
缺陷:對於海量資料排序處理,簡單的使用常規排序演算法並不合適,要麼就是排序造成大量的資料移動、要麼就是對已排序的資料查詢名次效率不高。
前面的排名演算法都是針對積分進行排序,然後通過統計積分高於自己的人數獲得排名。
要想知道某個使用者的名次,只需要知道比這個使用者高分的人數,不一定需要對積分做排序。
在這裡換個思路不對積分進行排序,僅僅是統計每個積分區間的人數,用積分區間的形式去統計相應的人數,下面是演算法描述。
1. 根據積分範圍建立平衡二叉樹。
設[0, n]為積分範圍, 構造的平衡二叉樹如下圖。
每個節點包含兩個資料字段(除了指標):
range: 表示積分範圍。
counts: 表示當前積分區間包含多少人。
積分的區間的劃分是根據平分的方式,把當前積分範圍一分為二生成兩個子節點,然後遞迴的重複該步驟,直到積分區間無法劃分為止(即區間[x, y], x == y)
例子:假設積分範圍為: [0, 5], 構造的平衡二叉樹如下圖:
節點內的資料表示當前積分區間的人數。
從上圖可以看出來,所有積分都在葉子節點,葉子節點即最小粒度的積分區間。
2. 統計相應積分區間的人數。
這裡主要有兩種操作:
假設積分為i
新增積分的過程就是查詢積分i, 同時累加查詢過程經過的節點計數。
下面給出操作例子,注意觀察操作路徑。
例: 需要新增積分3, 結果如下圖
接著在新增積分4,結果如下圖
接著再新增積分4,結果如下圖
接著新增積分2,結果如下圖
刪除積分的過程也是查詢積分i, 區別是查詢過程經過的節點計數全部減1。
ps: 只有積分是存在的情況下,才能做刪除操作,另外用一組標記,標識積分是否存在,這裡就不列舉了。
例子: 刪除積分4, 結果如下圖
3. 查詢名次操作。
查詢某個積分的排名的過程也是查詢積分i的過程,下面是查詢過程統計節點計數的演算法:
對於查詢路徑上的任意節點,如果積分在左節點區間,則累加右節點區間的計數。
最終累加計數的結果加1即是積分的名次
例子: 查詢積分3的名次
藍色節點是查詢積分3經過的路徑,紅色節點是需要累加的計數值。
最終結果是:0 + 1 + 1, 積分3的名次是第2名
從上面的演算法可以看出,對平衡二叉樹的操作,演算法複雜度是o(log n), n是最大積分。
在積分範圍不變的情況下,演算法複雜度是穩定的,跟使用者量無關,因此可以實現海量使用者積分排名、實時排名演算法需要。
對於海量積分資料實時排名、這裡給出的是核心演算法,實際業務的時候還需要增加一些額外的處理,比如uid於積分的對映表用於記錄使用者歷史積分、積分與uid的對映表用於topn這種查詢前n名的需求、資料持久化、高可用等需求。
海量積分資料實時排名演算法
積分排名在很多專案都會出現,積分排名主要滿足以下需求 當排序的資料量不大的時候,這個需求很容易滿足,但是如果資料量很大的時候比如百萬級 千萬級甚至上億的時候,或者有實時排名需求 這個時候要滿足效能 低成本等需求,在設計上就變得複雜起來了。高效做法是不對積分進行排序,僅僅是統計每個積分區間的人數,用積...
小記一次海量資料實時查詢網域名稱庫設計(下)
根據whois資料查詢業務場景 響應效能等需求,該庫採用hbase es 技術組合設計,其中hbase儲存全量whois資料,es庫作為查詢索引庫,只儲存查詢whois資料時的索引項資料。當提交一條查詢請求時,首先從es庫中利用索引檢索出記錄的唯一鍵 id 再使用該唯一鍵從hbase中查詢出全量資料...
Druid大資料實時處理的開源分布式系統 介紹
druid 是乙個為在大資料集之上做實時統計分析而設計的開源資料儲存。這個系統集合了乙個面向列儲存的層,乙個分布式 shared nothing的架構,和乙個高階的索引結構,來達成在秒級以內對十億行級別的表進行任意的探索分析。以下將詳細闡述druid的架構,如何支援快速聚合 靈活的過濾 和低延遲資料...