首页 | 互联网 | IT动态 | IT培训 | Cisco | Windows | Linux | Java | .Net | Oracle | 软件测试 | C/C++ | 嵌入式开发 | 存储世界 | 服务器
网络设备 | IDC | 安全 | 求职招聘 | 数字网校 | 网页设计 | 平面设计 | 技术专题 | 电子书下载 | 教学视频 | 源码下载 | 搜索 | 博客 | 论坛
中国IT实验室Linux频道
中国IT教育
Google
首页 资讯动态 认证考试 新手入门 核心技术 高级技术 J2EE J2ME Java&XML 开源技术 其他技术 RSS订阅 论坛 专题
您现在的位置: 中国IT实验室 >> Java >> 新手入门 >> 基础入门 >> 正文

Memcached使用点滴

   对于上面代码的了解需要从Memcached内存分配和回收机制开始,以前接触Memcached的时候只是了解,这部分代码写了以后就有些知道怎么回事了。Memcached为了提高内存的分配和回收效率,采用了slab和dump分区的概念。Memcached一大优势就是能够充分利用Memory资源,将同机器或者不同机器的Memcached服务端组合成为对客户端看似统一的存储空间,Memcached可以在一台机器上开多个端口作为服务端多个实例,也可以在多台机器上开多个服务实例,而slab就是Memcached的服务端。下面是我封装后的Cache配置:

    <?xml version="1.0" encoding="UTF-8"?>

    <memcached>

        <client name="mclient0" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool0">

            <!--errorHandler></errorHandler-->

        </client>

        <client name="mclient1" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool1">

            <!--errorHandler></errorHandler-->

        </client>

        <client name="mclient11" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool11">

            <!--errorHandler></errorHandler-->

        </client>

        <socketpool name="pool0" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0"

            nagle="false" socketTO="3000" aliveCheck="true">

            <servers>10.2.225.210:13000,10.2.225.210:13001,10.2.225.210:13002</servers>

        </socketpool>

        <socketpool name="pool1" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0"

            nagle="false" socketTO="3000" aliveCheck="true">

            <servers>10.2.225.210:13000</servers>

        </socketpool>

        <socketpool name="pool11" failover="true" initConn="10" minConn="5" maxConn="250" maintSleep="0"

            nagle="false" socketTO="3000" aliveCheck="true">

            <servers>10.2.225.210:13000</servers>

        </socketpool>

        <cluster name="cluster1">

            <memCachedClients>mclient1,mclient11</memCachedClients>

        </cluster>

    </memcached>

    可以看到其实pool才是最终连接服务端的配置,看看pool0,它会连接10.2.225.210:13000,10.2.225.210:13001,10.2.225.210:13002这些机器和他们的端口,但是对于使用pool0的mclient0来说它仅仅只是知道有一个叫做mclient0的cache可以保存数据。此时slab就有三个:10.2.225.210:13000和10.2.225.210:13001和10.2.225.210:13002。

    当一个key:value要被放入到Memcached中,首先Memcached会根据key的hash算法获取到hash值来选择被分配的slab,然后根据value选择适合的dump区。所谓dump区其实就是根据value的大小来将内存按照存储单元内容大小分页。这个是可以配置Memcached的,例如Memcached将slab中的内存划分成4个dump,第一dump区存储0-50k大小的数据,第二dump区存储50-100k的数据,第三dump区存储100-500k的数据,第四dump区存储500-1000K的数据。那么当key:value需要被写入的时候,很容易定位到value所处的dump,分配内存给value。这种分dump模式简化内存管理,加速了内存回收和分配。但是这里需要注意的几点就是,首先当你的应用场景中保存的数据大小离散度很高,那么就不是很适合Memcached的这种分配模式,容易造成浪费,例如第一dump区已经满了,第二第三dump区都还是只有一个数据,那么第二第三dump区不会被回收,第二第三dump区的空间就浪费了。同时Memcached对于value的大小支持到1M,大于1M的内容不适合Memcached存储。其实在Cache的设计中这样的情况发生本来就证明设计有问题,Cache只是加速,一般保存都是较小的id或者小对象,用来验证以及为数据定位作精准细化,而大数据量的内容还是在数据库等存储中。

    知道了基本的分配机制以后再回过头来看看代码:

    Map slabs = getCacheClient().statsItems();//获取所有的slab

    //用来收集所有slab的dump号

    while(itemsItr.hasNext())

               {

                  String server = itemsItr.next().toString();

                  Map itemNames = (Map) slabs.get(server);

                  Iterator itemNameItr = itemNames.keySet().iterator();

                  while(itemNameItr.hasNext())

                  {

                      String itemName = itemNameItr.next().toString();

                      // itemAtt[0] = itemname

                       // itemAtt[1] = number

                       // itemAtt[2] = field

                       String[] itemAtt = itemName.split(":");

    // 如果是itemName中是:number来表示,那么证明是一个存储数据的dump,还有一些是age的部分

                       if (itemAtt[2].startsWith("number"))

                       dumps.put(itemAtt[1], Integer.parseInt(itemAtt[1]));

                  }

               }

            //根据收集到的dump来获取keys

    if (!dumps.values().isEmpty())

               {

                  Iterator<Integer> dumpIter = dumps.values().iterator();

                  while(dumpIter.hasNext())

                  {

                      int dump = dumpIter.next();

    // statsCacheDump支持三个参数String[],int,int,第一个参数可以省略,默认填入null,表示从那些slab中获取dump号为第二个参数的keys,如果是null就从当前所有的slab中获取。第二个参数表示dump号,第三个参数表示返回最多多少个结果。

                      Map cacheDump = statsCacheDump(dump,limit);

                      Iterator entryIter = cacheDump.values().iterator();

                      while (entryIter.hasNext())

                       {

                            Map items = (Map)entryIter.next();

                            Iterator ks = items.keySet().iterator();

                        while(ks.hasNext())

                        {

                            String k = (String)ks.next();

                            try

                            {

 

上一页  [1] [2] [3] 下一页

【责编:landy】

中国IT教育

相关产品和培训
文章评论
 友情推荐链接
 认证培训
 专题推荐

 ·关于Java框架技术专题
 ·XML全攻略技术专题
 ·JAVA开源技术介绍专题
 ·Java嵌入式开发之J2ME技术专题
 ·超前体验 Oracle 11g的5个新特性…
 ·揭密使用VB.NET的五个实用技巧
 ·Oracle和SQL Server常用函数对比专题…
 ·展现C#世界 C#程序设计专题…
 ·Java入门 Tomcat的配置技巧精华专题…
 ·Oracle RMAN物理备份技术详解…
 今日更新
 社区讨论
 博客论点
 频道精选
 Java 频道导航