共计 4239 个字符,预计需要花费 11 分钟才能阅读完成。
简介
用过缓存零碎的必定都听过 memcached 的小名,memcached 是一个十分优良的分布式内存缓存零碎,利用十分的宽泛。Memcached 不仅仅是 Web 缓存,它更是一个通用的数据缓存,基本上你能够将任何货色存入 memcached 中,它的分布式设计具备很好的可扩展性和灵活性。
Memcached 是一个客户端 - 服务器端的架构模式。一般来说,在服务器上搭建好 Memcached 的服务器端,接下来就能够应用 Memcached 的客户端和服务器端进行替换了。
作为客户端和服务器端的模型,两者的通信必定是有特定的协定的,实用于 memcached 的协定就叫做 memcached protocol。
memcached 的协定有两种,别离是 text 协定和 binary 协定。本文将会具体解说 memcached text protocol 的定义。
memcached protocol 介绍
memcached 能够看做是一个简略的 key-value 的存储系统,客户端通过 key 来申请服务器端的数据,服务器端通过 key 的 hash 值来查找对应的数据,而后返回给客户端。
memcached 中的 key 长度个别不能超过 250 个字符。key 不能蕴含控制字符或空白字符。
为了保障客户端和服务器端的音讯通信顺畅,一般来说都会制订非凡的客户端和服务器端的通信协定,这个协定就叫做 protocol。
什么是 protocol 呢?protocol 听起来很浅近很神秘,然而实际上 protocol 就是约定好的单方交互的音讯格局。
对于 memcached 来说,memcached 同时反对 UDP 和 TCP 协定,并且提供了两种协定形式,别离是“文本协定”和“二进制协定”。
其中文本协定是在第一个版本就反对的协定,而二进制协定是在 v1.4 之后才反对的。
文本协定和二进制协定都反对同样的命令, 两者的惟一区别就是二进制协定具备更低的性能提早和更好的可扩展性,而文本协定的有点就是它的可调试性能更好。
memcached text 协定蕴含两局部数据,文本行和非结构化数据。前者是来自客户端的命令或来自服务器的响应,后者代表客户端拜访的数据。命令以 \r\n 结尾,数据能够用 \r、\n 或 \r\n,示意数据局部的完结。
memcached 反对的命令
memcached 反对三种命令,别离是存储命令, 读取命令和其余命令。
存储命令
memcached 中的存储命令总共有 6 个,别离是“set”、“add”、“replace”、“append”、”prepend” 和 “cas”。
首先,客户端发送如下所示的命令行:
command key [flags] [exptime] length [noreply]
另外 cas 命令的格局和其余几个不太一样:
cas key [flags] [exptime] length [casunique] [noreply]
下面的命令中,command 代表的是命令的名字,也就是下面的“set”、“add”、“replace”、“append”和 ”prepend”。
set 示意给 key 设置一个值。
Add 示意如果 key 不存在的话,就增加。
replace 用来替换已知 key 的 value。
append 示意将提供的值附加到现有 key 的 value 之后,是一个附加操作。
prepend 将以后 key 对应的 value 增加到提供的值前面。
cas 是一个原子操作,只有当 casunique 匹配的时候,才会设置对应的值。
flags 是一个十分乏味的参数,这个参数对于 memcached server 来说是通明的,这个参数只是用来标记客户端命令的类型,并不会被服务器端辨认。另外 flags 的长度在不同的 memcached 版本中也有所不同,在 memcached 1.2.0 或者依据低级的版本中,flags 是一个 16-bit 的整数。在 memcached 1.2.1 或以上的版本,flags 是一个 32-bit 的整数。
exptime 是过期工夫,0 示意不会过期。
length 是以 byte 示意的 value 的长度,这个值并不蕴含 value 中的结束符 ”\r\n”。
casunique 是一个 64-bit 的现有 entry 的惟一值。
noreply 通知服务器端,这是个不须要 reply 的命令。
在发送完命令行之后,客户端还须要发送数据块:
<data block>\r\n
举个例子,咱们想要将 jack 这个值设置到 student 这个 key 上,那么对应的命令应该如下所示:
set student 0 0 4\r\njack\r\n
对应的客户端收到的服务器端的返回可能有这些值:
- “STORED\r\n”,示意存储胜利。
- “NOT_STORED\r\n” 示意数据因为某些谬误未存储胜利。这通常意味着不满足“add”或“replace”命令的条件。
- “EXISTS\r\n” 示意要设置的值在上次进行 cas 操作之后曾经被批改了。
- “NOT_FOUND\r\n” 示意要设置的值用在 cas。
读取命令
memcached 的读取命令有 4 个,别离是“get”、“gets”、“gat”和“gats,这些命令的格局如下:
get <key>*\r\n
gets <key>*\r\n
gat <exptime> <key>*\r\n
gats <exptime> <key>*\r\n
memcached 中的读取命令前面不须要跟额定的数据块。
服务器端会依据接管到的 key 进行查问,每个 key 返回一条数据,格局如下:
VALUE <key> <flags> <bytes> [<cas unique>]\r\n
<data block>\r\n
在所有的数据都传输结束之后,服务器端会发送 ”END\r\n” 示意传输结束。
这里的 key 示意查问传入的 key。
flags 是存储命令传入的 flags。
bytes 是前面 data block 的长度。
cas unique 是以后 item 的惟一标记, 在 gets 或者 gats 命令中返回。
data block 是以后 item 具体的返回值。
下面咱们提到了 4 个读取的命令,那么他们有什么区别呢?
首先是 get 和 gets 的区别,get 用于获取 key 的 value 值,若 key 不存在,返回空。反对多个 key。gets 用于获取 key 的带有 CAS 令牌值的 value 值,若 key 不存在,返回空。反对多个 key。他们的区别在于 gets 会返回多一个 cas unique 值。
gat 和 get 的区别是,gat 是 get+touch 的命令综合体,除了返回以后值之外,还会更新 key 的过期工夫。
罕用的其余命令
除了存储和获取之外,还有一些罕用的其余命令。为什么这些命令被叫做第三类命令呢?这是因为这些命令只须要一个命令行即可,并不需要向服务器端传入额定的数据块。
上面是删除命令的格局:
delete <key> [noreply]\r\n
key 是要删除的对象。
noreply 示意是否须要收到服务器的返回值。
对应的服务器端返回值可能有两个:
- “DELETED\r\n” 示意删除胜利
- “NOT_FOUND\r\n” 示意要删除的对象并不存在。
上面是 Increment/Decrement 命令的格局:
incr <key> <value> [noreply]\r\n
decr <key> <value> [noreply]\r\n
key 是要批改的对象。
value 是要增加或者缩小的值, 它必须是一个 64-bit 无符号整数。
noreply 示意是否须要收到服务器的返回值。
服务器端的返回可能有两个:
- “NOT_FOUND\r\n” 示意要批改的对象没有找到
- “value\r\n” 返回批改胜利之后的值
还有一个罕用的是批改 key 过期工夫的 touch 命令:
touch <key> <exptime> [noreply]\r\n
key 是要批改的对象。
exptime 是过期工夫。
noreply 示意是否须要收到服务器的返回值。
服务器端的返回值有两种:
- “TOUCHED\r\n” 示意批改胜利。
- “NOT_FOUND\r\n” 示意要批改的对象不存在。
当然 memcached 反对的命令远不止下面所讲的这些。咱们只是从中挑选出了最罕用的一些命令进行解说。
memcached 服务器的返回值
下面在解说具体的命令的时候有提到服务器的返回值,这里再总结一下,memcached 服务器端的返回值有上面几种:
返回值 | 阐明 |
---|---|
STORED |
值存储胜利 |
NOT_STORED |
值存储失败 |
EXISTS |
cas 中要存储的对象已存在 |
NOT_FOUND |
要批改的对象不存在 |
ERROR |
提交了未知的命令 |
CLIENT_ERROR errorstring |
客户端输出有误,具体的错误信息寄存在 errorstring 中 |
SERVER_ERROR errorstring |
服务器端异样 |
VALUE keys flags length |
返回要查问的 key 对应的对象 |
DELETED |
对象曾经被删除 |
STAT name value |
统计信息 |
END |
服务器端返回完结 |
留神,下面所有的返回值都以 ”\r\n” 结尾。
反对 UDP 协定
下面咱们讲的都是 TCP 协定的报文格式。事实上 memcached 还反对 UDP 协定。
然而因为 UDP 不保障可靠性的特色,所以应用 UDP 的场合个别在做缓存的查问利用中,即便查问失败, 也只是被看做是缓存没有被命中而已,并不会影响到数据的准确性。
事实上 UDP 的数据包和 TCP 的数据包格局根本一样,只不过多了一个简略的帧头。并且所有的申请都必须在单个 UDP 数据包中实现。
留神,这里只有申请才有这个要求,服务器端的返回并没有这个限度。
在 UDP 中帧头长 8 个字节,其中 0 - 1 个字节示意的是申请 ID,申请 ID 是由客户端生成的一个枯燥递增的值。服务器端将会应用这个 ID 来标记是对哪个申请的响应。特地是在有服务器端有多个响应的状况下。
2- 3 个字节示意的是序列号,它的取值范畴是 0 到 n -1,其中 n 是音讯中总的报文个数,也就是 4 - 5 个字节所示意的。
最初的 6 - 7 字节是保留字节,以备未来应用,当初设置为 0。
总结
以上就是对 memcached 协定的介绍,通常来说咱们应用 memcached 都是通过 memcached 客户端来进行的,如果有仔细的敌人可能会发现,客户端应用的命令和协定中的命令差异不大,这是因为客户端就是对这些底层协定的封装,而后裸露给用户一个更加简略易操作的接口。
更多内容请参考 http://www.flydean.com/23-memcached-text-protocol/
最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!
欢送关注我的公众号:「程序那些事」, 懂技术,更懂你!