2010年8月1日 星期日

膜拜Redis

Redis的介紹

數據庫主要類型有對像數據庫,關係數據庫,鍵值數據庫等等,對像數據庫太超前了,現階段不提也罷;關係數據庫就是平常說的MySQL,PostgreSQL這些熟的不能再熟的東西,至於鍵值數據庫則是本文要著重說的,其代表主要有MemcacheDB,Tokyo Cabinet等等。

Redis本質上也是一種鍵值數據庫的,但它在保持鍵值數據庫簡單快捷特點的同時,又吸收了部分關係數據庫的優點。 從而使它的位置處於關係數據庫和鍵值數據庫之間。 Redis不僅能保存Strings類型的數據,還能保存Lists類型(有序)和Sets類型(無序)的數據,而且還能完成排序(SORT)等高級功能,在實現INCR,SETNX等功能的時候,保證了其操作的原子性,除此以外,還支持主從復制等功能。

詳細描述參見官方手冊,同時,官方提供了一個名為Retwis的項目的源代碼,可以對照著官方介紹學習,注意其中關於Data Layout的描述,其他沒什麼。

項目實踐中,多以關係數據庫為主,不過合理的使用Redis這樣的鍵值數據庫,往往能揚長避短,比如說實現一個類似消息隊列的功能,對MySQL來說,除非使用Q4M,否則很難滿足高並發請求,不過對Redis來說,通過內建的Lists支持,消息隊列就是小菜一碟。

Redis的安裝

tar zxvf redis-version.tar.gz
cd redis-version
make

由於沒有make install,所以得把源代碼目錄裡的關鍵文件手動複製到適當的位置:

cp redis.conf /etc/
cp redis-benchmark redis-cli redis-server /usr/bin/

如果內存情況比較緊張的話,需要設定內核參數:

echo 1 > /proc/sys/vm/overcommit_memory

然後編輯redis.conf配置文件(/etc/redis.conf),按需求做出適當調整,比如:

daemonize yes
logfile /dev/null

如果要記錄日誌的話,最好先調整loglevel到一個合適的級別,然後設定logfile,如果不需要,則可以像上面這樣直接把日子丟棄到/dev/null裡,還有一點,缺省情況下,數據文件dump.rdb會被生成到當前目錄,可以通過dir參數設定合適的目錄。

此外,如果你決定把Redis用於產品環境,還要注意maxmemory選項,因為Redis在啟動時會把所有數據加載到內存中,所以設定maxmemory相對安全。

接下來直接啟動服務就可以了,只有配置文件一個參數:

redis-server /etc/redis.conf

確認運行了之後,可以用redis-benchmark命令測試看看,還可以通過redis-cli命令實際操作一下,比如:

redis-cli set foo bar
OK
redis-cli get foo
bar

在設置鍵對應的值的時候,按照協議的規定是要提供數據大小這個參數的,上面的redis-cli命令之所以沒有提供這個參數是因為redis-cli本身進行了封裝。

可以通過telnet來驗證一點:

telnet 127.0.0.1 6379
Trying 127.0.0.1...
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
set foo 3
bar
+OK
get foo
$3
bar
^]
telnet> quit
Connection closed.

更多命令介紹參考文檔介紹。

Redis源代碼裡附帶了多種客戶端的擴展,比如說php(client-libraries/php),這是一個純PHP的實現方案,也有二進製版本的實現(phpredis)。 其他語言即便沒有現成的擴展實現,也可以自己按照協議規範寫一個擴展,應該不是什麼難事。

Redis內存要求很高,如果你的數據量很大的話,可能會導致系統使用swap,這會使性能急劇下降。 此時更好的方法是通過consistent hashing把數據分佈到多個服務器上,文檔上給出了簡單的例子解釋:

For example imagine to have N Redis servers, server-0, server-1, ..., server-N. You want to store the key "foo", what's the right server where to put "foo" in order to distribute keys evenly among different servers? Just perform the crc = CRC32("foo"), then servernum = crc % N (the rest of the division for N). This will give a number between 0 and N-1 for every key. Connect to this server and store the key.

在線演示:
http://try.redis-db.com/

參考鏈接:

http://redis.io/

http://github.com/jdp/redisent/tree/master
http://github.com/owlient/phpredis
http://rediska.geometria-lab.net/javascript:void(0)

沒有留言:

wibiya widget