Redis從理論到實例

Redis,在好多項目場景中幫助我們。

老生常談,Redis與memcached的區別

1. Redis不僅僅支持簡單的k/v類型的數據,還提供List、Set、Hash、Sorted Set等數據結構的存儲。相比而言更具數據庫特徵。

3. 除了多種數據結構的支持,Redis還提供更多額外的特性,比如Subscribe/Publish,以支持發佈/訂閱這種事件通知機制等。

4. Redis支持數據的備份,即master-slave模式的數據備份。

5. Redis支持數據的持久化,並不是所有的數據都一直存儲在內存中的,通過snapshot快照或AOF增量LOG方式,可將內存中的數據保持在磁盤中,重啓的時候可以再次加載重新使用。

6. 過期策略 Memcached在set時指定,redis可通過expire指定 

7. Memcached可以緩存圖片、視頻等。

8. 從網絡IO模型上,Memcached是多線程非堵塞IO複用的網絡模型,分監聽主線程和Worker子線程。網絡層使用libevent封裝的事件庫。映入了緩存一致性(cache coherency)和鎖,帶來性能損耗;Redis使用單線程的IO複用模型,封裝了一個簡單的AeEvent事件處理框架。單純IO操作,單線程可將速度發揮到最大,但是一些簡單的操作如排序和聚合等,CPU計算過程中,整個IO調度被堵塞,影響吞吐量。

9. 從數據一致性上,Mmecached引入了CAS,保證了多個併發訪問同一份數據的一致性;Redis提供了事務功能,保證了一串命令的原子性。

10. 從內存管理上,Memcached使用預分配內存池的方式,使用slab和chunk管理內存。內存池可以省去申請、釋放內存的開銷,減小內存碎片的發生,但也帶來一定程度的空間浪費。並且在空間仍很大時,新的數據仍有可能被剔除。Redis使用現場申請內存的方式,很少使用free-list等方式優化內存分配,一定程度上存在內存碎片。Redis把帶過期時間的數據單獨放在一起,稱爲臨時數據。非臨時數據永遠不會剔出,即便內存不夠導致swap。

總之,Redis的更多場景是作爲Memcached的替代者來使用的,當需要除key/value以外的更多數據類型支持時,使用Redis更合適,當存儲的數據不能被剔除時,使用Redis更合適。

附參考: http://blog.csdn.net/tonysz126/article/details/8280696

Redis 安裝 + Sentinel配置主從

[root@bx_2_35 ~]# cd /opt/soft/
[root@bx_2_35 soft]# wget http://download.redis.io/releases/redis-2.8.13.tar.gz
[root@bx_2_35 soft]# tar -xzf redis-2.8.13.tar.gz
[root@bx_2_35 soft]# tar -xzf redis-2.8.13.tar.gz 
[root@bx_2_35 soft]# cd redis-2.8.13
[root@bx_2_35 redis-2.8.13]# make

短連接:
[root@bx_2_35 redis-2.8.13]# cd src
[root@bx_2_35 src]# cp -pf redis-server /usr/local/bin
[root@bx_2_35 src]# cp -pf redis-cli /usr/local/bin
[root@bx_2_35 src]# cp -pf redis-sentinel /usr/local/bin

[root@bx_2_35 src]# cd ..
[root@bx_2_35 redis-2.8.13]# vim redis.conf 


[root@bx_2_35 redis-2.8.13]# redis-server 


關閉XShell會話(或者指定配置文件 redis-server redis.conf 就不需要關閉會話了)
重新打開會話
[root@bx_2_35 ~]# redis-cli 


持久化相關的配置在 redis.conf中
快照的方式持久化到磁盤
自動持久化規則配置
save 900 1
save 300 10
save 60 10000
Append-only file 的方式持久化 
每次執行寫操作命令之後,都會將數據寫到server.aofbuf中。
# appendfsync always
appendfsync everysec
# appendfsync no



重啓 redis


關閉會話(或者指定配置文件就不需要關閉會話了)

設置主從 ( 2.35主, 5.23從)
[root@bx_2_35 ~]# pkill redis-server

[@bx_5_23 /]# cd /opt/soft/redis-2.8.13/
[@bx_5_23 redis-2.8.13]# vim redis.conf 

[root@bx_2_35 redis-2.8.13]# redis-server redis.conf 
[@bx_5_23 redis-2.8.13]# redis-server redis.conf




[root@bx_2_35 redis-2.8.13]# vim sentinel.conf 
sentinel monitor mymaster 10.16.2.35 6379 1
[root@bx_2_35 redis-2.8.13]# redis-sentinel sentinel.conf --sentinel &


Redis消息隊列

Redis除了可以當做Key-Value型的NoSql數據庫外,同時由於它支持List數據結構,完全可以實現輕量級的消息隊列服務。

個人在項目中使用的幾個簡單應用場景是: 

1. 將新增加的獎品不時lpush到獎品隊列中,用戶符合中獎規則,rpop出來該獎品。簡單的生產者消費者隊列。

2. 用戶播放歷史記錄。

生產者

播放影片,前端Http輪詢上報當前用戶(user)、影片(film)、播放時長(time)。放入生產者隊列。由於用戶量較多,分配了5個隊列。按照user hashcode除以5取餘,分配該記錄到指定的隊列中。按user哈希的好處是同一個用戶的不同記錄肯定會落到唯一特定的隊列中。若落入不同的隊列,可能兩個隊列處理不是按上傳的先後順序,先上傳的可能會把後上傳的覆蓋掉。

String key = "film-history-q-" + (user.hashCode() % 5);
Long beforeLen = redisUtils.lLen(key);
    if (beforeLen < 50000) {
      StringBuilder sb = new StringBuilder(user);
      sb.append("|").append(film).append("|").append(video).append("|").append(time);
      Long afterLen = redisUtils.lPush(key, sb.toString());
      if (afterLen > 0) {
        return true;
      }
    }

此處限制beforeLen < 50000是爲了防止生產者隊列無限增大。超過這個限定,我們認爲很可能消費者掛掉了。另外未考慮更高的伸縮性: 如果5個隊列也不夠用,業務要求嚴格的話要考慮一致性哈希了。

消費者

構建5個消費者Worker,分別 對5個隊列進行消費,調用上報播放記錄接口。期間我們可以做一些合併相同用戶同一影片播放記錄的策略,減少上報播放記錄接口次數。


最後推薦一篇關於Redis應用場景的不錯的文章 http://www.cnblogs.com/si812cn/p/4042992.html

以及Redis命令參考 http://redisdoc.com/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章