1 命令行查看状态
很多时候我们需要去查看Memcached 的使用状态,比如Memcached 的运行时间,使用状态等等。在Windows系统中我们可以使用telnet 命令来查看Memcached 的相关运行情况。
开始—>运行àcmd 运行得到如下:
输入telnet命令: telnet 服务地址 端口
Memcached 的默认端口号是11211
输入stats 命令: 在这里屏幕是空白,看不到输入的内容,回车之后可以看到Memcached的运行相关信息。
Pid: Memcached 服务器中的进程编号
Uptime:Memcached服务器启动之后所经历的时间,单位秒
Time: 当前系统时间,单位秒
Version: Memcached 的版本号
pointer_size:服务器所在主机操作系统的指针大小,一般为32或64
curr_items:表示当前缓存中存放的所有缓存对象的数量
total_items:表示从memcached服务启动到当前时间,系统存储过的所有对象的数量,包括已经删除的对象
bytes:表示系统存储缓存对象所使用的存储空间,单位为字节
curr_connections:表示当前系统打开的连接数
total_connections:表示从memcached服务启动到当前时间,系统打开过的连接的总数
cmd_get: 查询缓存的次数,即使不成功也算一次
cmd_set: 保存数据的次数,当然这里只保存成功的次数
get_hits:表示获取数据成功的次数。
get_misses:表示获取数据失败的次数。
evictions:为了给新的数据项目释放空间,从缓存移除的缓存对象的数目。比如超过缓存大小时根据LRU算法移除的对象,以及过期的对象
bytes_read:memcached服务器从网络读取的总的字节数
bytes_written:memcached服务器发送到网络的总的字节数
limit_maxbytes:memcached服务缓存允许使用的最大字节数
threads:被请求的工作线程的总数量
2 Memcached 存储机制
关于Memcached的存储机制,在网上搜了一下讲解基本上都是千篇一律的。
memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。在之前的版本中,Memcached存储会导致很多内存碎片,从而加重了操作系统对内存管理的负担。Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块, 以完全解决内存碎片问题。
Slab Allocation 将分配的内存分割成各种尺寸的chunk (块),并把大小相同尺寸的chunk分为一组,就如上图一样:分割了 88b,112b,144b等尺寸。其实Slab Allocation还有重复利用内存的功能,也就是说分配的内存不会释放,而是重复利用。
当存储数据的时候,它会自动去查找最为匹配的chunk,然后将数据存储到其中。比如我存储数据的大小为110B,那么它会存储到112B的chunk中。
上面的问题来了,我存储只需要110B,但是我存储到112B的chunk中。如下图(借用):
那么在110b的存储中会浪费2B的内存空间
至于如何完全解决这个内存空间浪费的问题,还没有很好的方案,不过Memcached的 增长因子(Growth Factor)能够适当解决此问题。目前Memcached的默认增长因子 是1.25,也就是说会以原有的最大值基础上乘以1.25 来分配空间。
3 Memcached 对内存资源的有效利用
之前已经提到过了,Memcached 会重复利用已经分配的内存,也就是说不会去删除已有的数据而且释放内存空间,而是数据过期之后,用户将数据不可见。
Memcached 还是用了一种Lazy Expiration (延迟过期[姑且这样翻译]) 技术,就是Memcached不会去监视服务器上的数据是否过期,而是等待get的时候检查时间戳是否过期,减少Memcached在监控数据上所用到的时间。
4 Memcached 客户端使用简单封装
本文很多都是理论上的分析,这些大多也是从网络上看来的,根据自己的理解和实际的应用做了一些总结。有时候我们使用Memcached的客户端时并不是那么的友好,这里对其做了一下简单的封装,抽象出来了一个接口:
2 usingSystem.Collections.Generic;
3 usingSystem.Linq;
4 usingSystem.Text;
5 usingSystem.Collections;
6
7 namespaceMemcachedTest
8 {
9 publicinterfaceICache
10 {
11 boolContainKey(stringargKey);
12
13 boolAdd(stringargKey,objectargValue);
14
15 boolAdd(stringargKey, objectargValue, DateTime argDateExpiration);
16
17 boolAdd<T>(stringargKey, T entity) whereT : class;
18
19 boolAdd<T>(stringargKey, T entity, DateTime argDateExpiration) whereT : class;
20
21 boolSet(stringargKey, objectargValue);
22
23 boolSet(stringargKey, objectargValue, DateTime argDateExpiration);
24
25 boolSet<T>(stringargKey, T entity) whereT : class;
26
27 boolSet<T>(stringargKey, T entity, DateTime argDateExpiration) whereT : class;
28
29 boolReplace(stringargKey,objectargValue);
30
31 boolReplace(stringargKey,objectargValue,DateTime argDateExpiration);
32
33 boolReplace<T>(stringargKey, T entity) whereT : class;
34
35 boolReplace<T>(stringargKey, T entity, DateTime argDateExpiration) whereT : class;
36
37 objectGet(stringargKey);
38
39 T Get<T>(stringargKey);
40
41 boolRemove(stringargKey);
42
43 boolRemove(stringargKey, DateTime argDateExpiration);
44
45 boolRemove();
46
47 boolRemove(ArrayList servers);
48
49 }
50 }
下面这段代码对上面的接口进行了实现,里面的代码大多数人应该能够看懂,是比较简单的代码封装,如果能够了解本人上一篇的简单应用,对于这个封装的理解应该没有难度。实现代码如下:
2 usingSystem.Collections.Generic;
3 usingSystem.Linq;
4 usingSystem.Text;
5 usingMemcached.ClientLibrary;
6 usingSystem.Collections;
7
8 namespaceMemcachedTest
9 {
10 publicclassMemcache:ICache
11 {
12 privateMemcachedClient client;
13 privatestaticMemcache memcache;
14
15 ///<summary>
16 ///构造方法
17 ///</summary>
18 protectedMemcache()
19 {
20 SockIOPool pool =SockIOPool.GetInstance();
21 string[] servers ={ "127.0.0.1:11211"};
22 pool.SetServers(servers);
23 pool.MinConnections =3;
24 pool.MaxConnections =5;
25 pool.InitConnections =3;
26 pool.SocketConnectTimeout =5000;
27 pool.Initialize();
28 this.client =newMemcachedClient();
29 client.EnableCompression =false;
30 }
31
32 publicstaticMemcache Instance()
33 {
34 if(memcache ==null)
35 {
36 memcache =newMemcache();
37 }
38 returnmemcache;
39 }
40
41
42 ///<summary>
43 ///判断是否包含某个键
44 ///</summary>
45 ///<param name="argKey">键值</param>
46 ///<returns></returns>
47 publicboolContainKey(stringargKey)
48 {
49 returnclient.KeyExists(argKey);
50 }
51
52 ///<summary>
53 ///添加缓存数据
54 ///</summary>
55 ///<param name="argKey">键值</param>
56 ///<param name="argValue">存储值</param>
57 ///<returns></returns>
58 publicboolAdd(stringargKey, objectargValue)
59 {
60 returnclient.Add(argKey,argValue);
61 }
62
63 ///<summary>
64 ///添加缓存数据
65 ///</summary>
66 ///<param name="argKey">键值</param>
67 ///<param name="argValue">存储值</param>
68 ///<param name="argDateExpiration">过期时间</param>
69 ///<returns></returns>
70 publicboolAdd(stringargKey, objectargValue, DateTime argDateExpiration)
71 {
72 returnclient.Add(argKey, argValue, argDateExpiration);
73 }
74
75 ///<summary>
76 ///添加缓存数据
77 ///</summary>
78 ///<typeparam name="T">存储对象类型</typeparam>
79 ///<param name="argKey">键值</param>
80 ///<param name="entity">存储值</param>
81 ///<returns></returns>
82 publicboolAdd<T>(stringargKey, T entity) whereT : class
83 {
84 returnclient.Add(argKey, entity);
85 }
86
87 ///<summary>
88 ///添加缓存数据
89 ///</summary>
90 ///<typeparam name="T">存储对象类型</typeparam>
91 ///<param name="argKey">键值</param>
92 ///<param name="entity">存储值</param>
93 ///<param name="argDateExpiration">过期时间</param>
94 ///<returns></returns>
95 publicboolAdd<T>(stringargKey, T entity, DateTime argDateExpiration) whereT : class
96 {
97 returnclient.Add(argKey, entity, argDateExpiration);
98 }
99
100 ///<summary>
101 ///添加缓存数据,如果存在则替换原有数据
102 ///</summary>
103 ///<param name="argKey">键值</param>
104 ///<param name="argValue">存储值</param>
105 ///<returns></returns>
106 publicboolSet(stringargKey, objectargValue)
107 {
108 if(ContainKey(argKey))
109 {
110 returnfalse;
111 }
112 returnclient.Set(argKey, argValue);
113 }
114
115 ///<summary>
116 ///添加缓存数据,如果存在则替换原有数据
117 ///</summary>
118 ///<param name="argKey">键值</param>
119 ///<param name="argValue">存储值</param>
120 ///<param name="argDateExpiration">过期时间</param>
121 ///<returns></returns>
122 publicboolSet(stringargKey, objectargValue, DateTime argDateExpiration)
123 {
124 if(ContainKey(argKey))
125 {
126 returnfalse;
127 }
128 returnclient.Set(argKey, argValue, argDateExpiration);
129 }
130
131 ///<summary>
132 ///添加缓存数据,如果存在则替换原有数据
133 ///</summary>
134 ///<typeparam name="T">存储对象类型</typeparam>
135 ///<param name="argKey">键值</param>
136 ///<param name="entity">存储值</param>
137 ///<returns></returns>
138 publicboolSet<T>(stringargKey, T entity) whereT : class
139 {
140 if(ContainKey(argKey))
141 {
142 returnfalse;
143 }
144 returnclient.Set(argKey, entity);
145 }
146
147 ///<summary>
148 ///添加缓存数据,如果存在则替换原有数据
149 ///</summary>
150 ///<typeparam name="T">存储对象类型</typeparam>
151 ///<param name="argKey">键值</param>
152 ///<param name="entity">存储值</param>
153 ///<param name="argDateExpiration">过期时间</param>
154 ///<returns></returns>
155 publicboolSet<T>(stringargKey, T entity, DateTime argDateExpiration) whereT : class
156 {
157 if(ContainKey(argKey))
158 {
159 returnfalse;
160 }
161 returnclient.Set(argKey, entity, argDateExpiration);
162 }
163
164
165 ///<summary>
166 ///替换原有缓存
167 ///</summary>
168 ///<param name="argKey">键值</param>
169 ///<param name="argValue">存储值</param>
170 ///<returns></returns>
171 publicboolReplace(stringargKey, objectargValue)
172 {
173 returnclient.Replace(argKey,argValue);
174 }
175
176 ///<summary>
177 ///替换原有缓存
178 ///</summary>
179 ///<param name="argKey">键值</param>
180 ///<param name="argValue">存储值</param>
181 ///<param name="argDateExpiration">过期时间</param>
182 ///<returns></returns>
183 publicboolReplace(stringargKey, objectargValue, DateTime argDateExpiration)
184 {
185 returnclient.Replace(argKey,argValue,argDateExpiration);
186 }
187
188 publicboolReplace<T>(stringargKey, T entity) whereT : class
189 {
190 returnclient.Replace(argKey,entity);
191 }
192
193 publicboolReplace<T>(stringargKey, T entity, DateTime argDateExpiration) whereT : class
194 {
195 returnclient.Replace(argKey, entity,argDateExpiration);
196 }
197
198 publicobjectGet(stringargKey)
199 {
200 returnclient.Get(argKey);
201 }
202
203 publicT Get<T>(stringargKey)
204 {
205 T entity=default(T);
206 entity =(T)client.Get(argKey);
207 returnentity;
208 }
209
210 publicboolRemove(stringargKey)
211 {
212 returnclient.Delete(argKey);
213 }
214
215 publicboolRemove(stringargKey, DateTime argDateExpiration)
216 {
217 returnclient.Delete(argKey,argDateExpiration);
218 }
219
220 publicboolRemove()
221 {
222 returnclient.FlushAll();
223 }
224
225 publicboolRemove(ArrayList servers)
226 {
227 returnclient.FlushAll(servers);
228 }
229 }
230 }
上面的代码没有注释,因为提交不了这么长的代码,去掉了注释。代码大家可以看懂的,这里不做过多的讲解。
学习例子源码下载