3ewsd 发表于 2015-9-2 10:34:27

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

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:被请求的工作线程的总数量
   缓存命中率 = get_hits / cmd_get * 100% ;
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在监控数据上所用到的时间。
          Memcached 不会去释放已经使用的内存空间,但是如果分配的内存空间已经满了,而Memcached 是如何去保证内存空间的重复使用呢!Memcached 是用了 Least Recently Used(LRU) 机制来协调内存空间的使用。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 }
  上面的代码没有注释,因为提交不了这么长的代码,去掉了注释。代码大家可以看懂的,这里不做过多的讲解。
   学习例子源码下载
页: [1]
查看完整版本: 缓存应用--Memcached分布式缓存简介(二)