由于工作需要,2年前开始接触分布式的缓存 -- memcache。2年过去了,memcahce也发展了不少,同时也出现许多新星--TT、redis。但万变不离其宗,现将心得总结如下。
先说最早的memcache
这个东西感觉就是个BDB的内存版,就因为是纯内存的程序,所以性能异常的高。现在好像有自己的主页了(http://memcached.org/),记得最早的时候就是danga的个人主页,而且除了一个readme之外就没什么资料了,不过现在这个东西已经遍地开花了。
关于这个东西里面到底应该存放数据网上一直有很多种说法,有的说sql进行md5之后作为键值,结果作为内容存放,也有人说按照业务逻辑错放,反正是炒的不亦乐乎。
本人经过将近2年的实践,最后还是觉得要根据业务逻辑来存放,不能将sql加密然后对应结果集存放。这样做,基本上无法实现数据的及时更新,只能依靠memcahce的过期时间来更新。资讯类的静态数据比较合适,不过这种网站一般会做静态化的处理,所以memcache也发挥不了太大用途。真正有用武之地的地方是社区类网站,这类网站大部分是动态数据,而且性能要求还高,所以memcahce比较合适(貌似memcache本来就为了解决这个问题才被创造出来的)。
如果按照业务来进行存储,很容易控制数据的准确性,一般的程序每种业务都会有自己的底层数据,memcahce部分的操作何以放在这部分代码里。这样对上层程序是透明的,不会将上层的开发工程师搞的晕头转向。
memcache操作的基本逻辑:先检查在mem中是否存在,如果存在,则返回mem中的数据,如果不存在,根据条件到db中查找相应的结果,然后放入mem中,返回结果(如果mem写入失败,需要记录下日志)。这个逻辑有个弊端就是当缓存失效的时候上层程序没有感觉,结果底层程序一直会访问db,很可能导致db宕机,这就是为什么在mem写入失败的时候要记录日志的原因。以上实现了数据的存储,下面讲数据的更新,当db有insert和update操作的时候,需要根据相应的条件找到与之有关的mem键值,然后删除掉(当然您也可以在这个时候直接将修改后的数据放入mem,不过这样做性能就下降了一倍),当下次再有程序检查这个键值的时候,就会发现键值不存在,然后它会从db中再取一份新的数据出来放入mem。这样就实现了数据的被动更新。
为什我要把memcache设计成这样一个被动式更新的方式呢?因为这样做最节省资源。看看cdn的缓存方式就明白了,cdn也是一种被动式的缓存,只有当有用户访问到对应的资源是,cdn才会去检查相应的资源是否存在,不存在了去源站取回资源并缓存在自己这里。如果把memcache设计成主动更新的形式,实在是太浪费资源,因为这样做会有很多基本上没有访问的数据被放入了mem,如果想优化,还需要统计数据的使用率,然后才能决定哪部分数据不放入缓存。实现难度太高。
下面继续深入。存储逻辑清楚了,下面就开始看数据了。大家都知道,不同的业务数据的大小也是不一样的(session的数据基本上都是很小的值,基本上就几十字节,单条用户数据基本不会很大,也就1-3k,资源类的就比较大一点了,相片,投票,分享等基本在1k以上)。为什么说这个呢?这是由memcache的存储机制决定的,memcache存储在内存中的数据并不是有多长存多长的,而是预先定义小的大小,数据优先存放在能够存放的最小的空间里,至于为什么要这样做,大家可以看看memcache的帮助。由于这个实际情况,所以我们必须考虑要存放的数据的实际大小,以免内存被浪费掉(虽然内存都白菜价了,但那也是钱啊)。memcache有个启动参数-f用来控制最小空间的大小,基础空间大小是80b,然后按照80*(1+f)^n这个公式一次计算以后的空间大小。f的默认值是0.25。所以如果存储session数据,那么这个值可以适当的改小,如果存资源类的数据,这个值可以适当的改大,不建议改的太大,那样太浪费空间。其他的参数大家可以看网上的资料就可以学到了,基本上没什难得。
下面再深入,逻辑清楚了,单个进程也完美的启动了,下面是分布式的问题。memcahce的优势除了性能高之外就是分布式的结构了,这个结构可以让性能进一步的提升。既然要分布式,必然要进行hash运算,确定数据的实际存储位置。最初的memcahce只有一个余数的算法,虽然均匀性很好但是在增加以及减少机器的时候,命中率实在是低的可怜,所以后来出现了Consistent Hashing算法。这部分没什么说的,网上资料一大堆(http://ispring.javaeye.com/blog/221355)
到这里基本上程序已经运行起来了,剩下的是维护工作,经常去看看memcache服务器的状态啦,命中率啦,lru值啦,是否内存块存满啦等等,这个基本上是要和运维配合来做的事情了(因为他们有cacti,^_^)。
memcache基本上没什么了,后来出现TT,也是个很不错的东西,和memcahce一样的协议,还能定时将数据写到硬盘上,很好的解决了memcache宕机丢数据的问题。原来的session数据完全就可以挪到TT里了。
redis,这个是个更不错的东西,memcahce,TT的优点它都有,而且据说还更好。而且还有list和set,list和set解决了很多memcahe解决不了的问题,原来做list只能用memcahce做个伪的,要不然就弄个m4q,再不然找个queue软件,还要装,性能还没有redis好。要不是它现在还不太成熟,就可以将大部分缓存迁移到redis上了。不过redis的作者也偷懒,php的客户端竟然有严重bug!!!而且貌似redis的分布式也没有memcahce好。希望今年redis可以多进步点。
相关推荐
分布式缓存介绍,主要介绍目前比较流行的分布式缓存架构
Ehcache 是一种广泛使用的开源 Java 分布式缓存。主要面向通用缓存,Java EE 和轻量级容器。它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个 gzip 缓存 servlet 过滤器,支持 REST 和 SOAP api...
分布式缓存服务器的源代码,memcacaed-1.4.25,了解它,对大家以后编写一些服务器的缓存,自己的实现,会有所启发和帮助
分布式缓存 原理 架构及Go语言实现-高清-完整目录,分享给所有需要的人!
关于hadoop的分布式缓存的源码,用于大家的学习,改进hadoop的分布式缓存
redis分布式缓存中间件培训PPT
介绍ehcache做jvm缓存,ehcache做分布式缓存,redis做分布式缓存,redis分片集群,redis哨兵,redis基本数据,redis主从复制,redis和ehcache的二级缓存,redis雪崩效应,redis缓存穿透(整个环境搭建基于Centos,代码...
分布式缓存 redis 分布式缓存
redis分布式缓存+spring整合及 集群、分片等配置使用例子
分布式缓存-基于Redis集群解决单机Redis存在的问题。分布式缓存-基于Redis集群解决单机Redis存在的问题。分布式缓存-基于Redis集群解决单机Redis存在的问题。分布式缓存-基于Redis集群解决单机Redis存在的问题。...
主要涉及本地缓存与分布式缓存优缺点,使用,前部宣讲
java ehcache分布式缓存实例 RMI方式实现.
超牛逼的分布式缓存框架hazelcast,谁用谁知道!
作为云平台提升应用性能的一种重要手段,分布式缓存技术近年来受到了工业界和学术界的广泛关注.从云计算与分布式缓存技术的结合入手,分析介绍了分布式缓存的特性、典型应用场景、发展阶段、相关标准规范以及推动缓存...
实现Redis分布式缓存,此文件为相关原理
缓存在系统中用来做什么?Redis有哪些功能?
使用Go语言实现的分布式缓存,纯go语言项目,并非对已有的分布式缓存数据库的封装,内部使用map存储数据,并且实现了持久化与动态增删服务器节点的功能。
分布式缓存测试框架 RadarGun ,RadarGun 是一个用于对数据网格和分布式缓存进行基准测试的框架。 架构: 测试结果:
分布式缓存常见知识点(高并发、高可用、通信模型、主从架构、主备切换、哨兵、redis cluster集群、持久化、过期策略、缓存雪崩、穿透等等)
分布式缓存原理书籍 电子书, 分布式 缓存