超大實時排行榜的解決方案

2022-04-04 19:20:31 字數 1658 閱讀 9992

標題是個噱頭,這裡只說積分資料全部裝載到記憶體

首先,玩家的積分什麼的有單獨的表儲存,這裡不談序列化,語言是c++

假定score是double,id是int64

然後計算空間需求,這裡假設實現了專用無稅收的記憶體介面卡

32位程序大位址,每個節點32位元組,4g的程序可以放下1.34億的資料,去掉程序本身的邊角,1.2億

64位程序,每個節點48位元組,1億資料需要4.47g記憶體,根據需要自己給伺服器加記憶體吧...

然後就沒有然後了...

就是這麼簡單粗暴的把所有積分塞進記憶體

查詢第k名玩家的id

查詢積分n可以排多少名

好吧,存在的問題是,更新略噁心,用積分做k,存在相同積分時候,equal_range後遍歷找到對應id,erase後重新insert吧

序列化什麼的,可以考慮記憶體對映檔案+對應記憶體介面卡來搞定 

然後說說容器本身!

自己碼的sorted_set類,可隨機訪問的kv容器,std::multimap風格,允許重複key

operator操作不明確下標訪問或是key-value查詢,所以沒有實現

內部二叉樹結構,除了parent,left,right之外,只有乙個sbt需要的size域,4個指標大小

隨機訪問迭代器,可以+/-/+=/-=操作,可以兩個迭代器相減求距離

這裡的rank從0開始,並沒有給出select函式,而是參考std::vector使用at隨機訪問

各種介面的複雜度不超過o(log2n),參考陳啟峰的size balanced tree

實測4千萬資料,可以達到每秒百萬查,作為一般的遊戲行業,算是足夠了

樹結構還算平衡,順序/亂序插入的時間開銷是std::multimap的1.2倍左右,這裡請教是不是我實現有問題?

最後念叨點題外的!

說起來個人比較懶...

最初是我的俄羅斯方塊ai裡面的需求,對有序的std::vector不斷歸併,std::merge成了效能瓶頸!

之後考慮節ai內部本身就是乙個個節點,直接建立二叉樹來排序效果應該不錯,但是ai內部節點都是百萬級別!

於是直接用std::map的問題就是new的時候會有稅收,而且本身就是ai節點,所以參考std::map原始碼直接搞了個乙個不去new節點,直接把外部節點掛在樹上的容器!還沒有clear開銷!

似乎就是這樣了,然而後來聽說size balanced tree比red black tree效能還好,然後改造起來也不麻煩!索性順手加上那個神maintain來測試一下效能~

結果實測,比紅黑樹稍慢,也可能是我的實現有問題?沒有達到陳啟峰說的超越紅黑樹,不過也算是乙個數量級~

最終俄羅斯方塊ai還是用了紅黑樹...

------分割線------

群裡某人問:"sortedlist相當於c++裡的啥容器?"

於是我就把之前的外掛程式節點的容器拿來重構...

暫時叫sorted_set,跟redis的z系列很像,同npm的sorted-set(內部跳表實現)

相比其他的rank tree實現,附加域沒有任何浪費什麼的太漂亮了

本文3個目的

1.安利一下size balanced tree

2.找高人看看我的實現有什麼問題

3.拋磚引玉

最後傳送門

Redis 實現實時排行榜

面試 你懂什麼是分布式系統嗎?redis分布式鎖都不會?遊戲中存在各種各樣的排行榜,比如玩家的等級排名 分數排名等。玩家在排行榜中的名次是其實力的象徵,位於榜單前列的玩家在虛擬世界中擁有無尚榮耀,所以名次也就成了核心玩家的追求目標。乙個典型的遊戲排行榜包括以下常見功能 能夠記錄每個玩家的分數 能夠對...

排行榜實時性 可行性

用redis的跳表 百萬級別的排序能達到實時的更新,以下是沒用到redis跳表演算法的一些實時排行的考慮 在排行榜對前十名,前50名以後無要求時可行,思想很簡單就是在每次排序時,取前十玩家,且取到第十名玩家 此時的值,這樣每次排行資訊變化時,如果前十玩家改變,只需要排序十個 玩家,如果前十以外的玩家...

Redis排行榜的實現

遊戲闖關排行榜以通關次數正序 復活次數倒序和第一次通關的時間倒序來進行排序 第一步是組合排序分值,只有根據排序規則組合出來的分值,才能通過排序獲取到正確的排名。在排序規則中一般會有兩種方式,屬性正序和倒序。正序對於組合數字來說沒有影響,但是倒序就需要進行特殊的處理。那麼多說無益,上 排行榜顧名思義就...