分布式缓存系统Memcached学习心得

缘起: 在数据驱动的web开发中,经常要重复从数据库中取出相同的数据,这种重复极大的增加了数据库负载。缓存是解决这个问题的好办法。

Memcached是什么?

Memcached是由DangaInteractive开发的,高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。

Memcached能缓存什么?

通过在内存里维护一个统一的巨大的hash表,Memcached能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。

Memcached快么?

非常快。Memcached使用了libevent(如果可以的话,在linux下使用epoll)来均衡任何数量的打开链接,使用非阻塞的网络I/O,对内部对象实现引用计数(因此,针对多样的客户端,对象可以处在多样的状态),使用自己的页块分配器和哈希表,因此虚拟内存不会产生碎片并且虚拟内存分配的时间复杂度可以保证为O(1).。

DangaInteractive为提升DangaInteractive的速度研发了Memcached。目前,LiveJournal.com每天已经在向一百万用户提供多达两千万次的页面访问。而这些,是由一个由web服务器和数据库服务器组成的集群完成的。Memcached几乎完全放弃了任何数据都从数据库读取的方式,同时,它还缩短了用户查看页面的速度、更好的资源分配方式,以及Memcache失效时对数据库的访问速度。

Memcached的特点

Memcached的缓存是一种分布式的,可以让不同主机上的多个用户同时访问,因此解决了共享内存只能单机应用的局限,更不会出现使用数据库做类似事情的时候,磁盘开销和阻塞的发生。

Memcached的使用

一、Memcached服务器端的安装(此处将其作为系统服务安装)

下载文件:memcached1.2.1forWin32binaries(Dec23,2006)

1解压缩文件到c:\memcached

2命令行输入'c:\memcached\memcached.exe-dinstall'

3命令行输入'c:\memcached\memcached.exe-dstart',该命令启动Memcached,默认监听端口为11211

通过memcached.exe-h可以查看其帮助

二、客户端使用

下载memcachedjavaclient:http://www.whalin.com/memcached/#download

1解压后将java_memcached-release_2.0.1.jarjar包添加到工程的classpath中

       2 利用memcached java client 一个简单的应用
package com.danga.MemCached.test;      
         
    import java.util.Date;      
         
    import com.danga.MemCached.MemCachedClient;      
    import com.danga.MemCached.SockIOPool;      
         
         
    public class Test {          
        protected static MemCachedClient mcc = new MemCachedClient();         
             
        static {         
            String[] servers ={"192.168.40.4:12000"};         
             
            Integer[] weights = { 3 };         
             
            //创建一个实例对象SockIOPool       
            SockIOPool pool = SockIOPool.getInstance();         
             
            // set the servers and the weights      
            //设置Memcached Server      
            pool.setServers( servers );         
            pool.setWeights( weights );         
             
            // set some basic pool settings         
            // 5 initial, 5 min, and 250 max conns         
            // and set the max idle time for a conn         
            // to 6 hours         
            pool.setInitConn( 5 );         
            pool.setMinConn( 5 );         
            pool.setMaxConn( 250 );         
            pool.setMaxIdle( 1000 * 60 * 60 * 6 );         
             
            // set the sleep for the maint thread         
            // it will wake up every x seconds and         
            // maintain the pool size         
            pool.setMaintSleep( 30 );         
             
            // Tcp的规则就是在发送一个包之前,本地机器会等待远程主机      
                      // 对上一次发送的包的确认信息到来;这个方法就可以关闭套接字的缓存,      
                      // 以至这个包准备好了就发;      
                      pool.setNagle( false );         
            //连接建立后对超时的控制      
                      pool.setSocketTO( 3000 );      
            //连接建立时对超时的控制      
                      pool.setSocketConnectTO( 0 );         
             
            // initialize the connection pool         
            //初始化一些值并与MemcachedServer段建立连接      
                      pool.initialize();      
                     
             
            // lets set some compression on for the client         
            // compress anything larger than 64k         
            mcc.setCompressEnable( true );         
            mcc.setCompressThreshold( 64 * 1024 );         
        }         
                 
        public static void bulidCache(){         
            //set(key,value,Date) ,Date是一个过期时间,如果想让这个过期时间生效的话,这里传递的new Date(long date) 中参数date,需要是个大于或等于1000的值。      
            //因为java client的实现源码里是这样实现的 expiry.getTime() / 1000 ,也就是说,如果 小于1000的值,除以1000以后都是0,即永不过期      
            mcc.set( "test", "This is a test String" ,new Date(11211));     
        //十秒后过期      
                    
        }         
            
        public static void output() {         
            //从cache里取值      
            String value = (String) mcc.get( "test" );         
            System.out.println(value);          
        }         
                 
        public static void main(String[] args){         
            bulidCache();        
            output();             
        }       
             
    }
 
nowonder 写道
之前调研memcached最大的问题是它是一个单点,是一种集中式的分布式,组成它的n台机器里只要有一个down了,整个就挂了...

1、并不会整个挂掉,只会访问某些cache内容无法命中

2、就算全部挂掉,Cache就是减少对数据库访问的,所以无非就是对数据库压力大一些而已,能有什么影响?

3、如果你希望Cache持久化,或者带有故障切换功能,可以用memcachedb。
xtcn 写道
所以不能过于依赖于Cache

你的设计首先要保证DB在一定情况下还是能撑住访问量的

不然,万一出现大规模的Cache服务器的问题,后果会很严重:)

CacheServer的可靠性比DBServer还要高,你这种假设不成立。或者你应该这样假设:

所以不能过于依赖于数据库,

你的设计要保证没有数据库的情况下,网站能够照常提供服务,

不然,万一出现大规模的数据库服务器的问题,后果会很严重:)

memcached 要求set的对象必须是可序列化对象,jboss cache等java obect cache是没有这个说法的,这是本质的不同的,但是他可以在网络上用,所以必须序列化也可理解,lz的例子比较简单还没有说明这点.

楼主好像并不很了解memcached,我们公司已经用了好久,非常稳定,非常快,并发连接可以上到1w,我手头的应用常常保持在3-5k;它的快不仅是因为用了libevent,还因为它采取了“用内存冗余换存取速度”的内存管理策略,网上有文章专门分析它的内存分配回收管理的源码,讲的很清楚,在这上面jboss cache、ehcache、oscache跟它没法比;memcached的集群也非常好,听说国外有200+的memcached集群,我们也有这方面的尝试,效果也很好,一台down掉根本不会引起其他机器down掉,只是这台的数据丢了,需要慢慢积累回来;而且支持多客户端,java、php、python、ruby可以共享数据,就把它当作数据库用。我的建议是:你的应用访问量比较大,对响应速度要求很高,对数据一致性要求一般时,用它,挡在数据库前面,非常爽(memcached是互联网公司开发的,正好满足这三个条件);如果应用不忙,用用ehcache就行了。

bottom 写道
to oldyoungj,ehcache、oscache 的数据都是在本机服务器上的,访问时走的仅是系统总线。而memcached走的是网络。俺不相信网络传输速度还会快过系统总线。

并不需要那么快。我们的应用读取memcached的网络流量是每秒有2MB的流量,是读取数据库的网络流量的大约5倍。但是你要知道现在随便的PC机都是千兆网卡,因此memcached的get/set操作的延时非常少,并不比echache的get/set慢多少。在一个完整的web应用当中,我的压力测试表明,性能差异 <= 5%

减少数据库的IO是正确的。

但是没有数据库的情况下,网站还要照常提供服务也太牛x了把!

门户级别的网站,数据库正如其名:数据库,只是负责保存数据

页面使用cms发布成静态页,要么放squid,要么放cdn

论坛、sns这样的应用,会使用多种技术进行缓存。

拿sohu的bbs来说吧,pv为5000w,峰值8000w

其中帖子、评论读写频繁,其他部分读频繁。

帖子列表、评论列表使用c开发(其中排序算法很巧妙),socket调用

帖子、评论内容使用squid缓存

其他读频繁的部分使用memcached、squid、定时生成静态页面等多种技术。

数据库用mysql,分表。

个人认为,小规模应用中,jvm级别的cache可以用用,memcached可用可不用

大规模网站应用,肯定是系统水平切分,多种cache结合。

相关推荐