sync or async connect redis in golang
來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。# <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。 # <span style="font-family: Microsoft YaHei">同步模式</span>A -> BA <- BA請求,並擷取結果,經曆1個RTT,這裡稱之為同步模式。為了實現高QPS,需要M個AB來處理任務,這樣可以得到一個公式:M/RTT。 # <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 -> -> -> BA <- <- <- BA請求,不等待應答繼續請求,並擷取全部結果,經曆1個RTT,這裡稱之為非同步模式。為了實現高QPS,同樣可以得到一個公式:C,C表示發包頻率。 # <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)` `</pre></div>當你想在兩種模式下切換時,這些代碼都不用更改。 值得注意的是pipelining,同步模式的使用如下<div class="cnblogs_Highlighter"><pre class="brush:go;gutter:true;">conn.Send(A)conn.Send(B)conn.Flush()conn.Recive() // ret <-Aconn.Recive() // ret <-B</pre></div>而非同步模式是天然支援pipelining的,所以使用還是<div class="cnblogs_Highlighter"><pre class="brush:go;gutter:true;">conn.Do(A)conn.Do(B)</pre></div> 有時你會希望同時向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的網路RTT2. 應用程式裡的並發度3. Redis server的串連數上限4. 原生串連數上限5. 原生CPU核心數。 舉個關於RTT的例子:測試環境的網路RTT為1ms,應用程式經測試達到QPS要求後,M被確定到代碼中,然後上線到生產環境,而生產環境的RTT為10ms,那麼生產環境的QPS就會比預期要低10倍。或者在生產環境裡,由於目標Redis server發生故障而被切到了備機,此時備機和應用程式極有可能會跨機房,這也會帶來同樣的問題。 ## <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問題在非同步模式下並不存在。當然,在特定範圍內都可以被應用程式接受的話,同步和非同步模式選擇哪種都是適合的。 # <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)249 次點擊