所遇不良設計 四

2022-04-02 10:23:08 字數 2768 閱讀 5114

可能剛開始開發的時候,圖一時的簡單,為了在服務端少寫那麼多的c/c++**,用sql語句來實現一些邏輯,只需要幾行sql語句的儲存就解決了,服務端直接呼叫儲存過程,比如說我們要做兩張表的資料的關聯。兩張資料表的操作,如果用程式載入進入記憶體,然後在比對關聯的字段,似乎步驟過多。當用sql語句,可以用select … where … 就能解決問題。起初乙個區的玩家可能比較少,效能的問題不能凸顯出來。當遊戲開始冷卻下來,玩家大量離開,為了維持乙個區域上的玩家的活躍度,就會去合服。有時候甚至幾個區的遊戲合成到乙個區,兩張表的關聯資料過多,儲存過程執行速度過慢,會導致伺服器死鎖。到了後期,見到這個問題,要人員再去修改這個模組,可能有諸多抱怨,況且修改這個系統的人不是寫這個模組的本人。最後運維將一些等級比較低的,好長時間沒有玩的玩家的清理掉,來減少表間資料的關聯。我覺得這樣子損害了一部分玩家的利益的,可能他某天突然想起到這個遊戲,發現自己的賬號再也登不上了,雖然他不是付費的玩家。

還有乙個問題,就是排行榜的問題,如果用sql語句也是很簡單,直接select加上top函式並且排序就行了,多麼簡單。但是由於玩家的資料一直在變化,排行必須實時獲取,用儲存過程也是會耗費很多時間的,其在不停的對大量的資料進行重複排序的。這些問題,我們應該在服務端來解決,針對不同的問題,我們應該區分對待。

如果所排列的資料是有乙個範圍的,而且這個範圍比較小,比如[0, 1000]。我們可以使用桶排序的, 資料結構是乙個鍊錶陣列,陣列有1000個桶。如圖:

我們直接將對應的值插入到對應的桶的鍊錶裡面就ok,插入的速度是o(1),然後就可以直接按照從大到小的順序抽出1000玩家就ok。

如果所排列的資料是有沒有範圍的。我們可以這樣實現,用乙個vector容器來裝前一千個玩家,然後用乙個hashmap來容納其餘的玩家,當有乙個玩家的分值發生改的時候,如果能排上前1000, 就插入到vector裡面,插入的時間複雜度為o(n);如果排不上1000, 就放到hashmap裡面去,插入的時間複雜度為o(1),這樣子反應速度還是能夠忍受的。

注意:使用儲存過程首先要估量儲存過程是不是使用頻率比較高; 其次其關聯表的多少,而且要考慮當玩家數量激增到一定值時,其反應速度是否能夠被接收。

當我們執行乙個程序,不能關閉時,我們經常這樣子:

1

ps -ef | grep

"程序名

"#查詢到程序的id23

kill -9 progress'

s id #終止程序

view code

我發現有時候遊戲需要正常停服,維護的時候,經常這樣做; 雖然維護的時間是在夜深人靜的時間段,對伺服器造成不了什麼影響。我實在擔心伺服器程式就這樣突然閃停,會造成資料的紊亂。其實發現在linux下面經常能見到一些服務能夠通過命令來停止、開啟、重新啟動。例如:

1    /etc/netservice stop

23    /etc/netservice start

45    /etc/netservice restart

view code

為什麼我們不能通過命令選項的方式來對服務進行安全的停止了,使其安全著陸了。要是系統資料發生問題,將很難找到問題出現的源頭。下面是我用鎖來解決問題的流程圖:

上有三條主線:

1.直接進入start塊,來開啟服務,如果已經上鎖了,直接結束,提示已經執行了乙個服務例項,保證永遠只有乙個服務例項執行; 否則就啟動程式,因為已經獲取了鎖資源,再獲取鎖資源的時候會阻塞。

2.直接通過外部程式stop,來為已有的服務例項解鎖,start模組獲取第二次的鎖資源會阻塞,這時候解鎖之後,會獲取第二次所資源,緊接著進行收尾工作,接著再進行解鎖,最後結束程式。

3.是restart,先stop,停止已經有的例項,然後start來開啟服務。這乙個主線就是2和1的合集。 這樣子比kill -9 安全多了,讓程式正常著陸。

當沒有了快取,經常要查詢和更改玩家的資料,直接對資料庫進行操作。當在一天中最活躍的時間段,往資料庫中插入的資料太頻繁,或者查詢資料的太頻繁,就會造成資料庫的死鎖,伺服器會卡主,造成客戶端反應過慢,有時候造成服務端執行緒卡主,直接導致玩家登陸不進來,這種體驗對於玩家來說,糟糕透頂。

這時候快取就很重要了。快取一般就是共享記憶體資料結構,共享記憶體的好處就是能夠是實現程序間通訊,而且當乙個服務程序崩掉的時候,它還是存在的; 也就是共享記憶體脫離於程序之外。這時候我們要設計快取就是實現資料庫與服務端資料之間的過渡,不要讓查詢、更改資料庫太過頻繁。快取基本上能夠杜絕資料庫的查詢,其次可以把資料庫的更改收集起來,蒐集的足夠多了,在一定的時間點把資料同步到資料庫,這樣子效率就高多了。程式-快取-資料庫如圖:

這似乎很好,不過忽略了乙個問題,那就是持久化的問題。就是快取還沒來得及往資料庫裡面同步資料,突然間宕機了,這樣子造成大量玩家的資料丟失,造成損失還是挺大的。 要是實現快取+持久化,還是要費點腦子,我建議使用nosql資料庫。redis和mongdb都可以,我比較傾向於redis。還有一種快取就是memcache,但是不支援持久化的,我們可以通過memcache來儲存遊戲模板資料,因為模板資料是不用去更改的,只用作查詢。這樣子可以加快服務端的啟動速度(啟動時減少去載入模板表)。 使用redis和memcache,可以盡快的加快服務的啟動,使資料更加安全了。

以上的三幅都是用graphviz製作的,graphviz屬於語言作圖工具,設計的流程圖所想即所得。

面試所遇問題

一.python中元組合列表有什麼區別?python 的元組與列表類似,不同之處在於元組的元素不能修改,元組中的元素不能被刪除。元組使用小括號,列表使用方括號。二.c 中友元函式的作用?友元函式提供了不同類或物件的成員函式之間 類的成員函式和一般函式之間進行資料共享的機制。通俗的說,友元關係就是乙個...

工作所遇問題總結

入職後,單位給看的第乙個專案 是mfc程式,裡面利用cwintread類來生成乙個工作執行緒,而這個執行緒是可以接收訊息的,這讓我感覺很驚奇,居然還有這樣的技術?這個執行緒可以接收訊息,也可以利用postthreadmessage給主線程傳送訊息,真是讓我感覺新奇。我一定要弄明白,其中的道理!軟體狗...

Python學習所遇問題

print 遊戲開始 num input 猜數字 guess int num while guess 8 num input 猜錯啦請重新輸入 guess int num if guess 8 print 恭喜你猜對了 else if guess 8 print 偏大 else print 偏小 p...