twemproxy主干流程(4个主要模块概述)——剖析twemproxy代码正编

存储架构 2017-06-26 阅读原文

在twemproxy的发送和接收流程剖析中,我们已经完全弄清楚twemproxy如何将客户端以及服务端发来的包切分成msg,获得一个独立的msg后twemproxy应该如何处理?这是本文这次需要重点介绍的内容。

twemproxy的主干流程

图1 twemproxy的主干流程

如图1所示,twemproxy主要通过3个队列进行模块间的数据交互:客户端连接conn的发送队列conn->omsg_q,服务端连接s_conn的输入队列s_conn->imsg_q,服务端连接s_conn的发送队列s_conn->omsg_q以及conn->omsg_q里的msg的对应回复peer。

  • 客户层接收模块将所有需要回复的msg处理后分别写入到客户端conn连接的发送队列conn->omsg_q以及服务端连接s_conn的输入队列s_conn->imsg_q。
  • 服务层发送模块从服务端连接s_conn的输入队列s_conn->imsg_q取出,将其发送后写入服务端连接s_conn的发送队列s_conn->omsg_q。
  • 服务层接收模块将接到服务端的响应通过s_conn->omsg_q的提供顺序将回复的msg写入到conn->omsg_q里的msg的对应回复peer。
  • 客户层发送模块通过客户端连接conn的发送队列conn->omsg_q的顺序获得请求msg的对应的peer中的回复msg,然后发送个客户端。

由于twemproxy的队列里的元素是msg对象的指针,同样peer也是msg对象的指针,为此在twemproxy在接到请求直至发送回复的那段时间里没有进行内存拷贝,仅有在接收的时候申请内存。twemproxy通过这种精巧的设计使得内存零拷贝,同时配合空闲msg池的使用,大幅减少了系统申请和释放内存的次数,大幅提高了twemproxy性能,大幅减轻了twemproxycpu的压力。

twemproxy的客户层接收模块

图2 twemproxy的客户层接收

如图2,当客户层接收模块接收到客户端请求后:

  • twemproxy会从空闲msg池和系统内存中请求空的msg ,通过我们提到过的接收流程接收并解析客户端请求生成msg。
  • 解析后发现如果类型是mset,mget或者del的多key操作,根据key值进行分片操作将一个msg分成多个msg。
  • 将这些msg按顺序放入客户端连接conn的发送队列conn->omsg_q中(其中被分片的msg不放入服务端连接s_conn的输入队列s_conn->imsg_q中)。
  • 根据key值经过哈希建立对应的服务端连接,每个服务端在twemproxy中对应一个key值。
  • 在建立连接后,将msg插入服务端连接s_conn的输入队列s_conn->imsg_q中,并通知服务端层发送模块发送。

twemproxy的服务层发送模块

图3 twemproxy的服务层发送

如图3所示,当服务层接收模块接收到客户层接收模块的通知后:

  • t wemproxy从服务端连接s_conn的输入队列s_conn->imsg_q中取出msg。
  • 在相应的s_conn发送msg,从服务端连接s_conn的输入队列s_conn->imsg_q中删除。
  • 发送后,将发送过的msg插入到服务端连接s_conn的发送队列s_conn->omsg_q中。

twemproxy的服务层接收模块

图4 twemproxy的服务层接收

如图4所示,当服务层接收模块接收到服务端回复后:

  • twemproxy会从空闲msg池和系统内存中请求空的msg,通过我们提到过的接收流程接收并解析服务端回复生成msg。
  • 从服务端连接s_conn的发送队列s_conn->omsg_q中取出对应的客户端请求pmsg。
  • 查看客户端请求pmsg和客户端msg是否对应,msg可能需要被丢弃(因为在此时客户端连接断开,msg不能被发送),并将丢弃的msg放入空闲msg池中。
  • 将msg写入pmsg->peer中,然后从服务端连接s_conn的发送队列s_conn->omsg_q中删除pmsg。
  • 如果存在分片,那么在所有已经分片的msg收到请求回复后,将这些已经分片的msg并入被分片的msg中。
  • 将所有已经分片的msg置空,并将该消息通知给服务层接收模块。

twemproxy的客户层发送模块

图5 twemproxy的客户层发送

如图5所示,当客户层接收模块接收到服务层接收模块的通知后:

  • twemproxy从客户端连接conn的发送队列conn->omsg_q取出msg。
  • 将msg->peek中取出对应的回复pmsg并发送。
  • 从客户端连接conn的发送队列conn->omsg_q删除msg。
  • 将msg释放后放入空闲msg池。

总结

twemproxy通过客户端连接conn的发送队列conn->omsg_q,服务端连接s_conn的输入队列s_conn->imsg_q,服务端连接s_conn的发送队列s_conn->omsg_q以及conn->omsg_q里的msg的对应回复peer来完成twemproxy的代理服务,利用队列和peer指针特性实现了内存零拷贝。

NoSQL_博客园

责编内容by:NoSQL_博客园阅读原文】。感谢您的支持!

您可能感兴趣的

SSDB 和 Twemproxy集群和分布式 SSDB项目地址 SSDB 是一个 C/C++ 语言开发的高性能 ...
twemproxy发送流程探索——剖析twemproxy代码正编... 本文想要完成对twemproxy发送流程——msg_send的探索,对于twemproxy发送流程的数据结构已经在 《twemproxy接收流程探...
How We Scaled Our Cache and Got a Good Night’... Caching is arguably the most important and widely used technique in computer ...
通过Twemproxy提升PHP/Redis的性能 Twemproxy 可以说是最古老的 Redis 代理软件了,一般来说,引入代理后性能会比没有引入代理时低一些,毕竟代理会导致一些额外的性能损耗...
Twemproxy(Nutcracker)源码分析-connection的类别和创建... Twemproxy是比较优秀的轻量级的Redis和Memcached代理,是Twitter开源的,主要实现Redis和Memcached的集群化。(Redis3...