複習寶典之Redis

查看更多寶典,請點擊《金三銀四,你的專屬面試寶典》html

第八章:Redis

Redis是一個key-value的nosql數據庫.先存到內存中,會根據必定的策略持久化到磁盤,即便斷電也不會丟失數據。支持的數據類型比較多。java

主要用來作緩存數據庫的數據和web集羣時當作中央緩存存放seesion。mysql

守護進程:在linux或者unix操做系統中在系統引導的時候會開啓不少服務,這些服務就叫作守護進程。爲了增長靈活性,root能夠選擇系統開啓的模式,這些模式叫作運行級別,每一種運行級別以必定的方式配置系統。 守護進程是脫離於終端而且在後臺運行的進程。守護進程脫離於終端是爲了不進程在執行過程當中的信息在任何終端上顯示而且進程也不會被任何終端所產生的終端信息所打斷。linux

RDBMS web

  • 高度組織化結構化數據 面試

  • 結構化查詢語言(SQL) (SQL) redis

  • 數據和關係都存儲在單獨的表中。 spring

  • 數據操縱語言,數據定義語言 sql

  • 嚴格的一致性數據庫

  • 基礎事務

NoSQL 

  • 表明着不只僅是SQL

  • 沒有聲明性查詢語言

  • 沒有預約義的模式 -鍵 - 值對存儲,列存儲,文檔存儲,圖形數據庫

  • 最終一致性,而非ACID屬性

  • 非結構化和不可預知的數據

  • CAP定理 

  • 高性能,高可用性和可伸縮性

 

1)nosql數據庫分類

Redis和Memcache區別:

一、 Redis和Memcache都是將數據存放在內存中,都是內存數據庫。不過memcache還可用於緩存其餘東西,例如圖片、視頻等等。

二、Redis不只僅支持簡單的k/v類型的數據,同時還提供list,set,hash等數據結構的存儲。

三、虛擬內存--Redis當物理內存用完時,能夠將一些好久沒用到的value 交換到磁盤

 

nosql數據庫分類:

類型 部分表明 特色
列存儲 Hbase,Cassandra,Hypertable 顧名思義,是按列存儲數據的。最大的特色是方便存儲結構化和半結構化數據,方便作數據壓縮,對針對某一列或者某幾列的查詢有很是大的IO優點。
文檔存儲 MongoDB,CouchDB 文檔存儲通常用相似json的格式存儲,存儲的內容是文檔型的。這樣也就有有機會對某些字段創建索引,實現關係數據庫的某些功能。
key-value存儲 Tokyo Cabinet / Tyrant,Berkeley DB,MemcacheDB,Redis 能夠經過key快速查詢到其value。通常來講,存儲無論value的格式,照單全收。(Redis包含了其餘功能)
圖存儲 Neo4J,FlockDB 圖形關係的最佳存儲。使用傳統關係數據庫來解決的話性能低下,並且設計使用不方便。
對象存儲 db4o,Versant 經過相似面嚮對象語言的語法操做數據庫,經過對象的方式存取數據。
xml數據庫 Berkeley DB XML,BaseX 高效的存儲XML數據,並支持XML的內部查詢語法,好比XQuery,Xpath。

 

2)redis使用場景

緩存:

把常常須要查詢的、不多修改數據,放到讀速度很快的空間(內存),以便下次訪問減小時間。減輕壓力,減小訪問時間。

計數器:

redis中的計數器是原子性的內存操做。

能夠解決庫存溢出問題.進銷存系統庫存溢出。

session緩存服務器:

web集羣時做爲session緩存服務器

緩存隊列等

 

3)redis對象保存方式

Json字符串:

須要把對象轉換爲json字符串,當作字符串處理。直接使用set get來設置或者或。

優勢:設置和獲取比較簡單

缺點:沒有提供專門的方法,須要把把對象轉換爲json。(jsonlib)

字節:

須要作序列號,就是把對象序列化爲字節保存。

 

若是是擔憂JSON轉對象會消耗資源的狀況,這個問題須要考量幾個地方:

第一點:就是使用的JSON轉換lib是否就會存在性能問題。

第二點:就是數據的數據量級別,若是是存儲百萬級的大數據對象,建議採用存儲序列化對象方式。若是是少許的數據級對象,或者是數據對象字段很少,仍是建議採用JSON轉換成String方式。

畢竟redis對存儲字符類型這部分優化的很是好。具體採用的方式與方法,還要看你所使用的場景。

 

4)redis數據淘汰機制

在 redis 中,容許用戶設置最大使用內存大小 server.maxmemory,在內存限定的狀況下是頗有用的。譬如,在一臺 8G 機子上部署了 4 個 redis 服務點,每個服務點分配 1.5G 的內存大小,減小內存緊張的狀況,由此獲取更爲穩健的服務。

 

內存大小有限,須要保存有效的數據?

redis 內存數據集大小上升到必定大小的時候,就會施行數據淘汰策略。

redis 提供 6種數據淘汰策略:

volatile-lru:從已設置過時時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰

volatile-ttl:從已設置過時時間的數據集(server.db[i].expires)中挑選將要過時的數據淘汰

volatile-random:從已設置過時時間的數據集(server.db[i].expires)中任意選擇數據淘汰

allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰

allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰

no-enviction(驅逐):禁止驅逐數據

 

5)java操做redis方式

一、使用jedis java客戶端來訪問redis服務器,有點相似經過jdbc訪問mysql同樣。

二、固然若是是spring進行集成時,可使用spring data來訪問redis,spring data只是對jedis的二次封裝。jdbcTemplate jdbc關係同樣。

 

6)redis存儲的數據類型

1.String

要把一個String保存到redis中,用set(key,value),獲取值用get(key)。

2.Hash(通常用於保存對象)

要把一個Hash保存到redis中,遍歷Map<String,String>,逐個調用hset(key,hashKey,hashValue),獲取全部值有hgetAll(key)。

3.List

要把一個List保存到redis中,遍歷List<String>,逐個調用lpush(key,value),獲取值用lrange(key,start,end),start表明開始位置,end表明結束位置,若是爲-1則表明到未尾。

這裏lpush的意思是從左邊保存,也就是後來居上。

4.Set

要把一個Set保存到redis中,遍歷Set<String>,逐個調用sadd(key,value),獲取值用smembers(key)。

5.SortedSet

SortedSet的意思是他的每個元素是有順序的,順序根據其score來決定,若是socre同樣,則按value排序。保存到redis的方法是,對每個要保存的元素,調用zadd(key,score,value),獲取值用zrange(key,satrt,end),start表明開始位置,end表明結束位置,若是爲-1則表明到未尾。

 

7)redis的主從複製

相似mysql的master-slave模式同樣,redis的master-slave能夠提高系統的可用性,master節點寫入cache後,會自動同步到slave上。Master以寫爲主,Slave以讀爲主。

能夠實現:讀寫分離和容災恢復

缺點:延時,因爲全部的寫操做都是在Master上操做,而後同步更新到Slave上,因此從Master同步到Slave機器有必定的延遲,當系統很繁忙的時候,延遲問題會更加嚴重,Slave機器數量的增長也會使得這個問題更加嚴重。

 

配置過程:

主redis:192.168.10.1 6379 從redis:192.168.10.2 6380

一、將主從redis配置文件redis.conf中的aemonize no 改成 yes

二、修改從redis配置文件redis.conf中的port 6379 改成 6380,添加slaveof 192.168.10.1 6379

三、啓動主從服務

主redis:

[root@localhost redis-2.8.3]# src/redis-server /soft/redis-2.8.3-master/redis-2.8.3/redis.conf

從redis:

[root@localhost redis-2.8.3]# src/redis-server /soft/redis-2.8.3-slave/redis-2.8.3/redis.conf

四、測試數據同步

主redis:

[root@localhost redis-2.8.3]# src/redis-cli -p 6379 ​ 127.0.0.1:6379> set name abc ​ OK ​ 127.0.0.1:6379> get name ​ "abc" ​ 127.0.0.1:6379>

從redis:

[root@localhost redis-2.8.3]# src/redis-cli -p 6380 ​ 127.0.0.1:6380> get name ​ "abc" ​ 127.0.0.1:6380>

五、默認是讀寫分離的

在從redis:

[root@localhost redis-2.8.3]# src/redis-cli -p 6380 ​ 127.0.0.1:6380> set name 123 ​ (error) READONLY You can't write against a read only slave.

 

主從切換

一、中止主redis

[root@localhost redis-2.8.3]# src/redis-cli -n 6379 shutdown ​ [root@localhost redis-2.8.3]# src/redis-cli -p 6379 ​ Could not connect to Redis at 127.0.0.1:6379: Connection refused ​ not connected>

二、將從redis設成主redis ​ [root@localhost redis-2.8.3]# src/redis-cli -p 6380 slaveof NO ONE ​ OK

三、測試從redis是否切換從主redis

[root@localhost redis-2.8.3]# src/redis-cli -p 6380 ​ 127.0.0.1:6380> set name 123 ​ OK ​ 127.0.0.1:6380> get name ​ "123" ​ 127.0.0.1:6380>

四、原來的主redis恢復正常了,要從新切換回去

1)將如今的主redis的數據進行保存

[root@localhost redis-2.8.3]# src/redis-cli -p 6380 ​ 127.0.0.1:6380> get name ​ "abc" ​ 127.0.0.1:6380> set name 123 ​ OK ​ 127.0.0.1:6380> get name ​ "123" ​ 127.0.0.1:6380> save ​ OK ​ 127.0.0.1:6380> get name ​ "123" ​ 127.0.0.1:6380>

2)將如今的主redis根目錄下dump.rdb文件拷貝覆蓋到原來主redis的根目錄

3)啓動原來的主redis

[root@localhost redis-2.8.3]# src/redis-server /soft/redis-2.8.3-master/redis-2.8.3/redis.conf ​ 4)在如今的主redis中切換

[root@localhost redis-2.8.3]# src/redis-cli -p 6380 slaveof 192.168.10.1 6379 ​ OK

 

經常使用的設計方案:

一主二僕:一個Master,兩個Slave,Slave只能讀不能寫;當Slave與Master斷開後須要從新slave of鏈接纔可創建以前的主從關係;Master掛掉後,Master關係依然存在,Master重啓便可恢復。

薪火相傳:上一個Slave能夠是下一個Slave的Master,Slave一樣能夠接收其餘slaves的鏈接和同步請求,那麼該slave做爲了 鏈條中下一個slave的Master,如此能夠有效減輕Master的寫壓力。若是slave中途變動轉向,會清除以前的數據,從新創建最新的。

反客爲主: 當Master掛掉後,Slave可鍵入命令 slaveof no one使當前redis中止與其餘Master redis數據同步,轉成Master redis。

 

複製原理:

一、Slave啓動成功鏈接到master後會發送一個sync命令;

二、Master接到命令啓動後的存盤進程,同時收集全部接收到的用於修改數據集命令,在後臺進程執行完畢以後,master將傳送整個數據文件到slave,以完成一次徹底同步;

三、全量複製:而slave服務在數據庫文件數據後,將其存盤並加載到內存中;

四、增量複製:Master繼續將新的全部收集到的修改命令依次傳給slave,完成同步;

五、可是隻要是從新鏈接master,一次徹底同步(全量複製)將被自動執行。

 

哨兵模式:

反客爲主的自動版,可以後臺監控Master庫是否故障,若是故障了根據投票數自動將slave庫轉換爲主庫。一組sentinel能同時監控多個Master。

使用步驟:

一、在Master對應redis.conf同目錄下新建sentinel.conf文件,名字絕對不能錯;

二、配置哨兵,在sentinel.conf文件中填入內容:

     sentinel monitor 被監控數據庫名字(本身起名字) ip port 1

    說明:上面最後一個數字1,表示主機掛掉後slave投票看讓誰接替成爲主機,得票數多少後成爲主機。

三、啓動哨兵模式:

   命令鍵入:redis-sentinel  /myredis/sentinel.conf

  注:上述sentinel.conf路徑按各自實際狀況配置

8)redis序列化器

普通的鏈接使用沒有辦法把Java對象直接存入Redis,而須要咱們本身提供方案-對象序列化,而後存入redis,取回序列化內容後,轉換爲java對象。Spring模板中提供了封裝的方案,在它內部提供了RedisSerializer接口(org.springframework.data.redis.serializer.RedisSerializer)和一些實現類。也能夠自定義序列化器,實現RedisSerializer接口。經常使用的有:StringRedisSerializer,JdkSerializationRedisSerializer<T>,GenericToStringSerializer …

RedisTemplate默認的系列化類是JdkSerializationRedisSerializer,用JdkSerializationRedisSerializer序列化的話,被序列化的對象必須實現Serializable接口。在存儲內容時,除了屬性的內容外還存了其它內容在裏面,總長度長,且不容易閱讀。 咱們要求是存儲的數據能夠方便查看,也方便反系列化,方便讀取數據。

Jackson2JsonRedisSerializer和GenericJackson2JsonRedisSerializer,二者都能序列化成json,可是後者會在json中加入@class屬性,類的全路徑包名,方便反系列化。前者若是存放了List則在反系列化的時候若是沒指定TypeReference則會報錯:java.util.LinkedHashMap cannot be cast to 。

 

9)websocket

WebSocket 是 HTML5 開始提供的一種在單個 TCP 鏈接上進行全雙工通信的協議

WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,容許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和服務器只須要完成一次握手,二者之間就直接能夠建立持久性的鏈接,並進行雙向數據傳輸

在 WebSocket API 中,瀏覽器和服務器只須要作一個握手的動做,而後,瀏覽器和服務器之間就造成了一條快速通道。二者之間就直接能夠數據互相傳送。

如今,不少網站爲了實現推送技術,所用的技術都是 Ajax 輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,而後由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器須要不斷的向服務器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費不少的帶寬等資源。

WebSocket 協議本質上是一個基於 TCP 的協議

爲了創建一個 WebSocket 鏈接,客戶端瀏覽器首先要向服務器發起一個 HTTP 請求,這個請求和一般的 HTTP 請求不一樣,包含了一些附加頭信息,其中附加頭信息"Upgrade: WebSocket"代表這是一個申請協議升級的 HTTP 請求,服務器端解析這些附加的頭信息而後產生應答信息返回給客戶端,客戶端和服務器端的 WebSocket 鏈接就創建起來了,雙方就能夠經過這個鏈接通道自由的傳遞信息,而且這個鏈接會持續存在直到客戶端或者服務器端的某一方主動的關閉鏈接。

 

websocket事件觸發機制:

open:

一旦服務器響應了WebSocket鏈接請求,open事件觸發並創建一個鏈接。open事件對應的回調函數稱做onopen。

到open事件觸發時,協議握手已經完成,WebSocket已經準備好發送和接收數據。若是應用程序接收到一個open事件,那麼 能夠肯定WebSocket服務器成功地處理了鏈接請求,而且贊成與應用程序通訊。

message:

WebSocket消息包含來自服務器的數據。你也可能據說過組成WebSocket消息的WebSocket幀(Frame)。第3章將詳細討論消息和幀的概念。爲了理解消息使用API的方式,WebSocket API只輸出完整的消息,而不是WebSocket幀。message事件在接收到消息時觸發,對應於該事件的回調函數是onmessage。

除了文本,WebSocket消息還能夠處理二進制數據,這種數據做爲Blob消息或者ArrayBuffer消息處理。由於設置WebSocket消息二進制數據類型的應用程序會影響二進制消息,因此必須在讀取數據以前決定用於客戶端二進制輸入數據的類型。

error:

error事件在響應意外故障的時候觸發。與該事件對應的回調函數爲onerror。錯誤還會致使WebSocket鏈接關閉。若是你接收一個error事件,能夠預期很快就會觸發close事件。close事件中的代碼和緣由有時候能告訴你錯誤的根源。error事件處理程序是調用服務器重連邏輯以及處理來自WebSocket對象的異常的最佳場所。

close:

close事件在WebSocket鏈接關閉時觸發。對應於close事件的回調函數是onclose。一旦鏈接關閉,客戶端和服務器再也不能接收或者發送消息。

說明:WebSocket規範還定義了ping和pong幀,能夠用於持續鏈接(keep-alive)、心跳、網絡狀態檢測、延遲測量等,可是WebSocket API目前沒有輸出這些特性。儘管瀏覽器接受ping幀,可是不會觸發對應WebSocket上的ping事件。相反,瀏覽器將自動響應pong幀。然而,瀏覽器實例化的ping若是在一段時間內沒有獲得pong應答,可能會觸發鏈接的close事件。

當調用close()方法終止與服務器的鏈接時,也會觸發onclose事件處理程序;WebSocket close事件在鏈接關閉時觸發,這可能有多種緣由,好比鏈接失敗或者成功的WebSocket關閉握手。WebSocket對象特性readyState反映了鏈接的狀態(2爲正在關閉,3爲已關閉)。

close事件有3個有用的屬性(property),能夠用於錯誤處理和恢復:wasClean、code和error。wasClean屬性是一個布爾屬性,表示鏈接是否順利關閉。若是WebSocket的關閉是對來自服務器的一個close幀的響應,則該屬性爲true。若是鏈接是由於其餘緣由(例如,由於底層TCP鏈接關閉)關閉,則該屬性爲false。code和reason屬性表示服務器發送的關閉握手狀態。這些屬性和WebSocket.close()方法中的code和reason參數一致,咱們將在本章後面詳加介紹。

相關文章
相關標籤/搜索