sync or async connect redis in golang

gistao · · 1147 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

# <span style="font-family: Microsoft YaHei">Head of head</span> 在golang的整个生态里,redis client lib全部都使用多连接或者连接池。这是让人难以理解的,所以我和xiaofei一起写了一个同时支持同步和异步的redis client lib:RedisGo-Async。 github地址:https://github.com/gistao/RedisGo-Async。 qq群:131958277。 &nbsp; # <span style="font-family: Microsoft YaHei">同步模式</span> A -&gt; B A &lt;- B A请求,并获取结果,经历1个RTT,这里称之为同步模式。 为了实现高QPS,需要M个AB来处理任务,这样可以得到一个公式:M/RTT。 &nbsp; # <span style="font-family: Microsoft YaHei">[](https://github.com/gistao/RedisGo-Async/wiki/async-or-sync-%EF%BC%88%E4%B8%AD%E6%96%87%EF%BC%89#%E5%BC%82%E6%AD%A5%E6%A8%A1%E5%BC%8F)异步模式</span> A -&gt; -&gt; -&gt; B A &lt;- &lt;- &lt;- B A请求,不等待应答继续请求,并获取全部结果,经历1个RTT,这里称之为异步模式。 为了实现高QPS,同样可以得到一个公式:C,C表示发包频率。 &nbsp; # <span style="font-family: Microsoft YaHei">[](https://github.com/gistao/RedisGo-Async/wiki/async-or-sync-%EF%BC%88%E4%B8%AD%E6%96%87%EF%BC%89#%E5%A4%8D%E6%9D%82%E5%BA%A6)复杂度</span> 异步模式一般使用回调,较同步方式复杂的多。但GoRedis-Async提供的两种模式的使用是一样的。 <div class="cnblogs_Highlighter"> <pre class="brush:go;gutter:true;">conn := pool.Get() ret, err := conn.Do() doSomething(ret)`&nbsp;`</pre> </div> 当你想在两种模式下切换时,这些代码都不用更改。 &nbsp; 值得注意的是pipelining,同步模式的使用如下 <div class="cnblogs_Highlighter"> <pre class="brush:go;gutter:true;">conn.Send(A) conn.Send(B) conn.Flush() conn.Recive() // ret &lt;-A conn.Recive() // ret &lt;-B</pre> </div> 而异步模式是天然支持pipelining的,所以使用还是 <div class="cnblogs_Highlighter"> <pre class="brush:go;gutter:true;">conn.Do(A) conn.Do(B)</pre> </div> &nbsp; 有时你会希望同时向Redis serverA,B,C请求,最后一次性来处理结果。同步模式的使用如下 <div class="cnblogs_Highlighter"> <pre class="brush:go;gutter:true;">connA.Send() connA.Flush() connB.Send() connB.Flush() connC.Send() connC.Flush() connA.Recive() connB.Recive() connC.Recive()</pre> </div> 异步模式使用如下 <div class="cnblogs_Highlighter"> <pre class="brush:go;gutter:true;">retA := connA.AsyncDo() retB := connB.AsyncDo() retC := connC.AsyncDo() retA.Get() retC.Get() retB.Get()</pre> </div> # <span style="font-family: Microsoft YaHei">[](https://github.com/gistao/RedisGo-Async/wiki/async-or-sync-%EF%BC%88%E4%B8%AD%E6%96%87%EF%BC%89#%E6%89%A9%E5%B1%95%E6%80%A7)扩展性</span> ## <span style="font-family: Microsoft YaHei">[](https://github.com/gistao/RedisGo-Async/wiki/async-or-sync-%EF%BC%88%E4%B8%AD%E6%96%87%EF%BC%89#%E5%90%8C%E6%AD%A5%E6%A8%A1%E5%BC%8Fmrtt)同步模式:M/RTT</span> 在GoRedis-Async里,M表示 <div class="cnblogs_Highlighter"> <pre class="brush:go;gutter:true;">Pool.MaxActive</pre> </div> 这个值是固定的,取决于当前测试环境: 1. 应用程序和Redis server的网络RTT 2. 应用程序里的并发度 3. Redis server的连接数上限 4. 本机的连接数上限 5. 本机的CPU核数。 &nbsp; 举个关于RTT的例子: 测试环境的网络RTT为1ms,应用程序经测试达到QPS要求后,M被确定到代码中,然后上线到生产环境,而生产环境的RTT为10ms,那么生产环境的QPS就会比预期要低10倍。或者在生产环境里,由于目标Redis server发生故障而被切到了备机,此时备机和应用程序极有可能会跨机房,这也会带来同样的问题。 &nbsp; ## <span style="font-family: Microsoft YaHei">[](https://github.com/gistao/RedisGo-Async/wiki/async-or-sync-%EF%BC%88%E4%B8%AD%E6%96%87%EF%BC%89#%E5%BC%82%E6%AD%A5%E6%A8%A1%E5%BC%8Fc)异步模式:C</span> 在GoRedis-Async里,C只和应用程序的routine数量有关,上边所述的RTT问题在异步模式下并不存在。 当然,在特定范围内都可以被应用程序接受的话,同步和异步模式选择哪种都是适合的。 &nbsp; # <span style="font-family: Microsoft YaHei">[](https://github.com/gistao/RedisGo-Async/wiki/async-or-sync-%EF%BC%88%E4%B8%AD%E6%96%87%EF%BC%89#mmmin-cost-max-payload)MM(Min cost Max payload)</span> 基础库好坏的一个重要衡量标准就是MM。 同步模式从理论上来说,相比较异步模式需要更多的线程和连接资源。下边是RedisGo-Async、[redigo](https://github.com/garyburd/redigo)、官方redisclient的对比[基准测试报告](https://github.com/gistao/RedisGo-Async/blob/master/bench/benchresult.txt)。Y轴是耗时ms,X轴为各对比库,测试数据为1千万条。 ![](https://github.com/gistao/RedisGo-Async/raw/master/bench/bench.png)

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1147 次点击  
加入收藏 微博
3 回复  |  直到 2017-08-17 02:21:19
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传