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

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

1 命令行查看状态

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

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

 

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

 

Memcached 的默认端口号是11211
      输入stats 命令: 在这里屏幕是空白,看不到输入的内容,回车之后可以看到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的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块, 以完全解决内存碎片问题。

 借用一张图说明一下: 

 

     

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

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

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

 

    那么在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 } 

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

  学习例子源码下载 

 

 

相关文章
|
1月前
|
安全 大数据 Go
Go语言在分布式系统中的应用
【2月更文挑战第20天】Go语言,以其独特的语言特性和出色的性能,逐渐成为分布式系统开发领域的热门选择。本文将深入探讨Go语言在分布式系统中的应用,分析其优势及实际应用案例,旨在为开发人员提供有价值的参考与启示。
|
3月前
|
缓存 算法 NoSQL
【分布式详解】一致性算法、全局唯一ID、分布式锁、分布式事务、 分布式缓存、分布式任务、分布式会话
分布式系统通过副本控制协议,使得从系统外部读取系统内部各个副本的数据在一定的约束条件下相同,称之为副本一致性(consistency)。副本一致性是针对分布式系统而言的,不是针对某一个副本而言。强一致性(strong consistency):任何时刻任何用户或节点都可以读到最近一次成功更新的副本数据。强一致性是程度最高的一致性要求,也是实践中最难以实现的一致性。单调一致性(monotonic consistency):任何时刻,任何用户一旦读到某个数据在某次更新后的值,这个用户不会再读到比这个值更旧的值。
397 0
|
10天前
|
存储 缓存 NoSQL
缓存、分布式缓存和持久化
这篇内容介绍了缓存的概念和Redis的作用,以口袋与公文包的比喻解释了缓存如何提高数据访问速度。Redis是一个内存中的高级缓存系统,能提升系统响应速度。接着讨论了为何需要分布式缓存,通过多个“篮子”(Redis节点)解决单点故障和性能瓶颈,保证高可用性和数据安全性。最后提到了Redis的两种持久化机制——RDB(定期数据快照)和AOF(记录写操作日志),分别用照片备份和实时同步来比喻,说明它们在数据丢失风险和恢复速度上的权衡。
|
16天前
|
缓存 NoSQL 数据库
关于高并发下缓存失效的问题(本地锁 && 分布式锁 && Redission 详解)
关于高并发下缓存失效的问题(本地锁 && 分布式锁 && Redission 详解)
29 0
|
1月前
|
存储 缓存 运维
LAMP+Varnish缓存详解(一)——Varnish简介
LAMP+Varnish缓存详解(一)——Varnish简介
18 0
|
1月前
|
存储 缓存
本地缓存和分布式缓存区别
【2月更文挑战第16天】
38 2
本地缓存和分布式缓存区别
|
1月前
|
存储 缓存 算法
说说什么是本地缓存、分布式缓存以及多级缓存,它们各自的优缺点?
说说什么是本地缓存、分布式缓存以及多级缓存,它们各自的优缺点?
|
2月前
|
缓存 NoSQL Redis
如何在Python中使用Redis或Memcached进行缓存?
如何在Python中使用Redis或Memcached进行缓存?
28 2
|
3月前
|
NoSQL 安全 Redis
解决秒杀系统库存超卖问题:乐观锁与Redis分布式锁的应用
解决秒杀系统库存超卖问题:乐观锁与Redis分布式锁的应用
446 0
|
3月前
|
存储 缓存 大数据
本地缓存和分布式缓存
本地缓存和分布式缓存
65 0