转自:http://www.cnblogs.com/lovecindywang/archive/2010/05/19/1739025.html
先说说自己对Memcache和Mongodb的一些看法。主要是抛砖引玉了,希望看到大家的意见和补充。
Memcache
Memcache的优势我认为总结下来主要体如今:
1) 分布式。能够由10台拥有4G内存的机器,构成一个40G的内存池。假设认为还不够大能够添加机器,这样一个大的内存池,全然能够把大部分热点业务数据保存进去。由内存来阻挡大部分对数据库读的请求。对数据库释放可观的压力。
2) 单点。
假设Webserver或Appserver做负载均衡的话,在各自内存中保存的缓存可能各不同样。假设数据须要同步的话,比較麻烦(各自自己过期,还是分发数据同步?)。即使数据并不须要同步。用户也可能由于数据的不一致而产生用户体验上的不友好。
3) 性能强。不用怀疑和数据库相比确实是。根源上还是内存的读写和磁盘读写效率上几个数量级的差距。有的时候我们在抱怨数据库读写太差的情况下能够看看磁盘的IO,假设确实是瓶颈的话装啥强劲的数据库预计也档不了,强不强无非是这个数据库多少充分的利用了内存。
可是也不太建议在不论什么情况下使用Memcache替代不论什么缓存:
1) 假设Value特别大,不太适合。由于在默认编译下Memcache仅仅支持1M的Value(Key的限制到不是最大的问题)。事实上从实践的角度来说也不建议把很大的数据保存在Memcache中,由于有序列化反序列化的过程。别小看它消耗的CPU。讲到这个就要提一下,我一直认为Memcache适合面向输出的内容缓存,而不是面向处理的数据缓存,也就是不太适合把大块数据放进去拿出来处理之后再放进去。而是适合拿出来就直接给输出了。或是拿出来不须要处理直接用。
2) 假设不同意过期,不太适合。
Memcache在默认情况下最大30天过期,并且在内存达到使用限制后它也会回收最少使用的数据。因此,假设我们要把它当作static变量的话就要考虑到这个问题,必须有又一次初始化数据的过程。事实上应该这么想,既然是缓存就是拿到了存起来。假设没有必然有一个又一次获取又一次缓存的过程,而不是想着它永远存在。
在使用Memcache的过程中当然也会有一些问题或者说最佳实践:
1) 清除部分数据的问题。
Memcache仅仅是一个Key/Value的池,一个公共汽车谁都能够上。我认为对于类似的公共资源。假设用的人都依照自己的规则来的话非常easy出现故障。
因此。最好在Key值的规范上上使用类似命名空间的概念。 每个用户都能非常明白的知道某一块功能的Key的范围。或者说前缀。带来的优点是我们假设须要清空的话能够依据这个规范找到我们自己的一批Key然后再去清空,而不是清空全部的。当然有人是採用版本号升级的概念。老的Key就让它过去吧。到时候自然会清空,这也是一种办法。只是Key有规范总是有优点的,在统计上也方便一点。
2) Value的组织问题。
也就是说我们存的数据的粒度,比方要保存一个列表。是一个保存在一个键值还是统一保存为一个键值,这取决于业务。
假设粒度非常小的话最好是在获取的时候能批量获取,在保存的时候也能批量保存。对于跨网络的调用次数越少越好,能够想一下,假设一个页面须要输出100行数据,每个数据都须要获取一次。一个页面进行上百次连接这个性能会不会成问题。
那么Memcache主要用在哪些功能上呢?
事实上我认为平时能想到在内存中做缓存的地方我们都能够考虑下是不是能够去适用分布式缓存,可是基本的用途还是用来在前端或中部挡一下读的需求来释放WebserverAppserver以及DB的压力。
Mongodb
Mongodb是一款比較优良的非关系型数据库的文档型的数据库。它的优势主要体如今:
1) 开源。意味着即使我们不去改也能够充分挖掘它,MS SQL除了看那些文档。谁又知道它内部怎样实现。
2) 免费。意味着我们能够在大量垃圾server上装大量的实例。即使它性能不怎么高,也架不住许多的点啊。
3) 性能高。其他没比較过。和MS SQL相比,相同的应用(主要是写操作)一个撑500用户就挂了,一个能够撑到2000。
在数据量上到百万之后。即使没索引,MS SQL的插入性能下降的也一塌糊涂。事实上不论什么事物都有相对性的,在变得复杂变得完好了之后会牺牲一部分的性能,MS SQL体现的是很强的安全性数据完整性,这点是Mongodb办不到的。
4) 配置简单而且灵活。在生产环境中对数据库配置故障转移群集和读写分离的数据库复制是非经常见的需求,MS SQL的配置繁琐的步骤还是非常恐怖的。而Mongodb能够在五分钟之内配置自己所须要的故障转移组,读写分离更是仅仅须要一分钟。灵活性体如今,我们能够配置一个M一个S。两个M一个S(两个M写入的数据会合并到S上供读取),一个M两个S(一个M写入的数据在两个S上有镜像),甚至是多个M多个S(理论上能够创建10个M。10个S,我们仅仅须要通过轮询方式随便往哪个M上写,须要读的时候也能够轮训随意一个S。当然我们要知道不可能保证在同一时间全部的S都有一致的数据)。那么也能够配置两个M的对作为一套故障转移群集,然后这种群集配置两套。再相应两个S,也就是4个M相应2个S,保证M点具有故障转移。
5) 使用灵活。
在之前的文章中我提到甚至能够通过SQL到JS表达式的转换让Mongodb支持SQL语句的查询,无论怎么说Mongodb在查询上还是非常方便的。
之前也说过了。并非全部数据库应用都使用採用Mongodb来替代的,它的主要缺点是:
1) 开源软件的特点:更新快,应用工具不完好。因为更新快,我们的client须要随着它的更新来升级才干享受到一些新功能,更新快也意味着非常可能在某一阶段会缺乏某个重要功能。另外我们知道MS SQL在DEV/DBA/ADM多个维度都提供了非常好的GUI工具对数据库进行维护。而Mongodb尽管提供了一些程序。可是并非非常友好。
我们的DBA可能会非常郁闷,去优化Mongodb的查询。
2) 操作事务。Mongodb不支持内建的事务(没有内建事务不意味着全然不能有事务的功能),对于某些应用也就不适合。只是对于大部分的互联网应用来说并不存在这个问题。
在使用Mongodb的过程中主要遇到以下的问题:
1) 真正的横向扩展?在使用Memcache的过程中我们已经体会到这样的爽了,基本能够无限的添加机器来横向扩展。由于什么,由于我们是通过client来决定键值保存在那个实例上,在获取的时候也非常明白它在哪个实例上。即使是一次性获取多个键值,也是相同。而对于数据库来说,我们通过各种各样的方式进行了Sharding,不说其他的。在查询的时候我们依据一定的条件获取批量的数据,怎么样去处理?比方我们依照用户ID去分片,而查询根本不在乎用户ID,在乎的是用户的年龄和教育程度,最后依照姓名排序。到哪里去取这些数据?无论是基于client还是基于服务端的Sharding都是非常难做的,而且即使有了自己主动化的Sharding性能不一定能有保障。
最简单的是尽量依照功能来分。再下去就是历史数据的概念,真正要做到实时数据分散在各个节点,还是非常困难。
2) 多线程,多进程。在写入速度达不到预期的情况下我们多开几个线程同一时候写。或者多开几个Mongodb进程(同一机器),也就是多个数据库实例,然后向不同的实例去写。
这样能否提高性能?非常遗憾,非常有限。甚至能够说根本不能提高。为什么使用memcache的时候多开线程能够提高写入速度?那是由于内存数据交换的瓶颈我们没达到,而对于磁盘来说,IO的瓶颈每秒那么几十兆的是非常easy达到的,一旦达到这个瓶颈了,不管是开多少个进程都无法提高性能了。
还好Mongodb使用内存映射,看到内存使用的多了。事实上我对它的信心又多了一点(内存占用多了我认为CPU更easy让它不闲着),怕就怕某个DB不使用什么内存。看着IO瓶颈到了,内存和CPU还是吃不饱。
Memcache和Mongodb的配合
事实上有了Memcache和Mongodb我们甚至能够让80%以上的应用摆脱传统关系型数据库。
我能想到它们事实上能够互相配合弥补对方的不足:
Memcache适合依据Key保存Value,那么有的时候我们并不知道须要读取哪些Key怎么办呢?我在想是不是能够把Mongodb或说数据库当作一个原始数据。这份原始数据中分为须要查询的字段(索引字段)和普通的数据字段两部分。把大量的非查询字段保存在Memcache中。小粒度保存,在查询的时候我们查询数据库知道要获取哪些数据,一般查询页面也就显示20-100条吧。然后一次性从Memcache中获取这些数据。也就是说。Mongodb的读的压力主要是索引字段,而数据字段仅仅是在缓存失效的时候才实用,使用Memcache挡住大部分实质数据的查询。
反过来说,假设我们要清空Memcache中的数据也知道要清空哪些Key。
附录:
对于Memcached本身对value值大小的限制,笔者在这里单独强调下,踩过坑。能够查看这个文章:http://blog.csdn.net/billfeller/article/details/17200245
案例分析:公司使用LimeSurvey开源问卷调查系统进行用户调查,可是上线一段时间后出现用户明确提交了问题答案。系统却老是提示该题必填,追踪结果表明是由于LimeSurvey把大量问卷相关信息写到会话时。而php会话配置是存储到memcached的。当信息超过1M时就会出现数据丢失。导致系统觉得用户未提交问题。所以须要强调下Memcached用法——Memcached仅仅是分布式缓存,请尽量不要将其做为数据容器进行业务数据存储。