一、Redis基礎介紹 redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字元串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、a ...
一、Redis基礎介紹
redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字元串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在記憶體中。不同的是redis會周期性把更新的數據寫入磁碟或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。關於性能方面,redis也有一個不錯的表現:官方的bench-mark數據:測試完成了50個併發執行100000個請求;設置和獲取的值是一個256位元組字元串;Linux box是運行Linux 2.6結果:寫的速度是110000次/s,讀的速度是81000次/s 。
// 安裝步驟: $ wget http://redis.googlecode.com/files/redis-2.4.7.tar.gz $ tar zxvf redis-2.4.7.tar.gz $ cd redis-2.4.7 $ make
make命令執行完成後,會在當前目錄下生成本個可執行文件,分別是redis-server、redis-cli、redis-benchmark、redis-stat,它們的作用如下:
- redis-server:Redis伺服器的daemon啟動程式
- redis-cli:Redis命令行操作工具。當然,你也可以用telnet根據其純文本協議來操作
- redis-benchmark:Redis性能測試工具,測試Redis在你的系統及你的配置下的讀寫性能
- redis-stat:Redis狀態檢測工具,可以檢測Redis當前狀態參數及延遲狀況。
服務端啟動:
src/redis-server
客戶端連接:
src/redis-cli
例子:
redis> set name helloword! OK redis> get name "helloword!"
更多命令行使用可以藉助help。客戶端編碼方式:首先引入二方包。
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.2.1</version> </dependency>
API文檔示例:http://tool.oschina.net/apidocs/apidoc?api=jedis-2.1.0
Redis存儲中的key值不限長度,可以適用一些模糊查詢或匹配場景。
二、Redis列表改造
性能確實很高:現在海選列表頁是基於對Redis的強依賴,只讀redis不讀DB,如果redis沒有記錄或者掛了就直接返回空記錄頁面。在存儲的優化方面,是採取直接的VO存放在redis中,上層把海選商品的id放到redis的List中做分頁的索引,因為redis的列表是基於Linked list實現的,所以分頁索引時間複雜度為O(S+N),S為偏移量start,N為指定區間內元素的數量,但也很快的,現在海選列表的響應時間為30ms。
http://redis.readthedocs.org/en/latest/index.html這裡有各種redis的命令分析及複雜度。
Redis的數據結構及對應的操作很豐富。List的操作很不錯(這次主要是用了List),這次的列表分頁就是基於List的range介面實現的,可以取從start坐標到stop坐標之間range的值。在做海選列表的分頁時會遇到一個小問題,因為List不支持批量的set,所以只能一個一個的push進去,但這樣會導致id列表不斷的變化,雖然整個過程完成得很快,但如果數量達到1k或以上的時候這種變化還是會體現到前端頁面影響用戶,但redis提供了一種rename的機制,這樣我們在列表變化時可以先一個一個的push到一個tmp中,待push完成後再一次性的rename為正式key,這樣的馬上切換可以保證列表的變化不影響到前端用戶。
總結:redis的操作很豐富,但也有缺陷,不過我們只要將這些豐富的命令組合一下基本上就可以很好地補充這些缺陷點。對代碼的入侵。正因為redis有豐富的數據結構及操作,沒有像tair那樣可以用一個annotation就可以解決,所以,redis的介面會對工程的代碼有一定的影響,目前只能做到在VO層的隔離。
對redis的強依賴,通過任務保證數據的實時:這次的改造嘗試了另一種使用Cache的方式,就是實時的刷數據到redis(1分鐘一次)這樣做的好處是:
- 修改商品1分鐘生效,解決了運營修改商品後要待緩存失效了才生效,以前的方式,如果是詳情頁還可以馬上清緩存,但如果是按分頁進行緩存的話,不知道這個商品在第幾頁,很難清,這樣會造成列表頁與詳情頁不一致的情況
- 無論運營怎樣修改,都不會造成對前端用戶的影響,先前首頁出現過運營修改商品緩存失效後出現繁忙頁面的現象,但這次海選的優化可以避免這種現象但也有不好的地方:
- 1分鐘要批量讀一次DB,對DB也是有點壓力的
- 這種方式在凌晨沒人訪問的時候是一種浪費,不知有沒有些更綠色一點的同步機制?大家有什麼建議呢?
一些缺點:n 線上的監控要完善,如key的qps,value占的空間大小,最後有後臺操作線上的KV,這樣以後作為參考對一些請求次數很高的key進行優化(考慮放本地緩存等);。n 關於過期時間的操作比較不方便,ValueCommand中的multiSet介面沒有過期時間參數,而單獨set一個value時是有的,這點比較奇怪,而且其他的命令,在處理過期時間方面很多都要採用TedisManager來做。
跳錶演算法:這次在使用redis時學習了一個新的平衡數據結構---跳錶,實現快速的插入和查詢。
其原理和實現的複雜度比紅黑樹平衡樹之類的都要簡單。參考博客如下:
- http://kenby.iteye.com/blog/1187303
- http://www.cxphp.com/?p=241
- http://www.searchtb.com/2011/05/redis-storage.html
三、Redis命令
// Redis安裝 tar zxvf redis-2.8.9.tar.gz cd redis-2.8.9 #直接make 編譯 make #可使用root用戶執行`make install`,將可執行文件拷貝到/usr/local/bin目錄下。這樣就可以直接敲名字運行程式了。 make install 啟動
#加上`&`號使redis以後臺程式方式運行 ./redis-server & 檢測
#檢測後臺進程是否存在 ps -ef |grep redis #檢測6379埠是否在監聽 netstat -lntp | grep 6379 #使用`redis-cli`客戶端檢測連接是否正常 ./redis-cli 127.0.0.1:6379> keys * (empty list or set) 127.0.0.1:6379> set key "hello world" OK 127.0.0.1:6379> get key "hello world" 停止 #使用客戶端 redis-cli shutdown #因為Redis可以妥善處理SIGTERM信號,所以直接kill -9也是可以的 kill -9 PID
四、
五、