什么是memcache?
memcache是分布式的高速缓存系统,用于提升网站的访问速度。
memcache的原理:
先检查客户端的请求数据是否在memcached中,如有,直接把请求数据返回,不再对数据库进行任何操作;如果请求的数据不在memcached中,就去查数据库,把从数据库中获取的数据返回给客户端,同时把数据缓存一份到memcached中(memcached客户端不负责,需要程序明确实现);每次更新数据库的同时更新memcached中的数据,保证一致性;当分配给memcached内存空间用完之后,会使用LRU(Least Recently Used,最近最少使用)策略加上到期失效策略,失效数据首先被替换,然后再替换掉最近未使用的数据。
memcache的工作原理:
首先 memcached 是以守护程序方式运行于一个或多个服务器中,随时接受客户端的连接操作,客户端可以由各种语言编写,目前已知的客户端 API 包括 Perl/PHP/Python/Ruby/Java/C#/C 等等。客户端在与 memcached 服务建立连接之后,接下来的事情就是存取对象了,每个被存取的对象都有一个唯一的标识符 key,存取操作均通过这个 key 进行,保存到 memcached 中的对象实际上是放置内存中的,并不是保存在 cache 文件中的,这也是为什么 memcached 能够如此高效快速的原因。注意,这些对象并不是持久的,服务停止之后,里边的数据就会丢失。
memcache应用场景:
1、分布式应用:由于memcached本身基于分布式的系统,所以尤其适合大型的分布式 系统。
2、数据库前段缓存: 数据库常常是网站系统的瓶颈。数据库的大并发量访问,常常 造成网站内存溢出。当然我们也可以使用Hibernate的缓存机 制。但memcached是基于分布式的,并可独立于网站应用本身 所以更适合大型网站进行应用的拆分。
3、服务器间数据共享:举例来讲,我们将网站的登录系统、查询系统拆分为两个应用
放在不同等等服务器上,并进行集群,那这个时候用户登录后,登录信息如何从登录系统服务器同步到查询系统服务器呢?这时候我们便可以使用memcache,登录系统将登录信息缓存起来,查询系统便可以获得登录信息,就像获取本地信息一样。
memcache不适用的场景:
1、缓存的数据量比较小。
2、缓存的数据持久化。
memcache和memcached的区别:
1、memcache的历史比memcached历史早。memcache最早是在2004年2月开发的,最后更
新是在2013年4月,而memcached最早是在2009年1月开发的,最后更新是在2014年1月更新的。
2、memcache提供了面向对象和面向过程的接口,memcached只支持面向对象的接口。
这就意味着在安装 memcache 扩展的时候不要求安装其他的东西,但是在安装 memcached 的时候会要求你安装libmemcached。它具有低内存,线程安全等优点。据说新浪微博之前就全面将 PHP 的 memcache 替换成 PHP 的 memcached,在高并发下,稳定性果断提高。
3、memcached 比 memcache 支持更多的 memcache 协议,大概也就是说 memcached
有更多的方法,比如 getMulti() 和 setMulti() 函数非常有用,但是 memcache 并不支持。
4、memcache不支持长链接,memcached支持长链接
memcache的优点:
1、稳定。
2、配置简单
3、速度快
4、分布式扩展
怎样提高memcache的命中率?
1、要提高memcached的命中率,预估我们的value大小并且适当的调整内存页大小和增长因子是必须的。
2、合理组合缓存 Key,保证 Key 最大概率重复。
3、预加载缓存
redis和memecache的不同在于:
1、存储方式:
memecache 把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小
redis有部份存在硬盘上,这样能保证数据的持久性(笔者注:有快照和AOF日志两种持久化方式,在实际应用的时候,要特别注意配置文件快照参数,要不就很有可能服务器频繁满载做dump)。
2、数据支持类型:
redis在数据支持上要比memecache多的多。
3、使用底层模型不同:
新版本的redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
4、运行环境不同:
redis目前官方只支持LINUX 上去行,从而省去了对于其它系统的支持,这样的话可以更好的把精力用于本系统 环境上的优化,虽然后来微软有一个小组为其写了补丁。但是没有放到主干上
memcache只能当做缓存,cache
redis的内容是可以落地的,就是说跟mongodb有些类似,然后redis也可以作为缓存,并且可以设置master-slave
系统分配给Slab的内存空间称为page,默认是1MB。
memcache和redis和mongdb的区别
1、性能:从性能方面来看,redis和memcache差不多,要大于mongdb
2、操作的便利性:1、memcache数据结构单一
2、redis丰富一些,数据操作方面,redis更好一些,较少的网络I O次数
3、mongodb支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富
3、内存空间的大小和数据量的大小:
redis在2.0版本后增加了自己的VM特性,突破物理内存的限制;可以对key value设置过期时间(类似memcache)
memcache可以修改最大可用内存,采用LRU算法
mongoDB适合大数据量的存储,依赖操作系统VM做内存管理,吃内存也比较厉害,服务不要和别的服务在一起
4、可靠话(持久话)
redis支持(快照、AOF):依赖快照进行持久化,aof增强了可靠性的同时,对性能有所影响
memcache不支持,通常用在做缓存,提升性能;
MongoDB从1.8版本开始采用binlog方式支持持久化的可靠性
5、数据一致性(事务)z
Memcache 在并发场景下,用cas保证一致性
redis事务支持比较弱,只能保证事务中的每个操作连续执行
mongoDB不支持事
5、数据分析
mongoDB内置了数据分析的功能(mapreduce),其他不支持
6、应用场景:
edis:数据量较小的更性能操作和运算上
memcache:用于在动态系统中减少数据库负载,提升性能;做缓存,提高性能(适合读多写少,对于数据量比较大,可以采用sharding)
MongoDB:主要解决海量数据的访问效率问题
缓存的常见问题:
1、缓存雪崩
一般是由于某个节点失效,导致其它节点的缓存命中率下降,缓存中
缺失的数据直接去数据库查询,短时间内造成数据库服务器崩溃。
或者是由于缓存周期性失效,比如设置每隔6个小时失效一次,那么每6个小时将会有一个请求峰值,严重的话,也会导致数据库崩溃。
重启DB后,短期内又被压垮,但缓存又会恢复一点,DB反复重启多次,直至缓存重建完毕,才能恢复稳定。
解决方案:
1、采用加锁计数,或者使用合理的队列数量来避免缓存失效时对数据库造成太大的压力。这种办法虽然能缓解数据库的压力,但是同时又降低了系统的吞吐量。
2、分析用户行为,尽量让失效时间点均匀分布。避免缓存雪崩的出现
3、如果是因为某台缓存服务器宕机,可以考虑做主备,比如:redis主备,但是双缓存涉及到更新事务的问题,update可能读到脏数据,需要好好解决。
2、缓存无底洞现象
即使增加缓存节点,访问速度依然不快。被称之为缓存无底洞现象
之前的两台缓存服务器都要访问一次。后来增加到4台,结果每台还是只连接一次。因为信息散落在了四台服务器上。
本来一开始只要访问2台,后来要访问4台。所以对于memcache的链接数,并没有随着节点的增多而降低!!!
更多的机器不代表更多的性能,所谓“无底洞”就是说投入越多不一定产出越多
解决办法:
把某一组key按照共同前缀来分布。
3、永久数据被踢现象
1、数据在内存中失效后,并不会立马被删除,只有在下次get时候,系统才会将其删除。
2、Memcache可以因此,被一些未被及时删除的数据占满空间。
3、加之LRU淘汰机制,永久数据如果很少被访问的话,在内存空间被占满的情况下,再有新数据被缓存,则永久数据,就有可能被删除。
解决方案:
永久数据和非永久数据分开放。
4、缓存穿透
缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库中查询。
大并发的缓存穿透会导致雪崩
解决方案:1、如果查询数据库也为空,直接设置一个默认值存放到缓存, 这样第二次到缓冲中获取就有值了,而不会继续访问数据
库,这种办法最简单粗暴。
2、根据缓存数据Key的规则,不符合规则就过滤掉。
这样可以过滤一部分查询。在做缓存规划的时候,Key有一定规则的话,可以采取这种办法。这种办法只能缓解一部分的压力,过滤和系统无关的查询,但是无法根治。
3、采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的BitSet中,不存在的数据将会被拦截掉,从而避免了对底层存储系统的查询压力
5、缓存预热
单机web系统情况下比较简单。
解决思路:
1,直接写个缓存刷新页面,上线时手工操作下。
2,数据量不大,可以在WEB系统启动的时候加载。
3,搞个定时器定时刷新缓存,或者由用户触发都行。