memcache缓存服务器概念篇
mamcache是一套分布式的高速缓存系统,可以提高网站访问的速度,尤其是对于一些大型的公司或者频繁访问数据库的网站访问速度提升效果十分显著,memcache是一个开源免费的软件,memcache通过键值对的访问将数据缓存在内存当中,减少从后端数据读取数据的次数。
2,memcache分布式缓存系统
分布式:将数据分散存储在不同服务器上。
缓存系统:严格意义上来说,memcache不是一个nosql数据库,只是提供内存缓存功能系统,那怎么理解别人来说memcache是一个nosql数据库呢?关系型数据库是基于二维表来存放数据(事务,元祖,数据的持久性)等,最简单的理解就是数据在断电后不会丢失,非关系型数据库不使用sql语句来进行数据的查询而是基于key-value存储和读取数据的,所以又可以理解成nosql数据库了。
3,memcache和mysql区别
1)没有使用sql语句查询或存储数据;
2)memcache中没有mysql的表的概念,都是使用键值对来保存的;
3)memcache的数据保存在内存当中,数据读取速度快,数据断电丢失;
4,memcache分布式部署的原理
memcache虽然被称为“分布式缓存”,但是memcache本身完全不具备分布式的功能,memcache集群之间不会相互通信,所谓的“分布式”,完全依赖于客户端程序的实现,就像下面这张图的流程一样。
同时基于这张图,理一下memcache一次写缓存的流程:
① 应用程序输入需要写缓存的数据;
② API将key输入路由算法模块,路由算法根据key和memcache集群服务器列表得到一台服务器编号;
③ 由服务器编号得到memcache及其的ip地址和端口号;
④ API调用通信模块和指定编号的服务器通信,将数据写入该服务器,完成一次分布式缓存的写操作。
读操作和写缓存一样,只要使用相同的路由算法和服务器列表,只要应用程序查询的是相同的key,memcache客户端总是访问相同的客户端去读取数据,只要服务器中还缓存着该数据,就能保证缓存命中。
这种memcache集群的方式也是从分区容错性的方面考虑的,假如node02宕机了,那么node02上面存储的数据都不可用了,此时由于集群中node0和node1还存在,下一次请求node02中存储的key值的时候,肯定是没有命中的,这时先从数据库中拿到要缓存的数据,然后路由算法模板根据key值在node0和node1中选取一个节点,把对应的数据放进去,这样下一次就有可以走缓存了。但集群的做法要考虑成本的问题。
5,路由算法
从上面的图中,看出对服务器集群的管理,路由算法至关重要,就和负载均衡算法一样,路由算法决定着究竟该访问集群中的哪台服务器。
1)余数hash算法:
将要存储的key-vaule数据进行hash运算得到一个值,然后根据memcache的数据进行整除取余。根据余数把数据方放到对应的服务器上,由于hash值的随机性很大,所以服务器上存放的数据也就比较平衡,一般不会造成大量数据只放在一台服务器上的情况,但是这样又出现一个问题,当添加一台节点的时候,之前的数据就会读取不到。
解决方案:
(1)在网站访问量低的时候,技术团队加班,扩容,重启服务器
(2)通过模拟请求的方式进行缓存预热,使服务器中的数据重新分布。
2) 一致性hash算法:
通过一个叫做一致性hash环的数据结果实现key到缓存服务器的hash映射,简单来说一致性hash将整个hash值的控制组织成一个虚拟的圆环(这个环被称为一致性hash环)
缺点:当服务器节点太少的时候,容易造成节点数据不均匀。可以选择采用增加虚拟节点的方式解决。
更重要的是,集群中缓存服务器节点越多,增加/减少节点带来的影响越小;也就是说随着集群规模的增大,继续命中原有缓存数据的概率会越来越大,虽然仍然有小部分数据缓存在服务器中不能被读到,但是这个比例足够小,即使访问数据库,也不会对数据库造成致命的负载压力。
6,memcache实现原理
首先要说明一点,memcache的数据存放在内存中,因此有以下特点:
1)访问数据的速度比传统的关系型数据库要快,因为传统的关系型数据库(mysql,oracle)为了保证数据的持久性,数据存放在硬盘中,io操作速度慢。
2)memcache的数据存放在内存中,只要memcache重启,数据就会丢失。
3)既然memacache的数据存放在内存中,那么势必受到机器位数的限制,32位机器最多只能使用2GB的内存空间,64位机器可以认为没有上限。
然后我们来看一下memcache的原理,memcache最重要的是内存如何分配,memcache采用的内存分配方式是固定空间分配,如下图所示:
这张图片里面涉及了 slab_class、 slab、 page、 chunk 四个概念,它们之间的关系是:
1、 MemCache 将内存空间分为一组 slab;
2、每个 slab 下又有若干个 page,每个 page 默认是 1M,如果一个 slab 占用 100M 内存的话,那么这个 slab 下应该有 100 个 page;
3、每个 page 里面包含一组 chunk, chunk 是真正存放数据的地方,同一个 slab 里面的 chunk的大小是固定的;
4、有相同大小 chunk 的 slab 被组织在一起,称为 slab_class;
MemCache 内存分配的方式称为 allocator(分配运算), slab 的数量是有限的,几个、十几个或者几十个,这个和启动参数的配置相关。
memcache中的value存放的地方是有value的大小决定的,value总是会被存放到chunk大小最接近的一个slab中,比如 slab[1]的chunk 大小为 80 字节、 slab[2]的 chunk 大小为 100字节、 slab[3]的 chunk 大小为 128 字节(相邻 slab 内的 chunk 基本以 1.25 为比例进行增长,MemCache 启动时可以用-f 指定这个比例),那么过来一个88字节的value,这个value将被放到2号slab中。
放到slab的时候,首先slab要申请内存,申请内存是以page为单位的,所以在放入第一个数据的时候,无论带下多少,都会有1M大小的page被分配给该slab。申请到page后, slab会将这个page的内存按chunk的大小进行切分,这样就变成了一个chunk数组,最后从这个 chunk 数组中选择一个用于存储数据。
如果这个slab中没有chunk可以分配了怎么办,如果memcache启动没有追加-M(禁止LRU,这种情况下内存不够会报Out Of Memory 错误),那么 MemCache 会把这个 slab 中最近最少使用的 chunk 中的数据清理掉,然后放上最新的数据。
7,memcache的工作流程
(1)检查客户端的请求数据是否在memcached中,如果有,直接把请求数据返回,不在对数据库进行任何操作,路径操作为①②③⑦。
(2)如果请求的数据不在memcached中,就去查数据库,把从数据库中获取的数据返回给客户端,同时把数据缓存一份到memecached中(memcached客户端不负责,需要程序明确实现),路径操作为①②④⑤⑦⑥。
(3)每次更新数据库的同时更新memcached中的数据,保证一致性。
(4)当分配给memcached内存空间用完之后,会使用LRU策略加上到期失效策略,失效数据首先被替换,然后再替换掉最近未使用的数据。
8,memcached的特征
协议简单:
基于文本协议:常见的协议http,ftp,smtp都是基于文本行的,所谓基于文本行,指的是信息以文本传递;
基于libevent事件处理:
libevent是一套利用c语言开发的程序库,它将BSD系统的kqueue(BSD是unix的衍生版本),linux系统的epoll等事件处理功能封装成一个接口,与传统的select相比,提高了性能。
内置的内存管理方式:
所有数据都保存在内存中,数据访问速度快,但没有考虑数据单点容灾问题,重启服务,所有数据会丢失。
分布式:
各个memcached服务器之间互不通信,各自独立存取数据,不共享任何信息,服务器并不具备分布式功能,分布是部署取决于memcache客户端。
memcache的安装分为两个过程:memcache服务器端的安装和memcached客户端的安装。