缓存应用--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 } 

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

  学习例子源码下载 

 

 

相关文章
|
8月前
|
缓存 NoSQL 关系型数据库
Redis缓存和分布式锁
Redis 是一种高性能的键值存储系统,广泛用于缓存、消息队列和内存数据库。其典型应用包括缓解关系型数据库压力,通过缓存热点数据提高查询效率,支持高并发访问。此外,Redis 还可用于实现分布式锁,解决分布式系统中的资源竞争问题。文章还探讨了缓存的更新策略、缓存穿透与雪崩的解决方案,以及 Redlock 算法等关键技术。
|
12月前
|
安全 JavaScript 前端开发
HarmonyOS NEXT~HarmonyOS 语言仓颉:下一代分布式开发语言的技术解析与应用实践
HarmonyOS语言仓颉是华为专为HarmonyOS生态系统设计的新型编程语言,旨在解决分布式环境下的开发挑战。它以“编码创造”为理念,具备分布式原生、高性能与高效率、安全可靠三大核心特性。仓颉语言通过内置分布式能力简化跨设备开发,提供统一的编程模型和开发体验。文章从语言基础、关键特性、开发实践及未来展望四个方面剖析其技术优势,助力开发者掌握这一新兴工具,构建全场景分布式应用。
1013 35
|
存储 缓存 NoSQL
缓存加速新玩法,让你的应用飞起来
本文主要叙述如何运用云数据库 Tair 构建缓存,助力应用提速、优化性能。
|
11月前
|
分布式计算 Java 大数据
Java 大视界 —— 基于 Java 的大数据分布式计算在气象数据处理与天气预报中的应用进展(176)
本文围绕基于 Java 的大数据分布式计算在气象数据处理与天气预报中的应用展开,剖析行业现状与挑战,阐释技术原理,介绍其在数据处理及天气预报中的具体应用,并结合实际案例展示实施效果。
|
缓存 NoSQL Java
Redis应用—8.相关的缓存框架
本文介绍了Ehcache和Guava Cache两个缓存框架及其使用方法,以及如何自定义缓存。主要内容包括:Ehcache缓存框架、Guava Cache缓存框架、自定义缓存。总结:Ehcache适合用作本地缓存或与Redis结合使用,Guava Cache则提供了更灵活的缓存管理和更高的并发性能。自定义缓存可以根据具体需求选择不同的数据结构和引用类型来实现特定的缓存策略。
936 16
Redis应用—8.相关的缓存框架
Java 大视界 -- 基于 Java 的大数据分布式存储在视频监控数据管理中的应用优化(170)
本文围绕基于 Java 的大数据分布式存储在视频监控数据管理中的应用展开,分析管理现状与挑战,阐述技术应用,结合案例和代码给出实操方案。
|
存储 缓存 Java
Java中的分布式缓存与Memcached集成实战
通过在Java项目中集成Memcached,可以显著提升系统的性能和响应速度。合理的缓存策略、分布式架构设计和异常处理机制是实现高效缓存的关键。希望本文提供的实战示例和优化建议能够帮助开发者更好地应用Memcached,实现高性能的分布式缓存解决方案。
288 9
|
缓存 NoSQL PHP
用装饰器模式实现多层缓存:让PHP应用更快更稳
通过装饰器模式实现PHP多层缓存架构,详解如何利用内存、Redis、文件缓存组合提升应用性能。包含设计思路、代码示例与实战效果对比,助您构建高效缓存策略。
|
机器学习/深度学习 存储
DeepSeek进阶开发与应用4:DeepSeek中的分布式训练技术
随着深度学习模型和数据集规模的扩大,单机训练已无法满足需求,分布式训练技术应运而生。DeepSeek框架支持数据并行和模型并行两种模式,通过将计算任务分配到多个节点上并行执行,显著提高训练效率。本文介绍DeepSeek中的分布式训练技术,包括配置与启动方法,帮助用户轻松实现大规模模型训练。数据并行通过`MirroredStrategy`同步梯度,适用于大多数模型;模型并行则通过`ParameterServerStrategy`异步处理大模型。DeepSeek简化了分布式环境配置,支持单机多卡和多机多卡等场景。
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
330 5