如何分析memcached的删除机制和发展方向

64次阅读
没有评论

共计 4722 个字符,预计需要花费 12 分钟才能阅读完成。

本篇文章为大家展示了如何分析 memcached 的删除机制和发展方向,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

memcached 是缓存,所以数据不会永久保存在服务器上,这是向系统中引入 memcached 的前提。下面介绍 memcached 的数据删除机制,以及 memcached 的最新发展方向——二进制协议(Binary Protocol)和外部引擎支持。

memcached 在数据删除方面有效利用资源数据不会真正从 memcached 中消失

上次介绍过,memcached 不会释放已分配的内存。记录超时后,客户端就无法再看见该记录(invisible,透明),其存储空间即可重复使用。

Lazy Expiration

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

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

memcached 会优先使用已超时的记录的空间,但即使如此,也会发生追加新记录时空间不足的情况,此时就要使用名为 Least Recently Used(LRU)机制来分配空间。顾名思义,这是删除“最近最少使用”的记录的机制。因此,当 memcached 的内存空间不足时(无法从 slab class  获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。从缓存的实用角度来看,该模型十分理想。

不过,有些情况下 LRU 机制反倒会造成麻烦。memcached 启动时通过“-M”参数可以禁止 LRU,如下所示:

$ memcached -M -m 1024

启动时必须注意的是,小写的“-m”选项是用来指定最大内存大小的。不指定具体数值则使用默认值 64MB。

指定“-M”参数启动后,内存用尽时 memcached 会返回错误。话说回来,memcached 毕竟不是存储器,而是缓存,所以推荐使用 LRU。

memcached 的最新发展方向

memcached 的 roadmap 上有两个大的目标。一个是二进制协议的策划和实现,另一个是外部引擎的加载功能。

关于二进制协议

使用二进制协议的理由是它不需要文本协议的解析处理,使得原本高速的 memcached 的性能更上一层楼,还能减少文本协议的漏洞。目前已大部分实现,开发用的代码库中已包含了该功能。memcached 的下载页面上有代码库的链接。

http://danga.com/memcached/download.bml

二进制协议的格式

协议的包为 24 字节的帧,其后面是键和无结构数据(Unstructured Data)。实际的格式如下(引自协议文档):

 Byte/ 0 | 1 | 2 | 3 | 
 / | | | | 
 |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
 +---------------+---------------+---------------+---------------+
 0/ HEADER / 
 / / 
 / / 
 / / 
 +---------------+---------------+---------------+---------------+
 24/ COMMAND-SPECIFIC EXTRAS (as needed) / 
 +/ (note length in th extras length header field) / 
 +---------------+---------------+---------------+---------------+
 m/ Key (as needed) / 
 +/ (note length in key length header field) / 
 +---------------+---------------+---------------+---------------+
 n/ Value (as needed) / 
 +/ (note length is total body length header field, minus / 
 +/ sum of the extras and key length body fields) / 
 +---------------+---------------+---------------+---------------+
 Total 24 bytes

如上所示,包格式十分简单。需要注意的是,占据了 16 字节的头部 (HEADER) 分为 请求头(Request Header)和响应头(Response Header)两种。头部中包含了表示包的有效性的 Magic 字节、命令种类、键长度、值长度等信息,格式如下:

Request Header
 Byte/ 0 | 1 | 2 | 3 |
 / | | | |
 |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
 +---------------+---------------+---------------+---------------+
 0| Magic | Opcode | Key length |
 +---------------+---------------+---------------+---------------+
 4| Extras length | Data type | Reserved |
 +---------------+---------------+---------------+---------------+
 8| Total body length |
 +---------------+---------------+---------------+---------------+
 12| Opaque |
 +---------------+---------------+---------------+---------------+
 16| CAS |
 | |
 +---------------+---------------+---------------+---------------+
Response Header
 Byte/ 0 | 1 | 2 | 3 |
 / | | | |
 |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
 +---------------+---------------+---------------+---------------+
 0| Magic | Opcode | Key Length |
 +---------------+---------------+---------------+---------------+
 4| Extras length | Data type | Status |
 +---------------+---------------+---------------+---------------+
 8| Total body length |
 +---------------+---------------+---------------+---------------+
 12| Opaque |
 +---------------+---------------+---------------+---------------+
 16| CAS |
 | |
 +---------------+---------------+---------------+---------------+

如希望了解各个部分的详细内容,可以 checkout 出 memcached 的二进制协议的代码树,参考其中的 docs 文件夹中的 protocol_binary.txt 文档。

HEADER 中引人注目的地方

看到 HEADER 格式后我的感想是,键的上限太大了!现在的 memcached 规格中,键长度最大为 250 字节,但二进制协议中键的大小用 2 字节表示。因此,理论上最大可使用 65536 字节(2 sup 16 /sup)长的键。尽管 250 字节以上的键并不会太常用,二进制协议发布之后就可以使用巨大的键了。

二进制协议从下一版本 1.3 系列开始支持。

外部引擎支持

我去年曾经试验性地将 memcached 的存储层改造成了可扩展的(pluggable)。

http://alpha.mixi.co.jp/blog/?p=129

MySQL 的 Brian Aker 看到这个改造之后,就将代码发到了 memcached 的邮件列表。memcached 的开发者也十分感兴趣,就放到了 roadmap 中。现在由我和 memcached 的开发者 Trond Norbye 协同开发(规格设计、实现和测试)。和国外协同开发时时差是个大问题,但抱着相同的愿景,最后终于可以将可扩展架构的原型公布了。代码库可以从 memcached 的下载页面   上访问。

外部引擎支持的必要性

世界上有许多 memcached 的派生软件,其理由是希望永久保存数据、实现数据冗余等,即使牺牲一些性能也在所不惜。我在开发 memcached 之前,在 mixi 的研发部也曾经 考虑过重新发明 memcached。

外部引擎的加载机制能封装 memcached 的网络功能、事件处理等复杂的处理。因此,现阶段通过强制手段或重新设计等方式使 memcached 和存储引擎合作的困难 就会烟消云散,尝试各种引擎就会变得轻而易举了。

简单 API 设计的成功的关键

该项目中我们最重视的是 API 设计。函数过多,会使引擎开发者感到麻烦;过于复杂,实现引擎的门槛就会过高。因此,最初版本的接口函数只有 13 个。具体内容限于篇幅,这里就省略了,仅说明一下引擎应当完成的操作:

引擎信息(版本等)

引擎初始化

引擎关闭

引擎的统计信息

在容量方面,测试给定记录能否保存

为 item(记录)结构分配内存

释放 item(记录)的内存

删除记录

保存记录

回收记录

更新记录的时间戳

数学运算处理

数据的 flush

对详细规格有兴趣的读者,可以 checkout engine 项目的代码,阅读器中的 engine.h。

重新审视现在的体系

memcached 支持外部存储的难点是,网络和事件处理相关的代码(核心服务器)与 内存存储的代码紧密关联。这种现象也称为 tightly coupled(紧密耦合)。必须将内存存储的代码从核心服务器中独立出来,才能灵活地支持外部引擎。因此,基于我们设计的 API,memcached 被重构成下面的样子:

重构之后,我们与 1.2.5 版、二进制协议支持版等进行了性能对比,证实了它不会造成性能影响。

在考虑如何支持外部引擎加载时,让 memcached 进行并行控制(concurrency control)的方案是最为容易的,但是对于引擎而言,并行控制正是性能的真谛,因此我们采用了将多线程支持完全交给引擎的设计方案。

以后的改进,会使得 memcached 的应用范围更为广泛。

上述内容就是如何分析 memcached 的删除机制和发展方向,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注丸趣 TV 行业资讯频道。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-16发表,共计4722字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)