分布式缓存-memcached

转载
分布式缓存:
思考:
1.分布式水平线性扩展问题
2.高并发情况下的性能问题
3.避免单点故障问题
分布式缓存管理核心:
1.内存的分配,管理和回收
2.分布式管理和分布式算法
*3.缓存键值管理和路由

什么是Memcached:

许多Web 应用程序都将数据保存到RDBMS中,应用服务器从中读取数据并在浏览器中显示。但随着数据量的增大,访问的集中,就会出现REBMS的负担加重,数据库响应恶化,网站显示延迟等重大影响。Memcached是高性能的分布式内存缓存服务器。一般的使用目的是通过缓存数据库查询结果,减少数据库的访问次数,以提高动态Web 应用的速度、提高扩展性。如图:
这里写图片描述

Memcached作为高速运行的分布式缓存服务器具有以下特点:

协议简单:memcached的服务器客户端通信并不使用复杂的MXL等格式,而是使用简单的基于文本的协议。
基于libevent的事件处理:libevent是个程序库,他将Linux 的epoll、BSD类操作系统的kqueue等时间处理功能封装成统一的接口。memcached使用这个libevent库,因此能在Linux、BSD、Solaris等操作系统上发挥其高性能。
内置内存存储方式:为了提高性能,memcached中保存的数据都存储在memcached内置的内存存储空间中。由于数据仅存在于内存中,因此重启memcached,重启操作系统会导致全部数据消失。另外,内容容量达到指定的值之后memcached回自动删除不适用的缓存。
Memcached不互通信的分布式:memcached尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。各个memcached不会互相通信以共享信息。他的分布式主要是通过客户端实现的。

Memcached的内存管理:
转载

Memcached 采用Slab Allocator内存管理的原理

slab算法的发现是基于内核中内存使用的一些特点:一些需要频繁使用的同样大小数据经常在使用后不久又再次被用到;找到合适大小的内存所消耗的时间远远大于释放内存所需要的时间。所以Slab算法的发明人认为内存对象在使用之后不是立即释放给系统而是将它们用链表之类的数据结构管理起来以备将来使用,频繁分配和释放的内存对象应该用缓存管理起来。Linux的slab分配器就是基于这样的想法实现的,这个算法在空间和时间上都有很高的效率。

Slab implementation

Slab Allocation的原理相当简单。它首先从操作系统申请一大块内存,并将其分割成各种尺寸的块Chunk,并把尺寸相同的块分成组Slab Class。其中,Chunk就是用来存储key-value数据的最小单位。每个Slab Class的大小,可以在Memcached启动的时候通过制定Growth Factor来控制。假定Figure 1中Growth Factor的取值为1.25,所以如果第一组Chunk的大小为88个字节,第二组Chunk的大小就为112个字节,依此类推

这里写图片描述

当Memcached接收到客户端发送过来的数据时首先会根据收到数据的大小选择一个最合适的Slab Class,然后通过查询Memcached保存着的该Slab Class内空闲Chunk的列表就可以找到一个可用于存储数据的Chunk。当一条数据库过期或者丢弃时,该记录所占用的Chunk就可以回收,重新添加到空闲列表中。从以上过程我们可以看出Memcached的内存管理制效率高,而且不会造成内存碎片,但是它最大的缺点就是会导致空间浪费。因为每个 Chunk都分配了特定长度的内存空间,所以变长数据无法充分利用这些空间。如图所示,将100个字节的数据缓存到128个字节的Chunk中,剩余的28个字节就浪费掉了

这里写图片描述

这里写图片描述

每个缓存对象包含了slab对象的链表。一个slab对象是一块连续内存(页面)。其中有三个slab对象链表:
slabs_full,完全分配好的slab对象链表
slabs_partial,部分分配好的slab对象链表
slabs_empty,空对象链表,slab对象都没有分配好
其中空对象链表是内存回收的主要候选来源。slab链表上的对象是一块连续内存,这块内存被分成内存数据对象。这些数据对象是slab缓存上分配和释放的最小单位。
由于数据对象是从slab上分配的,所以单个的slab可以从一个slab链表移动到另一个slab链表。比如当slabs_partial上的一个slab的内存对象全部被分配了之后,这个slab就从slabs_partial上移动到slabs_full。当slabs_full上的一个slab上的部分内存对象被释放之后,这个slab就从slabs_full链表移动到slabs_partial上,当这个slab上的所有内存对象都被释放之后,它就会再次移动到slabs_empty上。

slab分配器带来的好处

通过缓存类似对象数据,内核中频繁的小数据对象的分配不会再消耗过多的时间,同时减少了系统的内存碎片
slab分配支持常用对象数据的初始化,减少了同类对象数据重复的初始化过程
slab分配支持硬件缓存对齐和着色,这样不同缓存下的对象数据可以使用同样的硬件缓存行,可以提高系统的性能
Memcached在数据删除方面有效里利用资源

Memcached删除数据时数据不会真正从memcached中消失。Memcached不会释放已分配的内存。记录超时后,客户端就无法再看见该记录(invisible 透明),其存储空间即可重复使用。

Lazy Expriationmemcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。这种技术称为lazy expiration.因此memcached不会再过期监视上耗费CPU时间。

对于缓存存储容量满的情况下的删除需要考虑多种机制,一方面是按队列机制,一方面应该对应缓存对象本身的优先级,根据缓存对象的优先级进行对象的删除。

LRU:从缓存中有效删除数据的原理

Memcached会优先使用已超时的记录空间,但即使如此,也会发生追加新纪录时空间不足的情况。此时就要使用名为Least Recently Used (LRU)机制来分配空间。这就是删除最少使用的记录的机制。因此当memcached的内存空间不足时(无法从slab class)获取到新空间时,就从最近未使用的记录中搜索,并将空间分配给新的记录。

Memcached分布式:

Memcached虽然称为“分布式“缓存服务器,但服务器端并没有“分布式”的功能。Memcached的分布式完全是有客户端实现的。现在我们就看一下memcached是怎么实现分布式缓存的。

例如下面假设memcached服务器有node1~node3三台,应用程序要保存键名为“tokyo”“kanagawa”“chiba”“saitama”“gunma” 的数据。

首先向memcached中添加“tokyo”。将“tokyo”传给客户端程序库后,客户端实现的算法就会根据“键”来决定保存数据的memcached服务器。服务器选定后,即命令它保存“tokyo”及其值。

同样,“kanagawa”“chiba”“saitama”“gunma”都是先选择服务器再保存。

接下来获取保存的数据。获取时也要将要获取的键“tokyo”传递给函数库。函数库通过与数据保存时相同的算法,根据“键”选择服务器。使用的算法相同,就能选中与保存时相同的服务器,然后发送get命令。只要数据没有因为某些原因被删除,就能获得保存的值。
这里写图片描述
这样,将不同的键保存到不同的服务器上,就实现了memcached的分布式。 memcached服务器增多后,键就会分散,即使一台memcached服务器发生故障无法连接,也不会影响其他的缓存,系统依然能继续运行。

Consistent Hashing:

Memcached采用键值分布策略:consistent hashing算法
参考博客1
参考博客2

缓存多副本

缓存多副本主要是用于在缓存数据存放时存储缓存数据的多个副本,以防止缓存失效。缓存失效发生在以下几种情况:
1. 缓存超时被移除(正常失效)
2. 缓存由于存储空间限制被移除(异常失效)
3. 由于缓存节点变化而导致的缓存失效(异常失效)
在缓存多副本的情况下,需要重新考虑缓存的分布式分布策略。其次缓存的多个副本实际本身是可能的多个读的节点,可以做为分布式的并行读,这是另外一个可以考虑的问题。

缓存数据的一致性问题

缓存数据尽量只读,因此缓存本身是不适合大量写和更新操作的数据场景的。对于读的情况下,如果存在数据变化,一种是同时更新缓存和数据库。一种是直接对缓存数据进行失效处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值