1.1 Memcached介绍
1.1.1 Memcached是什么
Memcached是一个开源的、支持高性能、高并发以及分布式的内纯缓存服务软件,从名称上前三个字符的单词Mem就是内存的意思,而后面的五个单词Cache就是缓存的意思,最后字符d,是daemon的意思,代表是服务端进程模式服务。
Memcached服务为C/S架构,分为服务端和客户端两部分,其中,服务端软件的名字形如Memcached-1.4.13.tar.gz,客户端软件的名字形如Memcache-2.25.tar.gz
Memcached诞生于2003年,最初由LiveJournal的BradFitzpatrick开发完成。Memcache是整个项目的名称,而 Memcached是服务器端的主程序名,因其协议简单,通过内存提供服务,且支持高并发而被广泛使用。
Memcached的作用
传统场景,多数web应用都将数据保存到RDBMS中,WWW服务器从中读取数据并在浏览器中显示,但随着数据量的增大、访问的集中,就会出现RDBMS的负担加重、数据库响应缓慢、网站打开延迟等恶劣影响。
这是就需要memcached出马了。Memcached是高性能的分布式内存缓存服务。使用Memcached的主要目的是,通过自身内存中缓存数据库 的查询结果,减少数据库访问次数,以提高动态web的应用的速度、提高网站架构的并发能力和可拓展性。
Memcached服务通过在事先规划好的系统内存空间中临时缓存数据库中的各类数据,以达到减少前端业务对数据库的直接高并发访问,从而达到提升大规模网站集群中动态服务的并发访问能力。
生产场景的Memcached服务一般被用来保存网站中经常被读取的对象或数据,就像我们的客户端浏览器也会把经常访问的网页缓存起来一样,通过内存来 存取对象或数据要比磁盘存取快很多,因为磁盘是机械的介质,因此,在当今的IT企业中,Memcached的应用范围很广。
互联网常见的内存缓存服务软件
Memcached常见用途工作流程
Memcached 是一种内存缓存软件,在工作中经常用户缓存数据库的查询数据,数据被缓存在事先预分配的Memcached管理的内存中,可以通过API的方式存取内存中 的缓存的这些数据,Memcached服务内存中缓存的数据就像一张巨大的HASH表,每条数据都是以key-value对的形式存在。
网站读取数据时Memcached的工作流程
Memcached缓存查询的数据库中的数据,当程序需要访问后端数据库获取数据时会有优先访问Memcached内存缓存,如果缓存中有数据就直接返回 给客户端,如果没有数据(没有命中)再去读取后端的数据库服务器读取数据,读取对应的数据后,在返回客户端的同时,还会把数据在Memcached内存中 进行缓存,以便下次被客户端访问,从而大大的减轻后端数据库的压力,提高整个网站架构的响应速度,提升了用户体验。
图4-1展示了Memcached缓存系统和后端数据库系统的协作流程。
图4-1Memcached作为缓存应用网站读数据流程图
1. 程序首先检查客户端请求的数据是否在Memcached缓存中存在,如果存在,直接把请求的数据返回,不再请求后端数据库。
2. 如果请求的数据在memcached缓存中不存在,则程序会去MEemcacched后端的数据库服务,把从数据库中渠道的数据返回给客户端,同时把新取到的数据缓存一份到Memcached缓存中。
网站更新数据时Memcached工作流程
当程序更新或者删除数据时,会首先处理数据库的数据,同时,通知Memcached中的对应旧数据失效,从而保证Memcache中缓存的数据始终和数据库中的数据一致,这个一致性非常重要。
当分配给Memcached内存空间用完之后,Memcached自身会使用LRU(LeastRecently Used,最近最少使用) 加到期失效策略,失效的数据首先被替换掉,然后是最近未使用的数据被替换掉。
如果是在高并发的场合,程序出了要通知Memcached过期的缓存失效外,还会通过相关机制,使得客户端在访问新数据前,预先把更新过的数据推送到 memcached中缓存起来,这样可以减少第一次查询数据库带来的访问压力,提升memcached中的缓存命中率。
1.1.4 Memcached在企业中的应用场景
作为数据库的查询数据缓存
1、 完整缓存(易)
例如:京东的商品分类,就可以事先放在MC内存里,然后在对外提供数据访问,这个被称之为预热。
此时可以只读取缓存就能读到商品分类数据,无需读取数据库了,所以数据库的压力就降下来了。
为什么商品分类可以事先放在缓存里呢?
因为商品分类是内部员工管理的,可以增加编辑后推送到Memcached内存里。
2、 热点缓存(难)
热 点缓存一般是指用户更新的商品,例如淘宝的卖家,当卖家新增商品后,淘宝网的程序就会把商品写入数据库,然后读取写入的数据,把这部分数据,放入 Memcached内存中,下一次访问这个商品的请求直接从Memcached内存中取走了。这种方法用来缓存网站的热点数据,既Memcached中经 常被访问的数据。
特别提示:这个过程可以通过程序实现,也可以在数据库上安装Memcache插件,直接由数据库出发更新内容到Memcached中。
淘宝、京东、小米等电商双11、秒杀抢购场景:
如果碰到双11、秒杀高并发的业务场景,必须要实现预热Memcached。
先把数据放入内存预热,然后再逐步动态更新,先读取缓存,如果缓存里没有对应的数据,再去读取数据库,然后把读到的数据放入缓存,如果数据库里的数据更新,需要同时触发缓存更新,防止给用户过期的数据,当然对于百万级别并发还有很多其他的工作要做。
所 有的网站动态数据都是保存在数据库当中的,每次频繁的存取数据库,会导致数据库性能急剧下降,无法同时服务更多的用户,比如MySQL特别频繁的锁表,那 么,就可以让Memcached来分担数据库的压力,增加memcached服务的好处除了可以分担数据库的压力,增加memcached架构也无需改动 整个网站架构,只需要修改程序让程序首先来读取Cache查询数据就好了,当然别忘了,更新数据时也要更新缓存。
4.1.6Memcached服务在大型站点中的应用
大型网站的设计原则
几乎所有的网站,当访问量增大时,在整个网站集群结构最先出现的瓶颈的几乎都是数据库角色以及存储角色的服务器,在工作中我们是尽量把用户的请求往整个网站架构的前面推,既当用户请求数据时,越是在靠近用户端把数据返回效果就越好-
分布式Memcached缓存服务架构
由于单台Memcached服务器的内存容量是有限的,并且单台也存在单点故障,因此,就需要将多个Memcached服务器组合起来提供服务,那么怎么组合效率才更高呢?
1. cache服务使用常规负载均衡模式的问题
2. 分布式缓存集群
a) Memcache支持分布式集群,其中方法之一就是在客户端应用程序上进行改造。例如:可以根据key适当进行有规律的封装,比如以用户为主的网站来说,每个用户都有 UserID,那么可以按照固定的id来进行提取和存取,如果1开头的用户保存在第一台memcache服务器上,以2开头的用户的数据保存在第二台 mecache服务器上,存取数据都按照UserID来进行相应的转换和存取。
但是这个有缺点,就是需要对UserID进行判断,如果业务不一致,或者其他类型的应用,可能不是那么合适,那么可以根据在iji的实际业务来进行考虑,或者去想更合适的方法
b) 在应用服务器上通过程序及URL_HASH,一致性哈希算法驱访问Memcached服务,所有Memcached服务器的地址池可以简单的配在每个程序的配置文件里。
c) 可以用Nginx的分支tengine实现对Mc的负载均衡,和普通web应用服务相比,这里的重点是调度算法,Mc服务一般会选择hash或一致性hash算法
i. 完整缓存,如果是多台就直接负载均衡。特点所有缓存数据都一样。百度的memcached TB 级别。一台机器的内存没那么大。就必须分布式。
ii. 热点缓存、分布式缓存
分布式缓存集群设计思想
1) 每一台MC服务器的内容都是不一样的,这些服务器内容加起来接近整个数据库的容量。
2) 通过在客户端程序或者MC的负载均衡器上用HASH算法,让同一内容都分配到一个MC服务器、
3) 普通的HASH算法对于节点宕机会带来大量的数据流动(失效),可能会引起雪崩效应
4) 一致性哈希算法(还可以带虚拟节点)可以让节点宕机对节点的数据流动(失效)降到最低。
分布式Memcached缓存集群调度算法
取模计算Hash
优点:简单、分散性优秀
缺点:添加/移除服务器时,缓存重组代价巨大,影响命中率
例:26个字母有三个节点增加一个节点,命中率下降了23%
Consistent Hash(一致性哈希算法)
Consistent hashing是一种算法,简单的说,在移除以及添加一个cache节点时,它能够尽可能小的改变已存在key的映射关系,尽可能让缓存服务器影响最小。
通常的hash算法都是讲value映射到一个32位的key值,既0-2^32-1次方的数组空间;可以将这个空间想象成一个首(0)尾(2^32-1)相接的圆环,如下面图所示:
Memcached的特性
Memcached作为高并发、高性能的缓存服务,具有如下特征:
C/S模式架构
Memcached是一套C/S模式架构的软件,由C语言编写,总共2000多行代码。
协议简单
Mmecached的协议实现比较简单,使用的是基于文本行的协议,能通过telnet/nc直接操作Memcached服务存取数据。
支持epoll/kqueue异步I/O模型,使用libevent作为事件处理通知机制。
简单的说,libevent是一套利用C开发的程序库,它将BSD系统的kqueue,Linux系统的epoll等事件处理功能封装成一个接口,确保即使服务器端的连接数增加也能发挥很好的性能。
Memcached就是利用这个库进行异步事件处理,关于这个库的更详细内容,有兴趣的读者可以查看相关文档
Key/value键值对数据类型
被缓存的数据以key/value键值对形式存在的。
全内存缓存,效率高
Memcached有一套自己管理内存的方式,这套管理方式非常高效,既全部数据都存放于Memcached服务实现分配的内存中,无持久性存储的设计,和系统的内存一样,重启系统或Memcached服务,Memcached内存中的数据既丢失。
如果希望重启后,数据依然能保留,那么就使用memcachedb以及redis这样的持久性内存缓存系统,当然还有常见的NOSQL软件如redis。