自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

關(guān)于Memcached客戶端CPU過高問題的排查

數(shù)據(jù)庫
對于Mencached分布式存儲系統(tǒng),大家應(yīng)用得還比較多,但是經(jīng)常會遇到一些問題。本文將介紹CPU過高的問題處理方法。

公司網(wǎng)站使用了Memcached來做分布式緩存,最近有人反映Memcached客戶端占用CPU過高,懷疑是第三方客戶端性能不佳,進(jìn)而懷疑是文本協(xié)議的問題,要求部門自己開發(fā)Memcached的客戶端,使其支持二進(jìn)制協(xié)議。因為重新開發(fā)客戶端工作量比較大,同時在日常開發(fā)中,沒有聽說過Memcached客戶端遇到瓶頸。因此對此問題進(jìn)行了排查。結(jié)果發(fā)現(xiàn)主要是由于客戶端反序列化,類設(shè)計不合理造成的。把排查過程分享下,希望對其他人有所幫助。 

首先想到是:Memcached服務(wù)器端內(nèi)存占滿,在清理內(nèi)存中,造成客戶端socket連接不上,不斷發(fā)生異常。隨上服務(wù)器查看了Memcached的內(nèi)存占用率,連接數(shù)等,發(fā)現(xiàn)利用率均很低。暫時先排除服務(wù)器端問題。 

其次想到可能是第三方在使用socket連接池時,造成資源沒有關(guān)閉,或者死鎖。隨對第三方客戶端代碼粗略讀了一遍,并搜索相關(guān)文檔。未發(fā)現(xiàn)異常代碼。暫時先排除第三方客戶端問題。 

最后想到會不會是開發(fā)人員在代碼編寫中出現(xiàn)了問題。隨對反映問題的兩個產(chǎn)品進(jìn)行了排查。發(fā)現(xiàn)了以下代碼。

  1. static Serializer ser = new Serializer(typeof(List<UserModule>)); 
  2. //using JsonExSerializer;  
  3. public static List<UserModule> GetAllUserModule(int userId)  
  4. {  
  5.     string cache = CacheManager.Current.Get<string>(GetCacheKey(userId));  
  6.     if (!string.IsNullOrEmpty(cache))  
  7.     {  
  8.         return ser.Deserialize(cache) as List<UserModule>;  
  9.     }  
  10.     else 
  11.     {  
  12.         return null;  
  13.     }  
  14. }  
  15.  
  16. public static List<UserModule> SetAllUserModule(int userId, List<UserModule> modules)  
  17. {  
  18.     if (modules != null)  
  19.     {  
  20.         string cache = ser.Serialize(modules);  
  21.         CacheManager.Current.Add(GetCacheKey(userId), cache);  
  22.     }  
  23.     else 
  24.     {  
  25.         CacheManager.Current.Remove(GetCacheKey(userId));  
  26.     }  
  27.     return modules;  

代碼片段2  

  1. /// <summary>  
  2. /// 聊天室房間  
  3. /// </summary>  
  4. [Serializable]  
  5. public class Room  
  6. {  
  7.     //房間有觀看人員數(shù)據(jù)  
  8.     List<Viewer> _viewers = null;  
  9.     List<string> _blackips = null;  
  10.     List<Viewer> _blackviewers = null;  
  11.     List<Notice> _notice = null;  
  12.     List<Speaker > _speakers = null;  
  13.     List<Content> _content = null;  
  14.  
  15.  
  16.     /// <summary>  
  17.     /// 添加新聊天者  
  18.     /// </summary>  
  19.     /// <returns>返回新添加的聊天人員</returns>  
  20.     public Viewer AddViewer()  
  21.     {  
  22.         Viewer vi = new Viewer();  
  23.         //MaxViewerID += 1;  
  24.           
  25.         //int id = MaxViewerID;   
  26.         int id = GetViewerID();   
  27.         vi.Name = GetViewerName("游客" + id);  
  28.         //vi.IP = System.Web.HttpContext.Current.Request.UserHostAddress;  
  29.         vi.IP = "127.0.0.1";  
  30.         vi.ViewID = id;  
  31.         Viewers.Add(vi);  
  32.         return vi;   
  33.     }  
  34.  
  35. /// <summary>  
  36.     /// 添加聊天內(nèi)容  
  37.     /// </summary>  
  38.     /// <param name="content">聊天的內(nèi)容</param>  
  39.     /// <param name="viewid">發(fā)言人的id</param>  
  40.     /// <returns>返回新添加的對象</returns>  
  41.     public Content AddContent(string content, int viewid)  
  42.     {  
  43.         MaxContentID += 1;  
  44.         Content con = new Content(DateTime.Now, content, viewid, MaxContentID);  
  45.         Contents.Add(con);  
  46.         return con;  
  47.     }  
  48.     ......  

調(diào)用代碼為:

  1. Room room = LiveSys.Get(key);  
  2. lock (room)  
  3. {  
  4.     if (room.MaxContentID == 0)  
  5.     {  
  6.         //ChatContentOp cpo = new ChatContentOp();  
  7.         //room.MaxContentID = cpo.GetMaxContentID();  
  8.  
  9.         room.MaxContentID = 300;  
  10.     }  
  11.     int viewerID = 123124123;  
  12.     room.AddContent(chatContent, viewerID);  
  13.     //判斷內(nèi)容是否大于100條。如果大于100條,刪除最近的100條以外的數(shù)據(jù)。  
  14.     System.IO.File.AppendAllText(@"d:\haha.txt""最大數(shù)值:" + 
  15. room.LimitContentCount + "###############聊天記錄數(shù):" + room.Contents.Count + "\r\n");  
  16.     if (room.Contents.Count > room.LimitContentCount)  
  17.     {  
  18.         room.Contents.RemoveRange(0, room.Contents.Count - room.LimitContentCount);  
  19.     }  
  20. }  
  21. LiveSys.Set(key, room); 

代碼1存在的問題是:

Cache存儲的參數(shù)類型為object,沒有必要先進(jìn)行一次序列化,然后再進(jìn)行存儲。而序列化是很消耗CPU的。

代碼2問題:

代碼2實現(xiàn)的是一個在線聊天室,聊天室本身含有訪客,發(fā)言等內(nèi)容。在發(fā)言時,對聊天室內(nèi)容進(jìn)行判斷,只顯示最近30條。新進(jìn)來訪客直接加到訪客別表中。表面上是沒什么問題的。但是細(xì)想之下有兩個問題:

1 聊天室類設(shè)計的比較復(fù)雜,每次從Memcached服務(wù)端取得數(shù)據(jù)后,都要進(jìn)行類型轉(zhuǎn)換。

2 沒有訪客清理機(jī)制。隨著訪客的不斷進(jìn)入,對象的體積會不斷增大。

對存疑部分編寫了代碼進(jìn)行測試。測試結(jié)果果然如推測所想。測試結(jié)果如下:

場景

寫入

讀取

大小

(單位)

CPU

次數(shù)

時間

平均

次數(shù)

時間

平均

本地緩存

10000

0.03125

0

10000

0

0

1k

0

MemClient

10000

19.2656

0.001926

10000

22.75

0.002275

1k

 

Json1k

1000

2.8437

0.002843

1000

5.375

0.005375

1k

 

Json8k

1000

3.8593

0.003859

1000

29.0312

0.029031

8k

 

直播1000人次

1000

38.9375

0.038937

1000

 

 

50k

 

直播8000人次

100

18.25

0.1825

100

 

 

350k

 

500k

100

7.375

0.07375

100

7.09375

0.070937

500k

 

場景

寫入

讀取

大小

(單位)

CPU

次數(shù)

時間

平均

次數(shù)

時間

平均

本地緩存

10000

0.03125

3.125E-06

10000

0.015625

1.5625E-06

1k

0

MemClient

10000

19.78125

0.001978

10000

21.953125

0.002195

1k

 

Json1k

1000

2.03125

0.002031

1000

6.078125

0.006078

1k

 

Json8k

1000

2.765625

0.002765

1000

55.375

0.055375

8k

 

直播1000人次

1000

38.53125

0.038531

1000

   

50k

 

直播8000人次

100

17.96875

0.179687

1000

   

350k

 

500k

100

7.5

0.075

100

6.5625

0.065625

500k

 

場景

寫入

讀取

大小

(單位)

CPU

次數(shù)

時間

平均

次數(shù)

時間

平均

本地緩存

10000

0.015625

1.5625E-06

10000

0.015625

1.5625E-06

1k

0

MemClient

10000

18.015625

0.001801

10000

25.96875

0.002596

1k

6%

Json1k

1000

1.15625

0.001156

1000

3.078125

0.003078

1k

40%

Json8k

1000

1.859375

0.001859

1000

32.484375

0.032484

8k

50%

直播1000人次

1000

45.046875

0.045046

1000

   

50k

30-40%

直播8000人次

100

31.703125

0.317031

100

   

350k

50%

500k

100

7.0625

0.070625

100

6.421875

0.064218

500k

6%

直播1000人次(當(dāng)天一共有1000人訪問,數(shù)據(jù)來源于運營檢測),留言內(nèi)容為30條時,Room體積大概為:57K  

直播1000人次(當(dāng)天一共有8000人訪問,數(shù)據(jù)來源于運營檢測),留言內(nèi)容為30條時,Room體積大概為:350k

 

根據(jù)圖表可以看到以下情況:處理時間、CPU利用率和數(shù)據(jù)量大小,序列化,類復(fù)雜性都有關(guān)系。

序列化問題(類型轉(zhuǎn)換)對性能影響最為明顯(可在場景”json1k”、場景直播中看到)。在Json1k中,存儲對象和前幾個場景是相同的,處理時間也相差不大,較大區(qū)別是CPU利用率由5%左右增長到40%左右(反序列化時尤為明顯)。在場景直播系統(tǒng)中,不存在序列化問題,但是其對象屬性中存在訪客,繁衍等多個復(fù)雜對象,造成其在處理時需要處理過多的類型轉(zhuǎn)換,同時其體積不斷增大。

存儲對象的大小和處理時間存在一定關(guān)系,例如場景”500k”,其處理時間增長,但是其CPU利用率并未提高,其時間增長是由于對象傳輸造成。

本地緩存在內(nèi)存中進(jìn)行尋址和類型轉(zhuǎn)換,涉及不到Socket連接,網(wǎng)絡(luò)傳輸,序列化操作,所以其處理相當(dāng)快。

就測試結(jié)果看:

本地緩存性能大約是分布式緩存性能的100倍左右。而出問題的聊天室除了CPU增高以外,其性能更比分布式緩存再降低40倍(直播1000人次)到200倍(直播8000人次)。綜合來看,聊天室的分布式緩存比本地緩存降了4000倍,甚至更多。

但是,還沒有完。 

對于第二個問題,更改類設(shè)計,清楚無效訪客,即可解決。 

但是第一個問題,為什么用戶在存儲之前,先進(jìn)行json序列化呢?嗯,這是一個問題。

遂問之。

答曰,有些類直接使用第三方客戶端存儲時,直接存儲報錯,所以先序列化為json類型,取值時再反序列化回來。

嗯,還有這事?

開發(fā)人員說了相關(guān)代碼。 

  1. interface IUser  
  2. {  
  3.     String UserId{ getset;}  
  4.     String UserName{ getset;}  
  5. }  
  6.  
  7. [Serializable]  
  8. class UserInfo : IUser  
  9. {  
  10.     String UserId{ getset;}  
  11.     String UserName{ getset;}  
  12. }  
  13. [Serializable]  
  14. class Game  
  15. {  
  16.     IUser User{ getset;}  
  17.     String UserName{ getset;}  

他說:Game對象在直接使用MemcachedClient時,是不能被二進(jìn)制序列化的,因為其User屬性類型為IUser,為一個接口。因此想了一個解決方法,即先將Game對象進(jìn)行 json序列化將其變?yōu)樽址?,然后將字符串存儲?/span>Memcached。 

原來是這樣。

接著又查看了MemcachedClient源代碼,其需要將對象進(jìn)行二進(jìn)制序列化,然后進(jìn)行存儲。接口屬性不能被序列化,遂又對序列化問題進(jìn)行了測試(見附件)。測試結(jié)果顯示上述代碼直接進(jìn)行二進(jìn)制序列化是可以的,同時直接使用第三方客戶端也是可以可行的。 

問題出在哪?難道是沒有加[Serializable]。

一查果然:一個Serializable引發(fā)的血案。。。

記得有人說過,慎用分布式,能不用盡量不用。

一方面在性能上確實下降很多,分布式存儲主要性能消耗在以下幾個方面:協(xié)議解析,Socket連接,數(shù)據(jù)傳輸,序列化/類型轉(zhuǎn)換。

一方面在使用場景和類設(shè)計上要求也更加嚴(yán)格。個人認(rèn)為Memcached是不太適合存儲特別大的文件的。雖然有人說網(wǎng)上已經(jīng)有用來存儲視頻的。

還有幾個問題希望知道的朋友回答下:

1 有沒有.Net方面的Memcached客戶端支持二進(jìn)制協(xié)議和一致性的?

2 測試中發(fā)現(xiàn),當(dāng)Memcached設(shè)置緩存過小時(例如64M),當(dāng)其內(nèi)存使用已經(jīng)到62M時,再進(jìn)行存儲,新存儲的內(nèi)容再取出來就是空值,不知道是什么原因。

原文標(biāo)題:Memcached客戶端CPU過高問題的排查

鏈接:http://www.cnblogs.com/hellofox2000/archive/2010/08/17/1801329.html

【編輯推薦】

  1. 分布式緩存系統(tǒng)Memcached入門指導(dǎo)
  2. .NET分布式緩存之Memcached執(zhí)行速度檢測
  3. 從Memcached看MySQL和關(guān)系數(shù)據(jù)庫的未來
  4. 分布式緩存系統(tǒng)Memcached簡介與實踐
  5. Google App Engine的Java持久性與數(shù)據(jù)存儲
責(zé)任編輯:彭凡 來源: 博客園
相關(guān)推薦

2019-04-29 14:23:46

Java服務(wù)器CPU

2009-11-25 13:21:30

PHP作為memcac

2011-06-28 09:09:57

JavaMemcached

2010-07-12 10:05:08

MemcachedPHP

2011-11-30 14:21:19

Java分布式緩存

2020-11-02 09:25:33

CPUJava線程

2021-09-22 15:46:29

虛擬桌面瘦客戶端胖客戶端

2018-11-26 08:49:42

CPU排查負(fù)載

2021-11-14 15:14:44

虛擬桌面顯示器IT

2011-03-21 14:53:36

Nagios監(jiān)控Linux

2011-04-06 14:24:20

Nagios監(jiān)控Linux

2011-08-17 10:10:59

2009-11-05 13:08:44

WCF客戶端配置

2010-03-16 17:53:43

無線客戶端NIC

2010-05-31 10:11:32

瘦客戶端

2011-10-26 13:17:05

2011-03-02 14:36:24

Filezilla客戶端

2010-12-21 11:03:15

獲取客戶端證書

2011-03-24 13:00:31

配置nagios客戶端

2010-07-19 16:30:19

Telnet客戶端
點贊
收藏

51CTO技術(shù)棧公眾號