Skip to content

单命令Get原理流程图及文字说明

Lewis Chan edited this page Jan 18, 2017 · 2 revisions

这是我通过阅读cerberus源码得到的Get命令流程图,核心大概如此,根据命令的不同,稍有不同。熟悉了此图,我想大致就比较清楚了。

redis-cerberus单命令Get流程图

下面的文字为个人的总结,稍有哆嗦,可对照着代码看

  • cerberus启动,创建Acceptor,注册ro/rdhup,等待连接
  • 当redis-cli连接时,Acceptor收到连接,new一个client,给它注册ro/rdhup;
  • 开始更新slot map,创建一个或多个SlotsMapUpdater连接,注册rw/rdhup,连接成功后,socket可写;向节点发送cluster nodes命令,事件interest修改为ro;
  • 收到cluster nodes响应解析成RedisNode后关闭SlotsMapUpdater,并通知Proxy更新其map;更新期间连接满足条件的Server,如果只读slave则连接所有满足条件的slaves,并发送READONLY指令,收到OK后,insterest修改为ro;若读写master,则就连接masters.
  • select_slave_if_possible回调完成后,设置cluster为ok,slot map已更新等flags. 接着查看缓存中有没有重试命令,有则为这些命令找到相应的Servers,并设置选中的Servers为可写;没有_set_slot_map则返回
  • 当redis-cli发送一个get命令时,解析时生成SingleCommandGroup对象,计算槽位并压入**_parsed_groups**;解析完成后,如果_awaiting_groups为空则进行_process,即对**_parsed_groups的CommandGroup进行迭代:选择Server,比如Get命令就是OneSlotCommand选择一个Server,找到Server则将cmd压入*_commands中(找不到就压入proxy retry缓存),回到_process里把当前处理的CommandGroup加进_awaiting_groups里;迭代结束后把*_parsed_groups**清空,然后Client添加peers,将peers中的Server设置为rw/nohup;
  • Server事件到来,_commands有值,则由_push_to_buffer_set将_commands的element传给***_sent_commands***,并填充Server发送缓存; Server可写,由writev写出,写完后设置成ro/nohup;
  • Server读事件到来,收到响应,对响应进行迭代:将响应结果转移到Client的Buffer里,通知Client,将**_awaiting_group里每个CommandGroup的Buffer追加到发送缓存中,转移到_ready_groups**,清**_awaiting_group**; 如果Client缓存不为空则设置Client为rw/nohup;最后在_recv_from里清已经处理的***_send_commands***
  • Client变为可写,发送缓存由writev写出,对**_ready_group中的命令作metrics统计;完了清ready_group,清peers;如果_parsed_group**非空,继续_process处理

当Server断开时,调用close_conn,Server清buffer,发送缓存,将命令(包括已经解析的和已经发送的)放入重试缓存,且从Server池中清除断开的Server; 在after_event中发现Server已关闭,会进行slot map更新