成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

談談陌陌爭霸在數據庫方面踩過的坑(排行榜篇)

移動開發 Android
陌陌爭霸中用于排名的分數區間不大,也就是 0 分到 5000 分。而參與排名的人數眾多,數以百萬計。對百萬用戶做插入排序,每個插入即使是 O(N) 的也不可接受。可事實是大量玩家的分數相同,都是并列排名的。所以我們只需要做 5000 個桶,每個桶里僅記錄這個分數有多少個人就可以了。

為什么大部分網絡服務都需要一個數據庫在后臺支撐整個系統?

這通常是因為大部分系統的一個運行周期都很短,對于傳統的網站服務來說,從收到一個 HTTP 請求開始,到終端用戶收到這個請求的結果為止,就是一個運行周期。

而其間可能處理的數據集是很大的,通常沒有時間(甚至沒有空間)把所有數據都加載到內 存,處理其中涉及的一小部分,然后保存在磁盤上再退出。

當數據量巨大時,任何對數據的操作的算法和數據結構都需要精心設計,這不是隨便一個程序員就可以輕松完成的任務。尤其是數據量大到超過內存容量時, 很多算法和數據結構對大部分非此領域的程序員來說都是陌生的。本著專業的事情交給專業的人來做的原則,一般系統都會把這部分工作交給獨立的數據庫來完成。

對數據的操作只有抽象的足夠簡單,系統才能健壯,這便有了 SQL 語言做一層抽象,讓數據管理的工作可以獨立出來。甚至于你想犧牲一部分的特性來提高性能,還可以選用近年來流行的各種 NOSQL 數據庫。

可在 MMO 游戲服務器領域,事情發生了一點點變化。

數據和業務邏輯是密切相關的,改變非常頻繁。MMO 服務器需要持續快速的響應用戶的請求。我們幾乎不可能把一切數據都放在獨立的數據庫中,比如玩家在虛擬世界中的位置,以及他所影響的其他玩家的列表;玩家 戰斗時的各種屬性變化,還有和玩家互動的那些 NPC 的狀態改變……

最大的矛盾是:MMO 游戲中數據集的改變不再是簡單的 SQL 可以表達的東西,不可能交給數據庫服務期內部完成。無論什么類型的數據庫,都不是為這種應用設計的。如果你硬要套用其它領域的應用模式的話,游戲服務器只 能頻繁的把各種數據從數據庫中讀出來,按游戲邏輯做出改變,再寫回去。數據庫變成了一個很低效的數據中轉中心,無論你是否使用內存數據庫,都改變不了這個 低效的本質。

我聽過無數從別的領域轉行到游戲領域做開發的程序員設計出來的糟糕系統。他們最終僅僅把數據庫當成一個可靠的數據儲存點和中轉點,認為把所謂重要的 數據寫進數據庫就萬事大吉,然后再別扭的從另一個位置把數據從數據庫讀出來使用。系統中充滿了對數據庫的奇怪異步回調用來改善系統的反應速度,而系統卻始 終步履闌珊。能做對已經是極限了,更何況游戲系統不僅僅是輸入輸出正確就是正確,如果超過了應用的響應時間,一切都是不正確的。

為了讓系統健壯,構架師在構架系統時,一定會把系統隔離成不同的模塊,并盡量簡化模塊間的溝通規則。這樣你可以單獨校驗每個模塊的質量,必要的時候可以更換。幾乎沒有人會因為效率或開發方便等原因而把應用代碼寫到 OS 內核中去跑就是這個道理。

每個模塊只對輸入它的數據負責,保證輸出的正確。通常測試也只對這個正確性負責。同學們最容易忽略的一點是,每個模塊都對它輸入數據的處理速度有一個上限,也就是它的吞吐量。

一旦輸入速度大于處理速度,模塊實現的再正確也是白搭。因為永遠都不會有輸出了。

對于大部分模塊,只要內存管夠,這都不是問題。實際運作的系統中很少有持續大數據量的輸入的,從一個較長的時間看,總的數據輸入是小于處理能力的,暫時沒能處理的數據堆積在內存就行了。

凡事都有例外。一個健壯的系統都需要對例外做處理。一個工作在 server 模式的數據庫是這樣解決這個例外的:它會支持查詢連接的并發,并發的查詢相互間對計算資源的占用是公平的,相互不影響(至少是設計上的理想)。而操作系統 或數據庫本身會限制并發的連接數,一旦達到最高連接數,系統會拒絕服務;這樣就把超過處理能力的輸入擋在了模塊外面。按這種設計,就不會有輸入(只要能抵 達)永遠沒有回應了。

可惜,這樣做的代價是,你必須在模塊間加入請求失敗的處理。一個設計不謹慎的系統最容易在錯誤處理上栽跟頭。他們總是期望任何一個模塊都能正確處理上級的請求。

btw, 為什么 12306 的訂票系統在高負載的情況下完全不可用?就是這點沒處理好。我指的是,一個實現正確的系統,一定不會連網頁的刷不出來,不給用戶正確的提示,哪怕只是錯誤 提示;也不應該在高負載下,有效處理能力急劇下降。我指的是,一旦用戶能進入正常流程,就應該順利把至少一個環節順利完成,而不是突然就卡在那里沒有任何 回應。

快跑題了。我談到這點,其實是想表達,說的容易,做起來是很難的。下一篇我會寫到我們在過年前出的一個事故和這個就有一些關系。

八卦時間:

陌陌勁舞團是陌陌游戲平臺上線的第 2 款游戲。我們的陌陌爭霸還在開發的時候,這款游戲就打算上線了。我對這個產品有限的了解都是道聽途說,所以如果有更清楚內情的同學發現說的不對,也請諒解。對于技術問題,我想八卦的真相就并不那么重要了,有則改之,無則嘉勉。

勁舞團這個品牌原本是屬于韓國人的,但這款游戲在國內曾經異常火爆,在國內代理它的久游也就買下來 IP ,自己制作手機版。據我所知,陌陌勁舞團完全是在上海開發的,沒韓國人什么事。

這是個比較簡單的游戲,至少服務器部分很簡單,也就是統計下分數,查查排名,以及解決一下收費問題而已。刨掉這些部分,它就是個單機游戲,根本不需要服務器。

因為勁舞團的品牌名氣,以及陌陌巨大的用戶群,游戲一上線就在 ios 免費榜飚上去了。如果不是企鵝公司看不順眼,立刻上線了節奏大師,估計還會在榜單上更火一些。事后證明節奏大師的上線也很倉促,完全是為了打擊競爭對手搶 著上的,因為后者的服務器也不穩定,很快就掛掉了,完全不像一個大公司應有的質量。

陌陌勁舞團順利拉來了用戶后,第一天服務器就出了狀況,重啟了幾次后完全不解決問題。所以決定停服休整。一停就是三天。當時我就納悶了,哪有修個小 bug 預計要三天的?這肯定是有結構性問題了。當時我們的項目按計劃也就最后半個月的時間了,本來陌陌的人督的我們很緊的,一下子人全飛去了上海。

一周后陌陌勁舞團才重新上線,遠超過當初預計的 3 天。事情一解決,陌陌的技術班底,從 CTO 到下面大多數人,全部飛到廣州和我們開會,讓我們重視服務器穩定性問題。會議內容主要是強調陌陌平臺初期導入用戶瞬間爆發量巨大,以及了解一下我們的設計 細節確保沒有大的問題。我所了解到的八卦就是在這段時間聽來的。

陌陌勁舞團使用的是 MongoDB 。似乎這玩意很受游戲開發者喜愛。我想主要是因為用起來簡單直接吧。游戲從業者如果之前沒有別的領域的開發經驗,對數據庫這東西一知半解的人居多。尤其是 從客戶端開發過來的人,他們通常的習慣就是看 API 文檔,了解怎么用看起來正確就夠了。然后上線測試一下,好像也對,工作似乎就結束了。就算有壓力測試,也很難做到和生產環境一致。

上線前,據說雙方溝通過。陌陌方想確認系統能不能橫向擴展,得到的答復是可以:加硬件即可。我想陌陌勁舞團開發方的思路是這樣的:我們的服務器系統 很簡單,不都是過一下數據庫么?MongoDB 是被很多人驗證過的,不會在這么簡單的業務中出問題吧。至于負載,不是還有 mongos 么?放心啦,沒事的。

最終的直接問題出在排行榜上。當有兩萬人在線時(沒錯,才兩萬人而已),大量用戶的排行榜查詢阻塞了數據庫。導致不僅僅是排行榜刷不出來,連沖值業務也受到了影響。土豪們充不進去錢,談什么玩游戲啊。最終產生了雪崩,整個數據庫都不正常使得游戲系統工作不起來。

為啥用了這么長時間才修好這個 bug ?

負責陌陌勁舞團的服務器開發的人在項目做完就離職了。想想一個設計有問題的系統交給非設計者維護有多糟糕吧?任何清醒的程序員都知道,這個時候即使是重寫也比改問題簡單。陌陌的同學做了個正確的決定,直接派自己的人駐留在上海,把服務器重新寫了一遍。

陌陌的技術背景是 Redis 的,他們的系統用 redis 構建,所以重寫就用了 redis 取代 mongodb 。寫到這里,我完全沒有 redis 和 mongodb 誰好誰差的意思。關鍵在人,你對什么熟悉就用什么,哪種數據庫都能對付這點小業務,關鍵看你能不能用對。

Redis 里正好有一個有序集(Sorted Set) 的數據結構,你用 ZADD 插入完數據后,它就天然有序了。這個插入是 O( M * log(N)) 的時間復雜度,基本可以滿足需求。而用 ZRANGE 查詢榜單僅需 O(log(N)+M) 的時間復雜度。

那么使用 Redis ,利用 sorted set 做排行榜系統是我們的唯一選擇么?絕對不是。我們也不可能為了這個特性必須選擇 redis 做數據庫。但這個例子可以說明:如果數據庫提供內在的特性可以對數據集做一些操作,我們就直接用,但需要了解這種操作的性能。它需要和整個系統對它的性能 期望匹配。

陌陌勁舞團使用 mongodb 內置的排序功能去做排行榜本也不是大問題。或許僅僅只是實現的人對 mongo 不熟悉造成的性能低下。這些隨著系統重建已經無法深究了。但核心問題是,僅僅一個排行榜系統的錯誤實現為何會影響整個系統的穩定性?

下面就是我的猜測了:

許多程序員為了提高數據庫的吞吐量,并不是一個事務就給數據庫建一個連接,用完就關掉的。因為新建 TCP 連接是個開銷較大的操作。維持太多連接對系統也是一個開銷。同學們喜歡做一個叫做連接池的東西,在系統其它部分和數據庫對接的地方走這個連接池。只要一個 舊有連接沒有斷開,就一直把對數據庫的請求通過固定連接發給數據庫,等待返回。

在數據庫的吞吐量滿足系統需求的時候,這個模塊很容易實現正確。但一旦超出需求,連接池上的數據就會越積越多,數據庫查詢越來越慢。而調用數據庫的模塊卻不覺得這是問題。

正確的行為應該是讓連接池快速反饋,斷開并扔掉不可能處理完的請求,讓請求方把這個不能處理的錯誤反饋到上個環節,直到流量被限制在合理的范圍內。整個系統才能不至于崩潰。當錯誤被迫反饋到玩家那里時,他頂多看到的是查詢失敗,而不太會影響到別的功能。

陌陌爭霸怎樣做排行榜的?

在上一篇里就有同學問道,如果你們不用數據庫,怎么做排行榜呢? 其實我在上一篇正文里就有解答:

“服務器只是在不斷的創造新數據并讓這些數據在內存中流通而已,它沒有任何需要從外部讀取數據。如果內存無限大,且服務器永遠不會當機,數據庫這個設施沒有存在的必要。”

排行榜單也是數據之一,游戲服務器開服一刻起,沒有任何玩家有排名信息。隨著玩家名次更替,榜單才逐步形成。我們只需要在玩家分數變化的時候同步榜單的變化即可。而玩家查詢僅僅是取走有序的榜單而已。

你看,這個過程和數據庫無關不是?需要設計的是調整榜單的算法,和榜單的數據結構以保證維持榜單的性能足夠強就好了。因為玩家名詞更替的頻率遠小于玩家網絡包的頻率,那么這個模塊的處理能力所需要的下限很容易滿足。我們不用考慮處理不過來的情況。

針對陌陌爭霸我們是這樣做的:

陌陌爭霸中用于排名的分數區間不大,也就是 0 分到 5000 分。而參與排名的人數眾多,數以百萬計。對百萬用戶做插入排序,每個插入即使是 O(N) 的也不可接受。可事實是大量玩家的分數相同,都是并列排名的。所以我們只需要做 5000 個桶,每個桶里僅記錄這個分數有多少個人就可以了。

當玩家分數變遷,把原來的桶減一,新的桶加一。這個操作就是 O(1) 的。

而排行榜的查詢僅需要把當前分數靠前的桶累加,就能獲知查詢者的名次。對于上百萬玩家,看到哪些人和你并列的人的名字是沒有意義的。這個查詢雖然是 O(n) 復雜度,但 n 只有區區 5000 ,還可以做 cache 以應對查詢頻率遠高于更新頻率的情況。

真正需要精確知道人名的是榜單的前 200 個人,而對前 200 個人做插入排序也很快,所以并不會造成性能問題。

我們在系統的單點做排行榜的維持,完全沒有外部數據庫操作,它只是一小段操作普通內存結構的 c 代碼。而這個單點遠遠成為不了整個系統的熱點。

我們在系統臨時退出時,把已經排好的榜單落地,下次啟動的時候恢復。但也不必完全信任落地的數據,可以用離線腳本檢索整個數據庫重新生成一份正確的榜單。所以數據庫中的榜單只是被 cache 起來而已,系統運行期間是不需要寫入數據庫的,也不用擔心數據丟失。

好吧,還是沒談到我們自己踩的坑,就又到了吃飯時間 :( 。

明天我將寫寫陌陌爭霸在運營期間遇到的第一起數據庫事故,它和 mongos 有關。同時也會談談我們在代理狂刃期間幫狂刃填的一些和 mongodb 有關的坑。

原文地址。51CTO獲作者授權轉載。

責任編輯:徐川 來源: blog
相關推薦

2014-03-09 23:29:12

2014-03-05 09:31:54

陌陌爭霸數據庫

2014-03-09 23:22:26

手游開發數據庫

2015-03-31 18:26:43

陌陌社交

2012-08-31 14:36:19

陌陌林志霖社交應用

2012-08-27 09:39:23

陌陌社交APP

2022-09-02 09:06:17

數據庫Oracle

2014-07-25 15:41:12

陌陌WOT2014GoRedis

2021-12-06 16:35:33

QQ微博社交軟件

2013-08-23 09:41:19

2021-07-09 14:18:15

數據庫DB-EnginesOracle

2015-05-27 11:05:46

阿里云陌陌CDN

2014-08-15 17:51:39

聽云

2015-05-12 14:34:09

陌陌

2021-08-05 10:46:21

數據庫SQL ServerDB-Engines

2021-04-02 12:51:03

數據庫DB-EnginesMongoDB

2015-12-11 16:07:03

光合資本

2025-05-07 08:21:01

2015-07-24 16:49:40

陌陌禮物

2012-08-23 16:41:10

陌陌投資
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲一区二区三区观看 | 狠狠躁天天躁夜夜躁婷婷老牛影视 | 午夜av在线 | 毛片视频网址 | wwww.8888久久爱站网 | 日韩影音| 久久精品99 | 日韩电影中文字幕在线观看 | 97精品超碰一区二区三区 | 日韩久久久久 | 毛片区 | 特级做a爱片免费69 精品国产鲁一鲁一区二区张丽 | 欧美在线小视频 | 日日夜夜狠狠操 | 国产人免费人成免费视频 | 欧美日韩精品久久久免费观看 | 亚洲成人av | 国产做a爱免费视频 | 日本精品裸体写真集在线观看 | 天天色官网 | av免费观看在线 | 一区二区三区精品视频 | 天天草狠狠干 | 成人三区四区 | 欧美一级二级视频 | 欧美一级毛片在线播放 | 国产成人精品一区 | 精品国产91| 国家一级黄色片 | 午夜av电影| 久婷婷| 国产精品久久久久久二区 | 99婷婷| 一本一道久久a久久精品蜜桃 | 色综合久久久久 | 午夜天堂精品久久久久 | 日韩久久久久 | 亚洲成人免费视频在线 | 成人精品一区亚洲午夜久久久 | 无码国模国产在线观看 | 国产精品成人一区二区 |