图片 4

twemproxyMemcache协议分析探寻

Posted by

简介

memcached是无偿和绽放源代码的高品质布满式内部存储器对象缓存系统,意在通过缓慢解决数据库负载来增长速度动态Web应用程序。其有以下特征:

  • 据说轻便的文本行协议
  • 整体数量遵照k/v形式存放在内部存款和储蓄器中,无持久化,重启服务多少会丢掉
  • 基于libevent异步I/O模型的事件通报机制。libevent是个程序库,它将Linux的epoll、BSD类操作系统的kqueue等事件处理成效封装成统一的接口。固然对服务器的连接数扩充,也能表明O(一)的性质。memcached使用这几个libevent库,由此能在Linux、BSD、Solaris等操作系统上发挥其高质量
  • 节点之间相互独立,达成布满式必要依赖客户端

其貌似作为后端数据库的缓存层来减弱数据库的下压力:

图片 1

memcache是一种和redis类似的高速缓存服务器,不过memcache只提供键值对那种总结的储存格局,相对于redis协理的囤积形式二种化,memcache就比较轻巧了。memcache通过tcp大概udp连接来促成memcache客户端和服务端的互动。memcache的情商是自定的,也分为两种:壹种是文件协议(那是大家明日探讨的机要),另1种是贰进制协议(在大家今日商量的范围),这里唯有介绍用tcp连接以及文本协议通讯的memcache协议。如有描述不当的地点请我们提出。

安装memcached

#先安装依赖软件
$ yum install gcc libevent libevent-devel
#源码安装memcached
$ cd /usr/local/src
$ wget http://memcached.org/files/memcached-1.5.2.tar.gz
$ tar -zxvf memcached-1.5.2.tar.gz
$ cd memcached-1.5.2
$ ./configure --prefix=/usr/local/memcached && make && sudo make install

memcache文本研讨

启动

$ /usr/local/memcached/bin/memcached -d -u root -l 192.168.56.10 -p 32054 -m 10 -c 100 -P /tmp/memcached_32054.pid
#选项说明,这里只列出比较重要的选项,具体选项说明使用memcached -h来查阅
-p   TCP端口,默认为11211,可以不设置
-U   UDP端口,默认为11211,0为关闭
-l   监听的ip地址
-d   守护进程(daemon)
-u   指定用户,如果当前为 root ,需要使用此参数指定用户
-m   最大内存,单位MB。默认64MB,32位操作系统,每个进程最多只能使用2GB,64位无限制
-M   禁止LRU策略,内存耗尽时返回错误,而不是删除数据
-c   最大连接数,默认是1024
-vv  查看日志
-P   memcache的pid文件,结束memcache进程:kill `cat /tmp/memcached_32054.pid`
-f   增长因子,默认1.25
-n   初始chunk=key+suffix+value+32结构体,默认48字节
-L   启用大内存页,可以降低内存浪费,改进性能
-t   线程数,默认4。由于memcached采用NIO,所以更多线程没有太多作用
-R   每个event连接最大并发数,默认20
-C   禁用CAS命令(可以禁止版本计数,减少开销)
-I   每次申请内存的页的大小(page),默认1M,最小1k,最大128M
-F   禁用flush_all

仓库储存命令

翻看进度

$ ps -aux | grep memcached
root      1359  0.0  0.3 413804  3132 ?        Ssl  13:51   0:00 /usr/local/memcached/bin/memcached -d -u root -p 32054 -m 10 -c 100
root      1372  0.0  0.0 112660   972 pts/0    R+   13:51   0:00 grep --color=auto memcached

add/replace/set/append/prepend命令格式如下:

宗旨命令

指令格式:

<command name> <key> <flags> <exptime>
<bytes> [noreply]\r\n
cas <key> <flags> <exptime> <bytes> <cas
unique> [noreply]\r\n

<command name> 有这么多少个: “set”, “add”, “replace”, “append”,
“prepend”

<flags>是服务器随多寡一同存款和储蓄的自由公斤人无符号整数(用十进制表示),并在寻觅项目时重回。
对于memcached的php客户端来讲flags=0表示不促销扣

$ telnet localhost 32054
Trying ::1...
Connected to localhost.
Escape character is '^]'.
stats #查看memcache状态
...
END

set name 0 0 3
hioooo
CLIENT_ERROR bad data chunk #超过3个字节存不下
ERROR

#设置1个数字
set count 0 0 1
1
STORED

#递增
incr count 1
2
incr count 6
8

#递减
decr count 1
7

#设置一个字符串
set myname 0 0 3
pig
STORED

#获取
get myname
VALUE myname 0 3
pig
END

#不存在则添加
add height 0 0 4
1.75
STORED
add myname 0 0 3
zhu
NOT_STORED #这儿因为myname已经存在,所以返回失败

#替换
replace height 0 0 4
1.60
STORED

#向已存在的缓存后面追加内容
append myname 0 0 3
fly
STORED

#向已存在的缓存前面追加内容
prepend myname 0 0 3
pig
STORED

#gets & cas 控制并发写,gets获得一个id,cas保存的时候带上这个id,如果发现id没变,保存之,并且更新id,如果变了说明数据已经被更新了,保存失败
gets myname
VALUE myname 0 6 6
pigfly
END
cas myname 0 0 3 6
zhu
STORED
get myname
VALUE myname 0 3
zhu

#设置缓存并且设定过期时间
#有效期可以是UNIX时间戳(从1970年1月1日开始的秒钟数),也可以是距离当前的秒数,对于后者而言,不能超过60*60*24*30(30天)
#下面把有效期设置为100天的秒数的后果就是马上就失效了,完全get不到
#至于设置为100天后的UNIX时间戳是不是能在100天后过期就不知道了,有人测试过记得告诉我~
set phone 0 8640000 11
13847292929
STORED
get phone
END

#向已存在的数据设置过期时间
touch myname 10

#删除
delete myname
DELETED
get myname
END

#清空所有缓存
flush_all
OK
get myname
END
get myname count
END

<command name> <key>
<flags> <exptime> <bytes>\r\n

动静新闻

STAT pid 1359 #memcache服务器的进程ID
STAT uptime 6630 #服务器已经运行的秒数
STAT time 1508917290 #服务器当前的unix时间戳
STAT version 1.5.2 #memcache版本
STAT libevent 2.0.21-stable #libevent版本
STAT pointer_size 64 #当前操作系统的指针大小(32位系统一般是32bit,64就是64位操作系统)
STAT rusage_user #0.835764 seconds the cpu has devoted to the process as the user,  cpu投入到进程的累计用户时间
STAT rusage_system 0.685101 #seconds the cpu has devoted to the process as the system, 进程的累计系统时间
STAT max_connections 100 #最大连接数
STAT curr_connections 10 #当前连接数
STAT total_connections 12 #启动以来总的连接数
STAT rejected_connections 0 #拒绝连接数
STAT connection_structures 11 #已分配的连接结构数
STAT reserved_fds 20 #Number of misc fds used internally
STAT cmd_get 2 #get(获取)次数
STAT cmd_set 4 #set(保存)次数
STAT cmd_flush 0 #flush(清空)次数
STAT cmd_touch 0 #更新过期时间次数
STAT get_hits 2 #获取命中次数
STAT get_misses 0 #获取失败次数
STAT get_expired 0 #获取已过期数据的次数
STAT get_flushed 0 #获取已被清空的数据的次数
STAT delete_misses 0 #删除失败次数
STAT delete_hits 0 #删除成功次数
STAT incr_misses 0 #递增失败次数
STAT incr_hits 0 #递增成功次数
STAT decr_misses 0 
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 133 #读取字节数
STAT bytes_written 159 #写入字节数
STAT limit_maxbytes 10485760 #分配给memcache的内存大小(字节)
STAT accepting_conns 1 #Whether or not server is accepting conns(服务器是否接受连接)
STAT listen_disabled_num 0
STAT time_in_listen_disabled_us 0
STAT threads 4 #当前线程数
STAT conn_yields 0 #连接操作主动放弃数目
STAT hash_power_level 16
STAT hash_bytes 524288
STAT hash_is_expanding 0
STAT slab_reassign_rescues 0
STAT slab_reassign_chunk_rescues 0
STAT slab_reassign_evictions_nomem 0
STAT slab_reassign_inline_reclaim 0
STAT slab_reassign_busy_items 0
STAT slab_reassign_busy_deletes 0
STAT slab_reassign_running 0
STAT slabs_moved 0
STAT lru_crawler_running 0
STAT lru_crawler_starts 3825
STAT lru_maintainer_juggles 12722
STAT malloc_fails 0
STAT log_worker_dropped 0
STAT log_worker_written 0
STAT log_watcher_skipped 0
STAT log_watcher_sent 0
STAT bytes 130 #当前存储占用的字节数
STAT curr_items 2 #当前存储的数据总数
STAT total_items 2 #启动以来存储的数据总数
STAT slab_global_page_pool 0
STAT expired_unfetched 0
STAT evicted_unfetched 0
STAT evicted_active 0
STAT evictions 0 #为获取空闲内存而删除的items数(分配给memcache的内存用满后需要删除旧的items来得到空间分配给新的items)
STAT reclaimed 0 #已过期的数据条目来存储新数据的数目
STAT crawler_reclaimed 0
STAT crawler_items_checked 10
STAT lrutail_reflocked 0
STAT moves_to_cold 2
STAT moves_to_warm 0
STAT moves_within_lru 0
STAT direct_reclaims 0
STAT lru_bumps_dropped 0

<data block>\r\n

安全

服务器一般有八个网卡,一个针对性内网,二个针对外网。由于memcached未有密码验证,就算一向揭示在外网,数据就可以随随意便被客人使用,大家能够有三种艺术来界定连接:

一.内网走访,运行memcached的时候增进-l参数,让memcached监听内网ip

$ memcached -d -m 1024  -u root -l 192.168.56.10 -p 32054 -c 1024

  

二.安装防火墙规则

$ iptables -F
$ iptables -P INPUT DROP
$ iptables -A INPUT -p tcp -s 192.168.56.10 --dport 32054 -j ACCEPT
$ iptables -A INPUT -p udp -s 192.168.56.10 --dport 32054 -j ACCEPT

格式的牵线如下:

自动重启&监察和控制

memcached有时候会冒出进度死掉的情事,那时候只要重启,又有什么不可日常使用。所以大家能够有个监察和控制memcached进度的脚本来完成当memcached进度死掉未来自动重启memcached,能够运用daemondtools,脚本如下:

#!/bin/sh
if [ f
/etc/sysconfig/memcached ];then
. /etc/sysconfig/memcached
fi
exec 2>&1
exec /usr/bin/memcached p
$PORT u
$USER m
$CACHESIZE c
$MAXCONN
$OPTIONS

通过STATS命令能够协和完成脚本来达到监察和控制的目标,php客户端方面有人写了个memcache.php,还足以行使nagios+rrdtool用直观化的图样形式贯彻:

图片 2

<command
name>能够是add(即扩充不设有的键值对),replace(即替换存在的键值对),set(上述二种的效用都负有),append(在设有的键对应的值后扩充对应的原委)以及prepend(在设有的键对应的值在此以前扩充对应的剧情)。

参考资料

  1. 《memcached周密剖析》
  2. 《nosql数据库入门》
  3. memcached协议

<key> 是数量项的键名。

<flags>是在收复内容时,与数量和出殡和埋葬块一同保存服务器上的任性十六个人无符号整形(用10进制来书写),一般为0。

<exptime>
是实惠时间。固然为0,该项永可是期,若是非0,该项将要<exptime>
后去除。

 <bytes>是<data
block>的长短,是数据项的长短。

<data block>是数码项的数码。

**add/replace/set/append/prepend命令回复**

“STORED\r\n”表明存款和储蓄成功。

“NOT_STORED\r\n”申明数据未有被储存,但不是因为发生错误。那经常意味着add
,
replace的尺码不满意或然项目早就位列删除队列(参考后文的“delete”命令)。

cas命令格式如下:

cas <key> <flags>
<exptime> <bytes> <cas
unique> [noreply]\r\n

<data block>\r\n

<key> ,<flags>,<exptime>, <bytes>以及<data
block>同add/replace/set/append/prepend命令

 <cas unique>
是三个与已存多少条约相关的全局唯1的陆拾陆个人数。客户端应该利用”gets”命令归来的该值来展开”cas”更新操作。

[noreply]是可选取提醒不要过来。注意:尽管请求行格式错误,服务器不自然能可相信地剖析”noreply”选项。在此种景况下,它也许会发送错误新闻给客户端,即便客户端从未读取该新闻的话会带来难题。客户端应该只构造合法的伸手。

cas命令回复如下:

 “EXIST\r\n”
提醒要翻新的数据自您上次取过后已透过修改。

 “NO_FOUND\r\n”
提醒要修改的数额并不设有。

 

delete格式命令如下:

delete <key>
<time>\r\n

delete是去除相应的键名。

<key> 是内需删除的键名。

<time>是二个单位为秒的年华,在该时间内服务器会拒相对此此键名的“add”和“replace”命令。此时内容被放入delete队列,无法再经过“get”获得该内容,也无从是用“add”和“replace”命令(可是“set”命令可用)。直到指按期间,这几个内容被最终从服务器的内部存储器中彻底清除。

delete命令回复如下:

 “DELETED\r\n”表示实践成功

“NOT_FOUND\r\n”表示尚无找到那项内容

 

读取命令

get/gets命令格式如下:

get/gets <key>*\r\n

<key>*指的是多个以空格分割的键名。

get/gets命令回复如下:

VALUE <key> <flags>
<bytes> [<cas unique>]\r\n

<data block>\r\n

<key>是数量项的键名

<flags>是由存款和储蓄命令设置的flags,一般为0

<bytes>是数据块的尺寸

<cas
unique>是三个616人整数,唯1标记了3个特定的数码项。

<data block>是数额项的多寡。

此处的具备数据以”END”截止。

 

**incr**/desc命令格式如下:

incr/desc <key> <value>
[noreply]\r\n

<key>是数额项的键名

<value>是对数据项incr(递增)/desc(递减)的值。它是三个616位的无符号10进制整数。

 [norply]是可选参数,不要过来。

**incr**/desc一声令下回复:

“NOT_FOUND\r\n” 提醒这一个数量项找不到。

 “<value>\r\n”,
当中<value>是以此数量项在通过递增/递减操作后的新值。

 

memcache文本和煦的伸手的解析

其一是在proto/memcache.c里的memcache_parse_req函数**


它也是用有限状态机去完成解析的

 1     enum {
 2         SW_START,
 3         SW_REQ_TYPE,
 4         SW_SPACES_BEFORE_KEY,
 5         SW_KEY,
 6         SW_SPACES_BEFORE_KEYS,
 7         SW_SPACES_BEFORE_FLAGS,
 8         SW_FLAGS,
 9         SW_SPACES_BEFORE_EXPIRY,
10         SW_EXPIRY,
11         SW_SPACES_BEFORE_VLEN,
12         SW_VLEN,
13         SW_SPACES_BEFORE_CAS,
14         SW_CAS,
15         SW_RUNTO_VAL,
16         SW_VAL,
17         SW_SPACES_BEFORE_NUM,
18         SW_NUM,
19         SW_RUNTO_CRLF,
20         SW_CRLF,
21         SW_NOREPLY,
22         SW_AFTER_NOREPLY,
23         SW_ALMOST_DONE,
24         SW_SENTINEL
25     } state;

 这里的蝇头状态机图如下:

图片 3

storage正是存款和储蓄命令,即add/replace/set/append/prepend/cas命令,retreval正是读取命令,即get\gets命令,other便是除了存款和储蓄命令,get\gets命令,touch命令,incr/desc命令之外的下令。

例如get\gets命令,先是SW_REQ_TYPE,就是get\gets字符串,再是SW_SPACES_BEFORE_KEY,即空格,然后使SW_KEY,正是键名,接着回到SW_SPACES_BEFORE_KEY,不断来回。

**memcache文本协商的回涨的分析**

以此是在proto/memcache.c里的memcache_parse_rsp函数**


它也是用单薄状态机去实现解析的,上面是那一个意况。

 1    enum {
 2         SW_START,
 3         SW_RSP_NUM,
 4         SW_RSP_STR,
 5         SW_SPACES_BEFORE_KEY,
 6         SW_KEY,
 7         SW_SPACES_BEFORE_FLAGS,     /* 5 */
 8         SW_FLAGS,
 9         SW_SPACES_BEFORE_VLEN,
10         SW_VLEN,
11         SW_RUNTO_VAL,
12         SW_VAL,                     /* 10 */
13         SW_VAL_LF,
14         SW_END,
15         SW_RUNTO_CRLF,
16         SW_CRLF,
17         SW_ALMOST_DONE,             /* 15 */
18         SW_SENTINEL
19     } state; 

此地的星星点点状态机图如下:

 图片 4

比如,倘若是get和gets的东山再起就能够先进入SW_RSP_STSportage,即“VALUE”,接着进入SW_SPACES_BEFOER_KEY那条线,知道那行的利落SW_RUNTO_C大切诺基LF,然后进入数据块SW_RUNTO_VAL这条线,知道SW_RSP_STR,直至到SW_RSP_STEnclave中分析出“END”,会到SW_CRLF这条线。

总结

正文重要介绍了memcache的文件协议以及tweproxy如何分析memcache请求包和memcache回复包。

相关文章

Leave a Reply

电子邮件地址不会被公开。 必填项已用*标注