• twemproxyMemcache协议解析探索——剖析twemproxy代码正编补充


    memcache是一种和redis类似的高速缓存服务器,但是memcache只提供键值对这种简单的存储方式,相对于redis支持的存储方式多样化,memcache就比较简单了。memcache通过tcp或者udp连接来实现memcache客户端和服务端的交互。memcache的协议是自定的,也分为两种:一种是文本协议(这是我们今天讨论的重点),另一种是二进制协议(在我们今天讨论的范围),这里仅仅介绍用tcp连接以及文本协议通信的memcache协议。如有描述不当的地方请大家指出。

    memcache文本协议

    存储命令

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

    <command name> <key> <flags> <exptime> <bytes>

    <data block>

    格式的介绍如下:

    <command name>可以是add(即增加不存在的键值对),replace(即替换存在的键值对),set(上述两种的功能都具有),append(在存在的键对应的值后增加对应的内容)以及prepend(在存在的键对应的值之前增加对应的内容)。

    <key> 是数据项的键名。

    <flags>是在取回内容时,与数据和发送块一同保存服务器上的任意16位无符号整形(用十进制来书写),一般为0。

    <exptime> 是有效时间。如果为0,该项永不过期,如果非0,该项将在<exptime> 后删除。

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

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

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

    "STORED "表明存储成功。

    "NOT_STORED "表明数据没有被存储,但不是因为发生错误。这通常意味着add , replace的条件不满足或者项目已经位列删除队列(参考后文的“delete”命令)。

    cas命令格式如下:

    cas <key> <flags> <exptime> <bytes> <cas unique> [noreply]

    <data block>

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

     <cas unique> 是一个与已存数据条目相关的全局唯一的64位数。客户端应该使用"gets"命令返回的该值来进行"cas"更新操作。

    [noreply]是可选项指示不要回复。注意:如果请求行格式错误,服务器不一定能可靠地解析"noreply"选项。在此种情况下,它可能会发送错误信息给客户端,如果客户端没有读取该信息的话会带来问题。客户端应该只构造合法的请求。

    cas命令回复如下:

     "EXIST " 指示要更新的数据自你上次取过后已经过修改。

     "NO_FOUND " 指示要修改的数据并不存在。

    delete格式命令如下:

    delete <key> <time>

    delete是删除对应的键名。

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

    <time>是一个单位为秒的时间,在该时间内服务器会拒绝对于此键名的“add”和“replace”命令。此时内容被放入delete队列,无法再通过“get”得到该内容,也无法是用“add”和“replace”命令(但是“set”命令可用)。直到指定时间,这些内容被最终从服务器的内存中彻底清除。

    delete命令回复如下:

     "DELETED "表示执行成功

    "NOT_FOUND "表示没有找到这项内容

    读取命令

    get/gets命令格式如下:

    get/gets <key>*

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

    get/gets命令回复如下:

    VALUE <key> <flags> <bytes> [<cas unique>]

    <data block>

    <key>是数据项的键名

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

    <bytes>是数据块的长度

    <cas unique>是一个64位整数,唯一标识了一个特定的数据项。

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

    这里的所有数据以"END"结束。

    incr/desc命令格式如下:

    incr/desc <key> <value> [noreply]

    <key>是数据项的键名

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

     [norply]是可选参数,不要回复。

    incr/desc命令回复:

    "NOT_FOUND " 指示这个数据项找不到。

     "<value> ", 其中<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;

     这里的有限状态机图如下:

    storage就是存储命令,即add/replace/set/append/prepend/cas命令,retreval就是读取命令,即getgets命令,other就是除了存储命令,getgets命令,touch命令,incr/desc命令之外的命令。

    例如getgets命令,先是SW_REQ_TYPE,就是getgets字符串,再是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; 

    这里的有限状态机图如下:

     

    例如,如果是get和gets的回复就会先进入SW_RSP_STR,即“VALUE”,接着进入SW_SPACES_BEFOER_KEY这条线,知道这行的结束SW_RUNTO_CRLF,然后进入数据块SW_RUNTO_VAL这条线,知道SW_RSP_STR,直至到SW_RSP_STR中解析出“END”,会到SW_CRLF这条线。

    总结

    本文主要介绍了memcache的文本协议以及tweproxy如何解析memcache请求包和memcache回复包。

  • 相关阅读:
    android EditText 软键盘 一些总结
    Activity的4种加载模式最佳解答及Intent常用标识
    Android App监听软键盘按键的三种方式
    解决ScrollView下嵌套ListView、GridView显示不全的问题(冲突)
    Android使用WindowManager实现悬浮窗口
    android 设置软键盘默认为26位软键盘
    android:configChanges属性总结
    空腹吃香蕉对身体好吗?哪些水果不宜空腹吃
    冒泡排序,选择排序,二分法
    Android:内存优化的一些总结
  • 原文地址:https://www.cnblogs.com/onlyac/p/7142739.html
Copyright © 2020-2023  润新知