缓存应用--Memcached分布式缓存简介(二)

1 命令行查看状态

  很多时候我们需要去查看Memcached 的使用状态,比如Memcached 的运行时间,使用状态等等。在Windows系统中我们可以使用telnet 命令来查看Memcached 的相关运行情况。

  开始—>运行àcmd 运行得到如下:

缓存应用--Memcached分布式缓存简介(二) 

输入telnet命令: telnet 服务地址 端口 

缓存应用--Memcached分布式缓存简介(二) 

Memcached 的默认端口号是11211
      输入stats 命令: 在这里屏幕是空白,看不到输入的内容,回车之后可以看到Memcached的运行相关信息。 

缓存应用--Memcached分布式缓存简介(二) 

Pid: Memcached 服务器中的进程编号

   UptimeMemcached服务器启动之后所经历的时间,单位秒

   Time 当前系统时间,单位秒

  Version: Memcached 的版本号

  pointer_size:服务器所在主机操作系统的指针大小,一般为3264

  curr_items:表示当前缓存中存放的所有缓存对象的数量

  total_items:表示从memcached服务启动到当前时间,系统存储过的所有对象的数量,包括已经删除的对象

  bytes:表示系统存储缓存对象所使用的存储空间,单位为字节

  curr_connections:表示当前系统打开的连接数

  total_connections:表示从memcached服务启动到当前时间,系统打开过的连接的总数

  cmd_get 查询缓存的次数,即使不成功也算一次

  cmd_set 保存数据的次数,当然这里只保存成功的次数

  get_hits:表示获取数据成功的次数。

  get_misses:表示获取数据失败的次数。

  evictions:为了给新的数据项目释放空间,从缓存移除的缓存对象的数目。比如超过缓存大小时根据LRU算法移除的对象,以及过期的对象

  bytes_readmemcached服务器从网络读取的总的字节数

  bytes_writtenmemcached服务器发送到网络的总的字节数

  limit_maxbytesmemcached服务缓存允许使用的最大字节数

  threads:被请求的工作线程的总数量

 

     缓存命中率 = get_hits / cmd_get * 100% ; 

 

 

2 Memcached 存储机制

       关于Memcached的存储机制,在网上搜了一下讲解基本上都是千篇一律的。

memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。在之前的版本中,Memcached存储会导致很多内存碎片,从而加重了操作系统对内存管理的负担。Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块, 以完全解决内存碎片问题。

 借用一张图说明一下: 

 

     缓存应用--Memcached分布式缓存简介(二)

Slab Allocation 将分配的内存分割成各种尺寸的chunk (),并把大小相同尺寸的chunk分为一组,就如上图一样:分割了 88b,112b,144b等尺寸。其实Slab Allocation还有重复利用内存的功能,也就是说分配的内存不会释放,而是重复利用。

当存储数据的时候,它会自动去查找最为匹配的chunk,然后将数据存储到其中。比如我存储数据的大小为110B,那么它会存储到112Bchunk中。

     上面的问题来了,我存储只需要110B,但是我存储到112Bchunk中。如下图(借用) 

缓存应用--Memcached分布式缓存简介(二) 

    那么在110b的存储中会浪费2B的内存空间
至于如何完全解决这个内存空间浪费的问题,还没有很好的方案,不过Memcached 增长因子(Growth Factor)能够适当解决此问题。目前Memcached的默认增长因子      是1.25,也就是说会以原有的最大值基础上乘以1.25 来分配空间。 

 

 

3 Memcached 对内存资源的有效利用

之前已经提到过了,Memcached 会重复利用已经分配的内存,也就是说不会去删除已有的数据而且释放内存空间,而是数据过期之后,用户将数据不可见。

         Memcached 还是用了一种Lazy Expiration (延迟过期[姑且这样翻译]) 技术,就是Memcached不会去监视服务器上的数据是否过期,而是等待get的时候检查时间戳是否过期,减少Memcached在监控数据上所用到的时间。

          Memcached 不会去释放已经使用的内存空间,但是如果分配的内存空间已经满了,而Memcached 是如何去保证内存空间的重复使用呢!Memcached 是用了 Least Recently UsedLRU 机制来协调内存空间的使用。LRU 意思就是最少最近使用,当此处内存空间数据最长时间没有使用,而且使用次数很少,在存储新的数据的同时就会覆盖此处空间。 

 

 

4 Memcached 客户端使用简单封装

本文很多都是理论上的分析,这些大多也是从网络上看来的,根据自己的理解和实际的应用做了一些总结。有时候我们使用Memcached的客户端时并不是那么的友好,这里对其做了一下简单的封装,抽象出来了一个接口:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Collections;
 6 
 7 namespace MemcachedTest
 8 {
 9     public interface ICache
10     {
11         bool ContainKey(string argKey);
12 
13         bool Add(string argKey,object argValue);
14 
15         bool Add(string argKey, object argValue, DateTime argDateExpiration);
16 
17         bool Add<T>(string argKey, T entity) where T : class;
18 
19         bool Add<T>(string argKey, T entity, DateTime argDateExpiration) where T : class;
20 
21         bool Set(string argKey, object argValue);
22 
23         bool Set(string argKey, object argValue, DateTime argDateExpiration);
24 
25         bool Set<T>(string argKey, T entity) where T : class;
26 
27         bool Set<T>(string argKey, T entity, DateTime argDateExpiration) where T : class;
28 
29         bool Replace(string argKey,object argValue);
30 
31         bool Replace(string argKey,object argValue,DateTime argDateExpiration);
32 
33         bool Replace<T>(string argKey, T entity) where T : class;
34 
35         bool Replace<T>(string argKey, T entity, DateTime argDateExpiration) where T : class;
36 
37         object Get(string argKey);
38 
39         T Get<T>(string argKey);
40 
41         bool Remove(string argKey);
42 
43         bool Remove(string argKey, DateTime argDateExpiration);
44 
45         bool Remove();
46 
47         bool Remove(ArrayList servers);
48 
49     }

50 } 

 

下面这段代码对上面的接口进行了实现,里面的代码大多数人应该能够看懂,是比较简单的代码封装,如果能够了解本人上一篇的简单应用,对于这个封装的理解应该没有难度。实现代码如下:

 

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using Memcached.ClientLibrary;
  6 using System.Collections;
  7 
  8 namespace MemcachedTest
  9 {
 10     public class Memcache:ICache
 11     {
 12         private MemcachedClient client;
 13         private static Memcache memcache;
 14 
 15         /// <summary>
 16         /// 构造方法
 17         /// </summary>
 18         protected Memcache()
 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 = new MemcachedClient();
 29             client.EnableCompression = false;
 30         }
 31 
 32         public static Memcache Instance()
 33         {
 34             if (memcache == null)
 35             {
 36                 memcache = new Memcache();
 37             }
 38             return memcache;
 39         }
 40 
 41 
 42         /// <summary>
 43         /// 判断是否包含某个键
 44         /// </summary>
 45         /// <param name="argKey">键值</param>
 46         /// <returns></returns>
 47         public bool ContainKey(string argKey)
 48         {
 49             return client.KeyExists(argKey);
 50         }
 51 
 52         /// <summary>
 53         /// 添加缓存数据
 54         /// </summary>
 55         /// <param name="argKey">键值</param>
 56         /// <param name="argValue">存储值</param>
 57         /// <returns></returns>
 58         public bool Add(string argKey, object argValue)
 59         {
 60             return client.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         public bool Add(string argKey, object argValue, DateTime argDateExpiration)
 71         {
 72             return client.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         public bool Add<T>(string argKey, T entity) where T : class
 83         {
 84             return client.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         public bool Add<T>(string argKey, T entity, DateTime argDateExpiration) where T : class
 96         {
 97             return client.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         public bool Set(string argKey, object argValue)
107         {
108             if (ContainKey(argKey))
109             {
110                 return false;
111             }
112             return client.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         public bool Set(string argKey, object argValue, DateTime argDateExpiration)
123         {
124             if (ContainKey(argKey))
125             {
126                 return false;
127             }
128             return client.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         public bool Set<T>(string argKey, T entity) where T : class
139         {
140             if (ContainKey(argKey))
141             {
142                 return false;
143             }
144             return client.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         public bool Set<T>(string argKey, T entity, DateTime argDateExpiration) where T : class
156         {
157             if (ContainKey(argKey))
158             {
159                 return false;
160             }
161             return client.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         public bool Replace(string argKey, object argValue)
172         {
173             return client.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         public bool Replace(string argKey, object argValue, DateTime argDateExpiration)
184         {
185             return client.Replace(argKey,argValue,argDateExpiration);
186         }
187 
188         public bool Replace<T>(string argKey, T entity) where T : class
189         {
190             return client.Replace(argKey,entity);
191         }
192 
193         public bool Replace<T>(string argKey, T entity, DateTime argDateExpiration) where T : class
194         {
195             return client.Replace(argKey, entity,argDateExpiration);
196         }
197 
198         public object Get(string argKey)
199         {
200             return client.Get(argKey);
201         }
202 
203         public T Get<T>(string argKey)
204         {
205             T entity=default(T);
206             entity = (T)client.Get(argKey);
207             return entity;
208         }
209 
210         public bool Remove(string argKey)
211         {
212             return client.Delete(argKey);
213         }
214 
215         public bool Remove(string argKey, DateTime argDateExpiration)
216         {
217             return client.Delete(argKey,argDateExpiration);
218         }
219 
220         public bool Remove()
221         {
222             return client.FlushAll();
223         }
224 
225         public bool Remove(ArrayList servers)
226         {
227             return client.FlushAll(servers);
228         }
229     }

230 } 

上面的代码没有注释,因为提交不了这么长的代码,去掉了注释。代码大家可以看懂的,这里不做过多的讲解。 

  学习例子源码下载 

 

 

上一篇:[Android]Activity启动过程


下一篇:我的博客即将入驻“云栖社区”,诚邀技术同仁一同入驻。