Kafka案例

 

假設我們正在開發一個多人在線網絡遊戲。遊戲中,玩家需要在虛擬世界中進行合作或者展開競爭。玩家之間也常常存在各種交易,包括錢、道具等。因此遊戲開發人員必須保證玩家沒有作弊,規則如下:如果玩家交易額顯著高於正常水平或者玩家登錄的IP地址與之前20次登錄的不一樣,那麼交易將被標記可疑。除了實時標記交易以外,我們還希望可以將這些數據導入到Apache Hadoop以方便數據科學家訓練、測試他們的算法與模型。

爲了提高實時的事件標記的效率,我們儘可能利用遊戲服務器的內存。遊戲系統包含了多臺遊戲服務器,因此在設計中,我們會在內存中保存每一個用戶最近的20次登錄記錄以及最新的20次交易明細(數據是分佈式存儲的)。

遊戲服務器主要扮演兩個不同的角色:接收並傳播用戶行爲,實時處理交易信息並對可疑事件進行標記。爲了高效的扮演第二個角色,我們需要將任何一個用戶的交易歷史保存在一臺服務器的內存中。這就意味着我們不得不在服務器之間傳輸消息,畢竟接收用戶行爲數據的服務器未必包含了該用戶的交易歷史。爲了保持角色之間的松偶和,我們利用Kafka在不同服務器之間傳輸消息。

attachments-2021-02-Fy2pTNkx6030acd5088bc.jpg

Kafka的特性使得它可以很好的滿足我們的需求:可擴展、數據分區、低延遲以及處理大量異構消費者的能力。在該案例中,我們爲登錄與交易處理定義了一個主題。之所以使用同一個主題主要是因爲我們希望在處理交易事件前已經獲得用戶登錄信息了(Kafka保證主題中的消息順序,但不保證不同主題間的消息順序)。

當用戶登錄或者交易時,接收服務器(圖中Accept)會將數據立即發送到Kafka。消息使用用戶id作爲主鍵,事件本身作爲消息的值域。這樣就可以保證同一用戶的所有事件,包括登錄事件與交易事件,都被保存在同一個分區中。每個處理服務器(圖中Process)運行一個Kafka消費者,所有的消費者被配置到同一個組,這樣,每個處理服務器將會處理部分Kafka分區,同時同一個用戶的所有數據都會被同一個處理服務器處理。當處理服務器讀取到用戶的交易事件時,它首先將該交易事件加入到用戶的交易歷史中(緩存在內存),接着它利用緩存的歷史數據對可疑的事件進行標記,在標記過程中無需額外的網絡或者磁盤開銷。

值得注意的是在實際系統中,我們一般根據處理服務器的數量來配置Kafka分區數量,比如爲每一個處理服務器分配一個分區,或者爲每一個處理服務器上的CPU核分配一個分區(當前Kafka集羣爲所有主題分配的分區總數一般不超過10,000)。

該方案看上去彷彿是一種迂迴的方式:遊戲服務器將數據發送到Kafka,另一臺遊戲服務器又從Kafka中進行讀取。然而,這個設計松偶和了遊戲服務器的兩個角色,因此可以幫助我們很方便的爲不同的角色配置相應的資源。另外,由於Kafka本身設計是以高吞吐以及低延遲爲初衷的,通過Kafka作一次“迂迴”其實並沒有帶來顯著的開銷。根據測試,一個3節點的Kafka集羣,處理每秒100萬條消息的平均延遲只有3毫秒。

當遊戲服務器發現可疑的交易後,它會把標記後的消息發送到一個新的Kafka主題,例如圖中的警告(Alert),因此告警服務器可以將該消息通知出去。同時,一個獨立的服務將上述的兩個主題中的數據導入Hadoop用以後續的分析。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章