最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

開源信創(chuàng)即時通訊GGTalk源碼剖析之:服務端全局緩存

2023-08-23 14:39 作者:傲瑞-即時通訊  | 我要投稿

上一篇:《開源信創(chuàng)國產(chǎn)即時通訊系統(tǒng)GGTalk源碼剖析之:數(shù)據(jù)庫設計》

GGTalk?對需要頻繁查詢數(shù)據(jù)庫的數(shù)據(jù)做了服務端全局緩存處理,這樣做一來大大降低了數(shù)據(jù)庫的讀取壓力,二來在客戶端的請求到來時,服務端能更快地響應,極大地提升了用戶體驗。這篇文章將會詳細剖析關(guān)于?GGTalk?服務端全局緩存的設計與實現(xiàn)。還沒有GGTalk源碼的朋友,可以點擊文章底部鏈接下載。


一. GGTalk 服務端三大核心

首先,我們需要了解?GGTalk服務端?的三大核心,其分別是:

  • 消息處理:處理來自客戶端的消息;

  • 全局緩存:將用戶和群組的數(shù)據(jù)緩存在內(nèi)存中;

  • 數(shù)據(jù)庫交互:對數(shù)據(jù)庫中的信息進行增刪改查。

1. 消息處理

此部分的代碼位于?GGTalk/TalkBase/Server/Core/ServerHandle.cs

當一個客戶端的請求進來時,首先會進入消息處理環(huán)節(jié),根據(jù)用戶傳遞的消息號,進入不同的邏輯分支。以修改用戶信息為例:

當一個用戶信息被修改時,會調(diào)用如上方法,然后通過調(diào)用?rapid客戶端引擎?上的?SendMessage?方法發(fā)送一條消息(其中?data?為用戶信息的?byte[]數(shù)組)。

客戶端發(fā)送消息會觸發(fā)?rapid服務端引擎?上的?MessageReceived?事件,最終程序流程會來到如下圖的地方。

根據(jù)客戶端傳遞在消息號來匹配對應的?if分支,然后進行對應的處理。

2. 全局緩存

此部分的代碼位于?GGTalk/TalkBase/Server/Core/ServerGlobalCache.cs

接著前面修改用戶信息的例子:

消息處理后會來到如上?if分支,其中分別調(diào)用了?serverGlobalCache?上的?UpdateUserInfo?和?GetUser?方法,下面是這兩個方法的具體實現(xiàn)。

此方法會從全局緩存獲取用戶數(shù)據(jù),若緩存中不存在,則會從數(shù)據(jù)庫中查詢,并將查詢到的用戶數(shù)據(jù)存入緩存中,方法最終返回用戶數(shù)據(jù)。

此方法先去獲取用戶的信息,修改用戶信息,然后通過調(diào)用?user?上的?DeletePartialCopy?方法清除用戶的緩存,最后再更新數(shù)據(jù)庫中用戶的信息。

3. 數(shù)據(jù)庫交互

此部分的代碼位于?GGTalk/GGTalk.Server/DBPersister.cs

同樣在這個修改用戶信息的例子中,在前面的講解中有涉及到兩處與數(shù)據(jù)庫的交互,分別是?GetUser?和?UpdateUserInfo?方法的調(diào)用。下面是這兩個方法的具體實現(xiàn):

在數(shù)據(jù)庫的交互環(huán)節(jié),我們使用的是?sqlsugar?來操作數(shù)據(jù)庫(這是一個開源的ORM框架,若想了解其詳細用法,請移步sqlsugar文檔)。

二. 服務端全局緩存

看到這里,相信你對?GGTalk服務端?的三大核心有了一定的了解,接下來將會詳細介紹關(guān)于?GGTalk?服務端全局緩存的設計。

1. 代碼位置

由于在?GGTalk服務端?中對用戶和群組信息查詢過于頻繁,故而?GGTalk?將用戶和群組的信息緩存在服務端內(nèi)存之中,進而達到減少資源消耗和更快的服務端響應的好處,但這樣做同時也會增加編碼的復雜度,那么?GGTalk?是如何在其中進行取舍的呢?下面將介紹具體實現(xiàn)。

2. ServerGlobalCache類

ServerGlobalCache類?就是?GGTalk?服務端全局緩存的核心實現(xiàn)了,這個類接受兩個泛型參數(shù),TUserTGroup,并要求TUser必須是TalkBase命名空間中的IUser接口的實現(xiàn)類或子類。TGroup必須是TalkBase命名空間中的IGroup接口的實現(xiàn)類或子類。

  • IUser:用戶基礎(chǔ)接口,定義了關(guān)于用戶一系列的屬性和方法。

除了這兩個泛型參數(shù)外,我們可以發(fā)現(xiàn)?ServerGlobalCache類?中還有三個字段,這三個字段是?ServerGlobalCache類?中所有方法的核心,其作用如下:

  • dbPersister:與數(shù)據(jù)庫進行交互;

  • userCache:與用戶緩存相關(guān);

  • groupCache:與群組緩存相關(guān)。

關(guān)于這三個字段,在后面的具體場景會展開更加詳細的介紹。

3. 緩存數(shù)據(jù)的實現(xiàn)

關(guān)于服務端緩存,最關(guān)鍵的就是?userCache?和?groupCache?字段了,其中?userCache?用于緩存用戶的信息;而?groupCache?用于緩存群組的信息。

首先我們來看關(guān)于這兩個字段的類型ObjectManager
public class ObjectManager<TPKey, TObject>

ObjectManager是對Dictionary的二次封裝,支持多線程安全,使用起來也更方便。這個類接受兩個泛型參數(shù),我們通過傳入不同的泛型可以實現(xiàn)不同數(shù)據(jù)的管理(在?GGTalk服務端?中,僅管理了用戶和群組的數(shù)據(jù))。

其內(nèi)部的Dictionary就是用來將用戶或群組的數(shù)據(jù)存儲在內(nèi)存中,達到緩存數(shù)據(jù)的目的。

4. 將數(shù)據(jù)庫中數(shù)據(jù)的讀入內(nèi)存(緩存數(shù)據(jù))

我們來看?ServerGlobalCache類?中如下兩個方法:

從名字上來看我們很容易就知道這兩個方法的意思,預加載用戶數(shù)據(jù)和預加載群組數(shù)據(jù),這兩個方法的主要作用就是將數(shù)據(jù)庫中用戶和群組的數(shù)據(jù)加載到內(nèi)存中。首先通過?dbPersister?字段來從數(shù)據(jù)庫中查詢到所有用戶和群組數(shù)據(jù),通過foreach遍歷,分別調(diào)用userCachegroupCache上的Add方法將每一條數(shù)據(jù)存儲到前面提到的objectDictionary字段中,也是就存儲在了服務端程序運行時的內(nèi)存里面。

5. 數(shù)據(jù)庫增刪改查

看到這里,關(guān)于?ServerGlobalCache類?的基礎(chǔ)設施你已經(jīng)了解的七七八八了,接下來都是基于這些基礎(chǔ)設施而實現(xiàn)的方法了。在這里我要糾正一個你可能感到疑惑的點,本篇文章不是介紹服務端緩存嗎,這里怎么扯到數(shù)據(jù)庫的增刪改查呢?

因為往往數(shù)據(jù)緩存和數(shù)據(jù)源之間存在著一些聯(lián)動,所以?ServerGlobalCache類?的作用不僅僅是緩存數(shù)據(jù),同時也存在大量獲取數(shù)據(jù)庫中的數(shù)據(jù)的方法,這也是為什么在類里面會有一個dbPersister字段,當然關(guān)于具體從數(shù)據(jù)庫中讀取數(shù)據(jù)的方法不在這個類里邊(回顧?GGTalk三大核心)。

接下來,讓我們看看?ServerGlobalCache類?還有什么:

我們可以看到,這些折疊的部分的代碼行數(shù)幾乎占據(jù)了?ServerGlobalCache類?的百分之九十,這是正是對數(shù)據(jù)庫和數(shù)據(jù)緩存的操作,每個折疊代碼塊的注釋都對應著?GGTalk數(shù)據(jù)庫?的一張表。

接下來我們主要分析一下關(guān)于用戶和群組的部分操作,看看?GGTalk服務端?是如何對數(shù)據(jù)庫和數(shù)據(jù)緩存進行操作的。

首先來看一個簡單的,添加新用戶操作:

這個方法接受一個TUser類型的參數(shù),參數(shù)中包含用戶的必要信息,然后分別添加到用戶緩存和插入到數(shù)據(jù)庫中。

接下來,再看最開始講三大核心的那個例子:

現(xiàn)在再來看是不是很清晰了呢,這個方法用于查詢單個用戶,接受一個用戶ID,首先會從用戶緩存中查找這個用戶,如果緩存中不存在,則從數(shù)據(jù)庫中查找,在用戶存在的情況下再將其存入內(nèi)存之中。

接下來再分析兩個關(guān)于群組操作的方法。

1、根據(jù)群組ID獲取群組信息:

和獲取用戶信息類似,此方法首先會在群組緩存中查找對應ID的群組,若群組不存在,則會從數(shù)據(jù)庫讀取對應ID的群組,并且在群組存在的情況下將其存入內(nèi)存之中。

2、解散群組操作

這個方法接受群組ID作為參數(shù),首先會調(diào)用GetCroup方法依次從內(nèi)存和數(shù)據(jù)庫中讀取關(guān)于目標群組的數(shù)據(jù)(如果緩存中沒有的話)。若群組存在,則從群組的MemberList屬性中遍歷用戶ID,再通過GetUser方法查詢用戶數(shù)據(jù),通過用戶的QuitGroup退出群組,然后在數(shù)據(jù)庫中更新用戶的信息。在這個群組中的每一個存在的用戶都退出群組后,從群組緩存中清除該群組的數(shù)據(jù)。然后再同步數(shù)據(jù)庫中的群組表的數(shù)據(jù),以及在數(shù)據(jù)庫中申請加入群組表中刪除加入此群組的記錄。

三. 結(jié)語

將數(shù)據(jù)庫中的數(shù)據(jù)緩存在內(nèi)存中是一把雙刃劍,若是將大量的數(shù)據(jù)保存在內(nèi)存中,這會大大加大內(nèi)存的占用,存在程序因為內(nèi)存不足而導致程序崩潰的風險。如何避免這樣的事情發(fā)生,這要求我們對內(nèi)存保持足夠的敏感。最后,希望這篇文章能夠?qū)δ阌兴鶐椭?br>在接下來的一篇我們將介紹GGTalk服務端的虛擬數(shù)據(jù)庫。
敬請期待:《GGTalk 開源即時通訊系統(tǒng)源碼剖析之:虛擬數(shù)據(jù)庫》

點擊下面鏈接下載GGTalk 8.0版本源碼。

https://zhuanlan.zhihu.com/p/651560820




開源信創(chuàng)即時通訊GGTalk源碼剖析之:服務端全局緩存的評論 (共 條)

分享到微博請遵守國家法律
娄底市| 馆陶县| 故城县| 长兴县| 汉源县| 田东县| 田阳县| 进贤县| 咸丰县| 江山市| 白城市| 汤阴县| 龙井市| 蒙城县| 临漳县| 昌黎县| 喜德县| 普格县| 兴文县| 安阳县| 杭锦后旗| 天门市| 通榆县| 梁河县| 涟源市| 千阳县| 彩票| 台前县| 永善县| 腾冲县| 睢宁县| 苏尼特左旗| 海门市| 敦煌市| 霸州市| 鲁山县| 醴陵市| 闸北区| 周至县| 阳西县| 交城县|