Redis之基本介紹

基本介紹html

  Redis是一種key-value存儲形式的非關係型數據庫,也是一個強大的內存型存儲系統,可是它比傳統的Memcached 更靈活,支持更多的數據類型,同時也能夠持久化。據官方數據表示Redis讀的速度是110000次/s,寫的速度是81000次/s 。並且Redis支持數據持久化,衆多數據結構存儲,master-slave模式數據備份等多種功能。java

支持的數據類型web

  先經過一張圖瞭解下Redis內部內存管理中是如何描述這些不一樣數據類型的:redis

  首先Redis內部使用一個redisObject對象來表示全部的key和value,redisObject最主要的信息如上圖所示:type表明一個value對象具體是何種數據類型,encoding是不一樣數據類型在redis內部的存儲方式,好比:type=string表明value存儲的是一個普通字符串,那麼對應的encoding能夠是raw或者是int,若是是int則表明實際redis內部是按數值型類存儲和表示這個字符串的,固然前提是這個字符串自己能夠用數值表示,好比:"123" "456"這樣的字符串。sql

    這裏須要特殊說明一下vm字段,只有打開了Redis的虛擬內存功能,此字段纔會真正的分配內存,該功能默認是關閉狀態的。經過上圖咱們能夠發現Redis使用redisObject來表示全部的key/value數據是比較浪費內存的,固然這些內存管理成本的付出主要也是爲了給Redis不一樣數據類型提供一個統一的管理接口,實際做者也提供了多種方法幫助咱們儘可能節省內存使用。數據庫

Stringapi

  String數據結構是簡單的key-value類型,value其實不只是String,也能夠是數字。緩存

  經常使用命令:get、set、incr、decr、mget等。ruby

  應用場景String是最經常使用的一種數據類型,普通的key/ value 存儲均可以歸爲此類,便可以徹底實現目前 Memcached 的功能,而且效率更高。還能夠享受Redis的定時持久化,操做日誌及 Replication等功能。除了提供與 Memcached 同樣的get、set、incr、decr 等操做外,Redis還提供了下面一些操做:數據結構

  • 獲取字符串長度
  • 往字符串append內容
  • 設置和獲取字符串的某一段內容
  • 設置及獲取字符串的某一位(bit)
  • 批量設置一系列字符串的內容

Hash

  在Memcached中,咱們常常將一些結構化的信息打包成hashmap,在客戶端序列化後存儲爲一個字符串的值,好比用戶的暱稱、年齡、性別、積分等,這時候在須要修改其中某一項時,一般須要將全部值取出反序列化後,修改某一項的值,再序列化存儲回去。這樣不只增大了開銷,也不適用於一些可能併發操做的場合(好比兩個併發的操做都須要修改積分)。而Redis的Hash結構可使你像在數據庫中Update一個屬性同樣只修改某一項屬性值。

經常使用命令:hget,hset,hgetall 等。

應用場景:

咱們簡單舉個實例來描述下Hash的應用場景,好比咱們要存儲一個用戶信息對象數據,包含如下信息:

用戶ID爲查找的key,存儲的value用戶對象包含姓名,年齡,生日等信息,若是用普通的key/value結構來存儲,主要有如下2種存儲方式:

 

  第一種方式將用戶ID做爲查找key,把其餘信息封裝成一個對象以序列化的方式存儲,這種方式的缺點是,增長了序列化/反序列化的開銷,而且在須要修改其中一項信息時,須要把整個對象取回,而且修改操做須要對併發進行保護,引入CAS等複雜問題。

第二種方法是這個用戶信息對象有多少成員就存成多少個key-value對兒,用用戶ID+對應屬性的名稱做爲惟一標識來取得對應屬性的值,雖然省去了序列化開銷和併發問題,可是用戶ID爲重複存儲,若是存在大量這樣的數據,內存浪費仍是很是可觀的。

那麼Redis提供的Hash很好的解決了這個問題,Redis的Hash實際是內部存儲的Value爲一個HashMap,並提供了直接存取這個Map成員的接口,以下圖:

 

  也就是說,Key仍然是用戶ID, value是一個Map,這個Map的key是成員的屬性名,value是屬性值,這樣對數據的修改和存取均可以直接經過其內部Map的Key(Redis裏稱內部Map的key爲field), 也就是經過 key(用戶ID) + field(屬性標籤) 就能夠操做對應屬性數據了,既不須要重複存儲數據,也不會帶來序列化和併發修改控制的問題。很好的解決了問題。

    這裏同時須要注意,Redis提供了接口(hgetall)能夠直接取到所有的屬性數據,可是若是內部Map的成員不少,那麼涉及到遍歷整個內部Map的操做,因爲Redis單線程模型的緣故,這個遍歷操做可能會比較耗時,而另其它客戶端的請求徹底不響應,這點須要格外注意。

List 

經常使用方法:

  Lists 就是鏈表,略有數據結構知識的人都應該能理解其結構。使用Lists結構,咱們能夠輕鬆地實現最新消息排行等功能。Lists的另外一個應用就是消息隊列,能夠利用Lists的PUSH操做,將任務存在Lists中,而後工做線程再用POP操做將任務取出進行執行。Redis還提供了操做Lists中某一段的api,你能夠直接查詢,刪除Lists中某一段的元素。

  Redis的list是每一個子元素都是String類型的雙向鏈表,能夠經過push和pop操做從列表的頭部或者尾部添加或者刪除元素,這樣List便可以做爲棧,也能夠做爲隊列。

 

Sets

Sets 就是一個集合,集合的概念就是一堆不重複值的組合。利用Redis提供的Sets數據結構,能夠存儲一些集合性的數據。

Set是集合,是String類型的無序集合,set是經過hashtable實現的,概念和數學中個的集合基本相似,能夠交集,並集,差集等等,set中的元素是沒有順序的。

經常使用方法:

Sorted Sets

 和Sets相比,Sorted Sets增長了一個權重參數score,使得集合中的元素可以按score進行有序排列,好比一個存儲全班同窗成績的Sorted Sets,其集合value能夠是同窗的學號,而score就能夠是其考試得分,這樣在數據插入集合的時候,就已經進行了自然的排序。能夠用Sorted Sets來作帶權重的隊列,好比普通消息的score爲1,重要消息的score爲2,而後工做線程能夠選擇按score的倒序來獲取工做任務。讓重要的任務優先執行。 

 經常使用方法:

java中jedis操做不一樣數據類型的經常使用命令

 

pub/sub

發佈訂閱,相似於消息隊列mq。能夠選擇對某個Key進行訂閱,一旦這個key發佈了一些消息,則全部訂閱了這個Key的對象就能夠收到這個消息。主要能夠用在實時消息系統上,例如聊天之類的。

Transactions

NoSQL不支持事務,可是經過提供了打包執行的功能,即這個包裏面的全部命令必需要一塊兒執行,此外還能夠鎖定某個Key,在打包執行命令時若是檢測到這個Key發生了變化,則直接回滾。

持久化方案

redis默認開啓的RDB持久化方式,可是若是開始了AOF方式,那麼在系統重啓時優先衝AOF文件中回覆數據

Redis只RDB持久化和AOF持久化

數據淘汰策略

  長期將Redis做爲緩存使用,不免會遇到內存空間存儲瓶頸,當Redis內存超出物理內存限制時,內存數據就會與磁盤產生頻繁交換,使Redis性能急劇降低。此時如何淘汰無用數據釋放空間,存儲新數據就變得尤其重要了。對此,Redis在生產環境中,採用配置參數maxmemory 的方式來限制內存大小。當實際存儲內存超出maxmemory 參數值時會執行配置的淘汰策略。Redis 肯定驅逐某個鍵值對後,會刪除這個數據,並將這個數據變動消息發佈到本地(AOF 持久化)和從機(主從鏈接)。可是咱們要注意redis的刪除策略和淘汰策略是有區別的。

  • volatile-lru:從設置過時時間的數據集(server.db[i].expires)中挑選出最近最少使用的數據淘汰。沒有設置過時時間的key不會被淘汰,這樣就能夠在增長內存空間的同時保證須要持久化的數據不會丟失。
  • volatile-ttl:除了淘汰機制採用LRU,策略基本上與volatile-lru類似,從設置過時時間的數據集(server.db[i].expires)中挑選將要過時的數據淘汰,ttl值越大越優先被淘汰。
  • volatile-random:從已設置過時時間的數據集(server.db[i].expires)中任意選擇數據淘汰。當內存達到限制沒法寫入非過時時間的數據集時,能夠經過該淘汰策略在主鍵空間中隨機移除某個key。
  • allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰,該策略要淘汰的key面向的是全體key集合,而非過時的key集合。
  • allkeys-random:從數據集(server.db[i].dict)中選擇任意數據淘汰。
  • no-enviction:禁止驅逐數據,也就是當內存不足以容納新入數據時,新寫入操做就會報錯,請求能夠繼續進行,線上任務也不能持續進行,採用no-enviction策略能夠保證數據不被丟失,這也是系統默認的一種淘汰策略。
  • allkeys-lfu 從數據集(server.db[i].dict)中挑選使用頻率最小的數據淘汰,該策略要淘汰的key面向的是全體key集合,而非過時的key集合。
  • volatile-lfu 從設置過時時間的數據集(server.db[i].expires)中挑選出使用頻率最小的數據淘汰。沒有設置過時時間的key不會被淘汰,這樣就能夠在增長內存空間的同時保證須要持久化的數據不會丟失

 

Redis內存淘汰策略,看這一篇就夠了!

Redis數據過時和淘汰策略詳解

Redis中LRU淘汰策略的深刻分析

Redis的緩存淘汰策略LRU與LFU

 

優缺點

 優勢:

  • 速度快,由於數據存在內存中,相似於HashMap,HashMap的優點就是查找和操做的時間複雜度都是O(1)
  • 支持豐富數據類型,支持string,list,set,sorted set,hash
  • 支持事務,操做都是原子性,所謂的原子性就是對數據的更改要麼所有執行,要麼所有不執行
  • 豐富的特性:可用於緩存,消息,按key設置過時時間,過時後將會自動刪除

 缺點:

redis和memcached的區別

  • memcached全部的值均是簡單的字符串,redis做爲其替代者,支持更爲豐富的數據類型
  • redis的速度比memcached快不少,由於redis經過hasfMap存對象,因此再存取時不須要序列化和反序列化。
  • Memecache把數據所有存在內存之中,斷電後會掛掉,數據不能超過內存大小。redis能夠持久化其數據
  • value的大小:redis最大能夠達到1GB,而memcache只有1MB
  • 使用底層模型不一樣:它們之間底層實現方式 以及與客戶端之間通訊的應用協議不同;
  • Redis 是單線程,多路複用方式提升處理效率。Memcached 是多線程的,經過CPU線程切換來提升處理效率。

使用注意點

  • Master寫內存快照,save命令調度rdbSave函數,會阻塞主線程的工做,當快照比較大時對性能影響是很是大的,會間斷性暫停服務,因此Master最好不要寫內存快照。Master AOF持久化,若是不重寫AOF文件,這個持久化方式對性能的影響是最小的,可是AOF文件會不斷增大,AOF文件過大會影響Master重啓的恢復速度。Master最好不要作任何持久化工做,包括內存快照和AOF日誌文件,特別是不要啓用內存快照作持久化,若是數據比較關鍵,某個Slave開啓AOF備份數據,策略爲每秒同步一次。
  • 若是數據比較重要,某個Slave開啓AOF備份數據,策略設置爲每秒同步一次
  • 爲了主從複製的速度和鏈接的穩定性,Master和Slave最好在同一個局域網內
  • 儘可能避免在壓力很大的主庫上增長從庫
  • 主從複製不要用圖狀結構,用單向鏈表結構更爲穩定,即:Master <- Slave1 <- Slave2 <- Slave3…
  • 這樣的結構方便解決單點故障問題,實現Slave對Master的替換。若是Master掛了,能夠馬上啓用Slave1作Master,其餘不變。

使用場景

String 

適用場景:適合最簡單的k-v存儲,相似於memcached的存儲結構,短信驗證碼,配置信息等,就用這種類型來存儲。

案例:1.微博數,粉絲數,

hash

適用場景:通常key爲ID或者惟一標示,value對應的就是詳情了。如商品詳情,我的信息詳情,新聞詳情等。

案例:1.存儲部分變動數據,如用戶信息等

List

適用場景:由於list是有序的,比較適合存儲一些有序且數據相對固定的數據。如省市區表、字典表等。由於list是有序的,適合根據寫入的時間來排序,如:最新的***,消息隊列等

案例:

  1.在Redis中咱們的最新微博ID使用了常駐緩存,這是一直更新的。可是咱們作了限制不能超過5000個ID,所以咱們的獲取ID函數會一直詢問Redis。只有在start/count參數超出了這個範圍的時候,才須要去訪問數據庫。咱們的系統不會像傳統方式那樣「刷新」緩存,Redis實例中的信息永遠是一致的。SQL數據庫(或是硬盤上的其餘類型數據庫)只是在用戶須要獲取「很遠」的數據時纔會被觸發,而主頁或第一個評論頁是不會麻煩到硬盤上的數據庫了。

取最新N個數據的操做:
記錄前N個最新登錄的用戶Id列表,超出的範圍能夠從數據庫中得到。
//把當前登陸人添加到鏈表裏
ret = r.lpush("login:last_login_times", uid)

//保持鏈表只有N位
ret = redis.ltrim("login:last_login_times", 0, N-1)

//得到前N個最新登錄的用戶Id列表
last_login_list = r.lrange("login:last_login_times", 0, N-1)

Sets

適用場景:能夠簡單的理解爲ID-List的模式,如微博中一我的有哪些好友,set最牛的地方在於,能夠對兩個set提供交集、並集、差集操做。例如:查找兩我的共同的好友等。

案例:

  1.在微博應用中,能夠將一個用戶全部的關注人存在一個集合中,將其全部粉絲存在一個集合。Redis還爲集合提供了求交集、並集、差集等操做,能夠很是方便的實現如共同關注、共同喜愛、二度好友等功能,對上面的全部集合操做,你還可使用不一樣的命令選擇將結果返回給客戶端仍是存集到一個新的集合中。

使用:

交集,並集,差集:(Set)
//book表存儲book名稱

set book:1:name    」The Ruby Programming Language」

set book:2:name     」Ruby on rail」

set book:3:name     」Programming Erlang」

//tag表使用集合來存儲數據,由於集合擅長求交集、並集

sadd tag:ruby 1

sadd tag:ruby 2

sadd tag:web 2

sadd tag:erlang 3

//即屬於ruby又屬於web的書?

 inter_list = redis.sinter("tag.web", "tag:ruby")

//即屬於ruby,但不屬於web的書?

 inter_list = redis.sdiff("tag.ruby", "tag:web")

//屬於ruby和屬於web的書的合集?

 inter_list = redis.sunion("tag.ruby", "tag:web")

獲取某段時間全部數據去重值,這個使用Redis的set數據結構最合適了,只須要不斷地將數據往set中扔就好了,set意爲集合,因此會自動排重。

 Sorts sets

適用場景:是set的加強版本,增長了一個score參數,自動會根據score的值進行排序。比較適合相似於top 10等不根據插入的時間來排序的數據。

案例:排行榜應用,取TOP N操做

使用:

//將登陸次數和用戶統一存儲在一個sorted set裏

zadd login:login_times 5 1

zadd login:login_times 1 2

zadd login:login_times 2 3

ZADD key score member

//當用戶登陸時,對該用戶的登陸次數自增1

ret = r.zincrby("login:login_times", 1, uid)

//那麼如何得到登陸次數最多的用戶呢,逆序排列取得排名前N的用戶

ret = r.zrevrange("login:login_times", 0, N-1)

ZREVRANGE key start stop [WITHSCORES]

Redis集羣

Redis三種主從模式的基本介紹

  • 主從複製
  • 哨兵模式
  • Redis-Cluster集羣

 

學習連接

redis經點應用場景

redis經典場景

redis經典適用場景

redis的安裝

redis的命令大全

redis持久化配置過程

redis在Java中的經常使用命令

Redis的Cluster集羣的搭建

相關文章
相關標籤/搜索