WEB缓存技术之阿堂教程:聊聊memcached分布式缓存技术--好文

转自:http://blog.sina.com.cn/s/blog_4c925dca010193sy.html

堂最早接触memcached技术,实际 上是在原来的一家游戏公司,因为阿堂带领项目组开发的一款网游,上了人人网后,准备要上腾讯的朋友网,腾讯也是比较牛,作为他们的合作伙伴,当时他们会为我们免费提供了CMEM技术和CDB技术(虽然说是免费,但是游戏赚钱后,是要双方分成的),这在当时和现在来说都是非常前沿的技术了。腾讯在国内的技术科研投入和应用上,不愧是走在国内的前列了。
         这里,阿堂先简单介绍下CMEM技术和CDB技术。
 
     什么是CMEM?
(1)全称为Cloud Memcache,是腾讯云平台提供的极高性能、内存级、持久化、分布式的Key-Value存储服务。
(2)CMEM是作为最终落地存储来设计的,拥有数据库级别的访问保障和持续服务能力。
(3)CMEM支持memcached协议,能力比memcached强(能落地),适用memcached、ttserver的地方都适用CMEM。
(4)CMEM解决了内存数据可靠性、分布式及一致性上的问题,让海量访问业务的开发变得简单快捷。
 
  什么是CDB?
  CDB的全称是Cloud Database,主要具有以下一些特点:
(1)云存储服务,是腾讯云计算平台提供的分布式数据存储服务
(2)完全兼容MySQL协议,适用于面向表结构的场景,适用MySQL的地方都可以使用CDB
(3)提供了高性能、高可靠、易用、便捷的MySQL集群服务
(4)整合了备份、扩容、迁移等工具,同时提供CDB管理台,开发者可以方便的进行登录、数据库和表的增删查改等工作
(5)现网CDB的运营数据超过40T,接入业务包括蜀山传奇、武道破天、捕鱼大亨、梦回西游、斗战西游等
 
         既然腾讯都在用memcached协议,那就可以看出memcached技术是如何强大了。那么就请随阿堂一起来看看memcached技术吧!
         Memcached是开源的分布式cache系统,现在很多的大型web应用程序包括腾讯,facebook,youtube,wikipedia,yahoo等等都在使用memcached来支持他们每天数亿级的页面访问。通过把cache层与他们的web架构集成,他们的应用程序在提高了性能的同时,还大大降低了数据库的负载
 
        这里我就简单给大家介绍一下memcached的工作原理:
 
       Memcached处理的原子是每一个(key,value)对(以下简称kv对),key会通过一个hash算法转化成hash-key,便于查找、对比以及做到尽可能的散列。同时,memcached用的是一个二级散列,通过一张大hash表来维护。
 
      Memcached有两个核心组件组成:服务端(ms)和客户端(mc),在一个memcached的查询中,mc先通过计算key的hash值来确定kv对所处在的ms位置。当ms确定后,客户端就会发送一个查询请求给对应的ms,让它来查找确切的数据。因为这之间没有交互以及多播协议,所以memcached交互带给网络的影响是最小化的。
 
举例说明:考虑以下这个场景,有三个mc分别是X,Y,Z,还有三个ms分别是A,B,C:
( mc  :  memcached的客户端    ms  : memcached的服务端)
设置kv对
X想设置key=”foo”,value=”seattle”
X拿到ms列表,并对key做hash转化,根据hash值确定kv对所存的ms位置
B被选中了
X连接上B,B收到请求,把(key=”foo”,value=”seattle”)存了起来
 
获取kv对
Z想得到key=”foo”的value
Z用相同的hash算法算出hash值,并确定key=”foo”的值存在B上
Z连接上B,并从B那边得到value=”seattle”
其他任何从X,Y,Z的想得到key=”foo”的值的请求都会发向B

 WEB缓存技术之阿堂教程:聊聊memcached分布式缓存技术--好文_第1张图片


 
存策略

当ms的hash表满了之后,新的插入数据会替代老的数据,更新的策略是LRU(最近最少使用),以及每个kv对的有效时限。Kv对存储有效时限是在mc端由app设置并作为参数传给ms的。

同时ms采用是偷懒替代法,ms不会开额外的进程来实时监测过时的kv对并删除,而是当且仅当,新来一个插入的数据,而此时又没有多余的空间放了,才会进行清除动作。

缓存数据库查询
现在memcached最流行的一种使用方式是缓存数据库查询,下面举一个简单例子说明:

App需要得到userid=xxx的用户信息,对应的查询语句类似:

“SELECT * FROM users WHERE userid = xxx”

App先去问cache,有没有“user:userid”(key定义可预先定义约束好)的数据,如果有,返回数据;如果没有,App会从数据库中读取数据,并调用cache的add函数,把数据加入cache中。

当取的数据需要更新,app会调用cache的update函数,来保持数据库与cache的数据同步。

从上面的例子我们也可以发现,一旦数据库的数据发现变化,我们一定要及时更新cache中的数据,来保证app读到的是同步的正确数据。

        经过上面的描述后,相信网友们应该对 memcached的基本原理有了一个比较深晰的认识了 

        阿堂为了让网友们对上面的图示案例更好的理解,下面结合代码来说明一下

public class MemCached
{
    
// 创建全局的唯一实例
    protected static MemCachedClient mcc = new MemCachedClient();
    
    
protected static MemCached memCached = new MemCached();
    
    
// 设置与缓存服务器的连接池
    static {
        
// 服务器列表和其权重
        //如下设置了三个ms 

        String[] servers = {"192.168.7.1:11211",
"192.168.7.2:11212","192.168.7.3:11213"};

        Integer[] weights = {3};

        
// 获取socke连接池的实例对象
        SockIOPool pool = SockIOPool.getInstance();

        
// 设置服务器信息
        pool.setServers( servers );
        pool.setWeights( weights );

        
// 设置初始连接数、最小和最大连接数以及最大处理时间
        pool.setInitConn( 5 );
        pool.setMinConn( 
5 );
        pool.setMaxConn( 
250 );
        pool.setMaxIdle( 
1000 * 60 * 60 * 6 );

        
// 设置主线程的睡眠时间
        pool.setMaintSleep( 30 );

        
// 设置TCP的参数,连接超时等
        pool.setNagle( false );
        pool.setSocketTO( 
3000 );
        pool.setSocketConnectTO( 
0 );

        
// 初始化连接池
        pool.initialize();

        
// 压缩设置,超过指定大小(单位为K)的数据都会被压缩
        mcc.setCompressEnable( true );
        mcc.setCompressThreshold( 
64 * 1024 );
    }
    
    

    
protected MemCached()
    {
        
    }
    
    

    
public static MemCached getInstance()
    {
        
return memCached;
    }
    
    

    
public boolean add(String key, Object value)
    {
        
return mcc.add(key, value);
    }
    
    
public boolean add(String key, Object value, Date expiry)
    {
        
return mcc.add(key, value, expiry);
    }
    
    
public boolean replace(String key, Object value)
    {
        
return mcc.replace(key, value);
    }
    
    
public boolean replace(String key, Object value, Date expiry)
    {
        
return mcc.replace(key, value, expiry);
    }
    
    

    
public Object get(String key)
    {
        
return mcc.get(key);
    }
    
    
public static void main(String[] args)
    {
        MemCached cache 
= MemCached.getInstance();
       
        cache.add(
"foo ""seattle");
        //如上这一步经过了这样几个过程
        1.对key foo进行哈希
        2.选择服务器 (假设根据哈希算法,选择的服务器是 
192.168.7.2:11212  MS B)
        3. 连接
        4.设置 key foo和value seattle


        //
 cache.get("foo")如下一步执行
         1.根据key foo进行哈希知道了 key foo是在 
 192.168.7.2:11212  MS B 上
         2.连接  192.168.7.2:11212  MS B 
         3.在 192.168.7.2:11212  MS B 上根据 key foo得到相应的value seattle了
 
        System.out.print("get value : " + cache.get("foo"));

    }
}
 
 
            至此,想必网友们对memcached技术有了一个比较相对完整的理解和认识了!   
          由于阿堂对memcached技术也在不断学习中,也算是一个新手了,这里总结分享一下,希望能对朋友们有所帮助!在后一篇文章中,阿堂准备分享一篇memcached的集群技术的实战分享给其它网友,敬请期待。

转自:http://blog.sina.com.cn/s/blog_4c925dca010193sy.html

你可能感兴趣的:(java,memcached)