天天看點

十個正确使用 Redis 的技巧

redis 在目前的技術社群裡是非常熱門的。從來自 antirez 一個小小的個人項目到成為記憶體資料存儲行業的标準,redis已經走過了很長的一段路。随之而來的一系列最佳實踐,使得大多數人可以正确地使用 redis。下面我們将探索正确使用 redis 的10個技巧。

十個正确使用 Redis 的技巧

<a target="_blank"></a>

okay,以挑戰這個指令開始這篇文章,或許并不是一個好的方式,但其确實可能是最重要的一點。很多時候當我們關注一個redis執行個體的統計資料,我們會快速地輸入”keys *”指令,這樣key的資訊會很明顯地展示出來。平心而論,從程式化的角度出發往往傾向于寫出下面這樣的僞代碼:

<code>for key in 'keys *':</code>

<code>doallthethings()</code>

但是當你有1300萬個key時,執行速度将會變慢。因為keys指令的時間複雜度是o(n),其中n是要傳回的keys的個數,這樣這個指令的複雜度就取決于資料庫的大小了。并且在這個操作執行期間,其它任何指令在你的執行個體中都無法執行。

由于 redis 沒有非常詳細的日志,要想知道在 redis 執行個體内部都做了些什麼是非常困難的。幸運的是 redis 提供了一個下面這樣的指令統計工具:

<code>127.0.0.1:6379&gt; info commandstats</code>

<code># commandstats</code>

<code>cmdstat_get:calls=78,usec=608,usec_per_call=7.79</code>

<code>cmdstat_setex:calls=5,usec=71,usec_per_call=14.20</code>

<code>cmdstat_keys:calls=2,usec=42,usec_per_call=21.00</code>

<code>cmdstat_info:calls=10,usec=1931,usec_per_call=193.10</code>

通過這個工具可以檢視所有指令統計的快照,比如指令執行了多少次,執行指令所耗費的毫秒數(每個指令的總時間和平均時間)

隻需要簡單地執行 config resetstat 指令就可以重置,這樣你就可以得到一個全新的統計結果。

redis 之父 salvatore 就說過:“通過執行get/set指令來測試redis就像在雨天檢測法拉利的雨刷清潔鏡子的效果”。很多時候人們跑到我這裡,他們想知道為什麼自己的redis-benchmark統計的結果低于最優結果 。但我們必須要把各種不同的真實情況考慮進來,例如:

可能受到哪些用戶端運作環境的限制?

是同一個版本号嗎?

測試環境中的表現與應用将要運作的環境是否一緻?

redis-benchmark的測試結果提供了一個保證你的 redis-server 不會運作在非正常狀态下的基準點,但是你永遠不要把它作為一個真實的“壓力測試”。壓力測試需要反應出應用的運作方式,并且需要一個盡可能的和生産相似的環境。

以一種優雅的方式引入 hashes 吧。hashes 将會帶給你一種前所未有的體驗。之前我曾看到過許多類似于下面這樣的key結構:

<code>foo:first_name</code>

<code>foo:last_name</code>

<code>foo:address</code>

上面的例子中,foo 可能是一個使用者的使用者名,其中的每一項都是一個單獨的 key。這就增加了 犯錯的空間,和一些不必要的 key。使用 hash 代替吧,你會驚奇地發現竟然隻需要一個 key :

<code>127.0.0.1:6379&gt; hset foo first_name "joe"</code>

<code>(integer) 1</code>

<code>127.0.0.1:6379&gt; hset foo last_name "engel"</code>

<code>127.0.0.1:6379&gt; hset foo address "1 fanatical pl"</code>

<code>127.0.0.1:6379&gt; hgetall foo</code>

<code>1) "first_name"</code>

<code>2) "joe"</code>

<code>3) "last_name"</code>

<code>4) "engel"</code>

<code>5) "address"</code>

<code>6) "1 fanatical pl"</code>

<code>127.0.0.1:6379&gt; hget foo first_name</code>

<code>"joe"</code>

無論什麼時候,隻要有可能就利用key逾時的優勢。一個很好的例子就是儲存一些諸如臨時認證key之類的東西。當你去查找一個授權key時——以oauth為例——通常會得到一個逾時時間。這樣在設定key的時候,設成同樣的逾時時間,redis就會自動為你清除!而不再需要使用keys *來周遊所有的key了,怎麼樣很友善吧?

如果必須確定關鍵性的資料可以被放入到 redis 的執行個體中,我強烈建議将其放入 try/except 塊中。幾乎所有的redis用戶端采用的都是“發送即忘”政策,是以經常需要考慮一個 key 是否真正被放到 redis 資料庫中了。至于将 try/expect 放到 redis 指令中的複雜性并不是本文要講的,你隻需要知道這樣做可以確定重要的資料放到該放的地方就可以了。

當然是錯的。redis 是一個單線程程序,即使啟用了持久化最多也隻會消耗兩個核心。除非你計劃在一台主機上運作多個執行個體——希望隻會是在開發測試的環境下!——否則的話對于一個 redis 執行個體是不需要2個以上核心的。

到目前為止 redis sentinel 已經經過了很全面的測試,很多使用者已經将其應用到了生産環境中(包括 objectrocket )。如果你的應用重度依賴于 redis ,那就需要想出一個高可用方案來保證其不會掉線。當然,如果不想自己管理這些東西,objectrocket 提供了一個高可用平台,并提供7×24小時的技術支援,有意向的話可以考慮一下。

本文來自雲栖社群合作夥伴“linux中國”,原文釋出日期:2015-08-21