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

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

  学习例子源码下载 

 

 

相关文章
|
16天前
|
缓存 NoSQL 数据库
运用云数据库 Tair 构建缓存为应用提速,完成任务得苹果音响、充电套装等好礼!
本活动将带大家了解云数据库 Tair(兼容 Redis),通过体验构建缓存以提速应用,完成任务,即可领取罗马仕安卓充电套装,限量1000个,先到先得。邀请好友共同参与活动,还可赢取苹果 HomePod mini、小米蓝牙耳机等精美好礼!
|
30天前
|
存储 缓存 数据库
缓存技术有哪些应用场景呢
【10月更文挑战第19天】缓存技术有哪些应用场景呢
|
1月前
|
人工智能 文字识别 Java
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
尼恩,一位拥有20年架构经验的老架构师,通过其深厚的架构功力,成功指导了一位9年经验的网易工程师转型为大模型架构师,薪资逆涨50%,年薪近80W。尼恩的指导不仅帮助这位工程师在一年内成为大模型架构师,还让他管理起了10人团队,产品成功应用于多家大中型企业。尼恩因此决定编写《LLM大模型学习圣经》系列,帮助更多人掌握大模型架构,实现职业跃迁。该系列包括《从0到1吃透Transformer技术底座》、《从0到1精通RAG架构》等,旨在系统化、体系化地讲解大模型技术,助力读者实现“offer直提”。此外,尼恩还分享了多个技术圣经,如《NIO圣经》、《Docker圣经》等,帮助读者深入理解核心技术。
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
|
2月前
|
缓存 NoSQL Java
谷粒商城笔记+踩坑(12)——缓存与分布式锁,Redisson+缓存数据一致性
缓存与分布式锁、Redisson分布式锁、缓存数据一致性【必须满足最终一致性】
126 14
谷粒商城笔记+踩坑(12)——缓存与分布式锁,Redisson+缓存数据一致性
|
1月前
|
存储 缓存 NoSQL
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
64 4
|
1月前
|
缓存 移动开发 前端开发
HTML5 应用程序缓存详解
HTML5 应用程序缓存(Application Cache)通过缓存 HTML、JavaScript、CSS 和图像等资源,使 Web 应用能在离线状态下运行。它利用 Manifest 文件(`.appcache`)定义缓存资源列表,浏览器会在加载页面时下载并缓存这些资源。此外,应用程序缓存还提供了事件处理机制,允许开发者监控缓存状态并进行手动管理。尽管这一技术已被视为过时,建议使用 Service Workers 和 Cache API 等现代替代方案来实现更强大的离线功能和缓存控制。
|
2月前
|
缓存 JavaScript 中间件
优化Express.js应用程序性能:缓存策略、请求压缩和路由匹配
在开发Express.js应用时,采用合理的缓存策略、请求压缩及优化路由匹配可大幅提升性能。本文介绍如何利用`express.static`实现缓存、`compression`中间件压缩响应数据,并通过精确匹配、模块化路由及参数化路由提高路由处理效率,从而打造高效应用。
161 9
|
2月前
|
存储 NoSQL Java
分布式session-SpringSession的应用
Spring Session 提供了一种创建和管理 Servlet HttpSession 的方案,默认使用外置 Redis 存储 Session 数据,解决了 Session 共享问题。其特性包括:API 及实现用于管理用户会话、以应用容器中性方式替换 HttpSession、简化集群会话支持、管理单个浏览器实例中的多个用户会话以及通过 headers 提供会话 ID 以使用 RESTful API。Spring Session 通过 SessionRepositoryFilter 实现,拦截请求并转换 request 和 response 对象,从而实现 Session 的创建与管理。
分布式session-SpringSession的应用
|
2月前
|
存储 NoSQL Java
分布式session-SpringSession的应用
Spring Session 提供了一种创建和管理 Servlet HttpSession 的方案,默认使用外置 Redis 存储 Session 数据,解决 Session 共享问题。其主要特性包括:提供 API 和实现来管理用户会话,以中立方式替换应用程序容器中的 HttpSession,简化集群会话支持,并在单个浏览器实例中管理多个用户会话。此外,Spring Session 允许通过 headers 提供会话 ID 以使用 RESTful API。结合 Spring Boot 使用时,可通过配置 Redis 依赖和支持缓存的依赖实现 Session 共享。
分布式session-SpringSession的应用
|
2月前
|
机器学习/深度学习 缓存 NoSQL
深度学习在图像识别中的应用与挑战后端开发中的数据缓存策略
本文深入探讨了深度学习技术在图像识别领域的应用,包括卷积神经网络(CNN)的原理、常见模型如ResNet和VGG的介绍,以及这些模型在实际应用中的表现。同时,文章也讨论了数据增强、模型集成等改进性能的方法,并指出了当前面临的计算资源需求高、数据隐私等挑战。通过综合分析,本文旨在为深度学习在图像识别中的进一步研究和应用提供参考。 本文探讨了后端开发中数据缓存的重要性和实现方法,通过具体案例解析Redis在实际应用中的使用。首先介绍了缓存的基本概念及其在后端系统性能优化中的作用;接着详细讲解了Redis的常见数据类型和应用场景;最后通过一个实际项目展示了如何在Django框架中集成Redis,
下一篇
无影云桌面