讀書筆記系列主要記錄本身看的書籍中的知識點,算是一個概括整理吧。Redis在咱們的平常開發中能夠說是很經常使用了,《Redis開發與運維》
這本書講解了Redis開發和運維的方方面面,很系統、全面,關鍵是實用。特來擼擼它,記錄一番。全書分爲14章,下面將記錄我的認爲每章中重要的知識點。redis
Redis是一種基於鍵值對(key-value)的NoSQL數據庫,Redis中的值能夠是由string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)、Bitmaps(位圖)、HyperLogLog、GEO(地理信息定位)等多種數據結構和算法構成,能夠知足不少的應用場景。由於Redis會將全部數據都放在內存裏,因此它的讀寫性能很是好。Redis還能夠將內存的數據利用快照和日誌的形式保存到硬盤上,這樣發生斷電或者機器故障,內存中的數據就不會丟失。固然Redis還提供了其餘不少附加功能。算法
(1)速度快數據庫
Redis的全部數據都是放在內存裏的,這是速度快的最主要緣由;
Redis是用C語言實現的,「距離」操做系統更近,執行速度相對會更快;
Redis採用單線程架構,預防了多線程可能產生的競爭問題;編程
(2)基於鍵值對的數據結構緩存
Redis中的值不只能夠是字符串,還能夠是具體的數據結構,方面在不一樣應用場景的開發。Redis主要提供五種數據結構:字符串、哈希、列表、集合、有序列表,而且在字符串的基礎上演變出來了位圖(Bitmaps)和HyperLogLog倆種「數據結構」。Redis3.2版本加入了GEO(地理信息定位)的功能。網絡
(3)豐富的功能session
除了5種數據結構,還有其餘額外的許多功能:數據結構
鍵過時功能,用來實現緩存;
發佈訂閱功能,用來實現消息系統;
Lua腳本功能,利用Lua腳本創造出新的Redis命令;
簡單的事務功能,在必定程度上保證事務特性;
流水線(Pipeline)功能,客戶端能將一批命令一次性傳到Redis,減小網絡開銷。多線程
(4)簡單穩定架構
代碼少,單線程,服務端、客戶端處理簡單,redis不依賴操做系統中的類庫,本身實現了事件處理的相關功能。
(5)客戶端語言多
redis提供了簡單的TCP通訊協議,不少編程語言能夠很方便的接入到redis。
(6)持久化
redis提供了兩種持久化方式:RDB和AOF。能夠用這兩種策略將內存的數據保存在硬盤中,保證了數據的可持久性。
(7)主從複製
redis提供了複製功能,實現了多個相同數據的redis副本,複製功能是分佈式redis的基礎。
(8)高可用和分佈式
redis提供了高可用實現Redis Sentinel(哨兵),可以保證redis節點的故障發現和故障自動轉移。而且3.0版本提供了分佈式實現Redis Cluster(集羣),
這是redis真正的分佈式實現,提供了高可用、讀寫和容量的擴展性。
緩存、排行榜系統、計數器應用(redis自然支持計數功能,且計數性能很好)、社交網絡(粉絲、共同喜愛、推送等,社交網站的訪問量比較大,傳統的關係型數據庫不太適合保存這種類型的數據,可用redis實現)、消息隊列系統(消息隊列具備業務解耦、非實時業務削峯等特性,redis能夠知足通常的消息隊列功能,不過通常項目中仍是使用專業的消息隊列,更增強大)。
redis也有不適合它解決的問題場景,站在數據規模和數據冷熱角度來分析的話:數據規模角度,數據可分爲大規模數據和小規模數據,redis的數據是放在內存裏的,若是數據規模很是大,不適合使用redis存儲;站在數據冷熱角度,數據分爲熱數據和冷數據,熱數據是指須要頻繁操做的數據,若是將冷數據放在redis中,浪費內存。
(1)查看全部鍵:keys *
(2)鍵總數:dbsize
注意:dbsize命令在計算總數時候不會遍歷全部鍵,而是直接獲取redis內部的鍵總數變量,時間複雜度O(1);而keys命令會遍歷全部鍵,時間複雜度O(n),若是redis保存了大量鍵時,線上環境禁止使用。
(3)檢查鍵是否存在(鍵存在返回1,不存在返回0):exists key
(4)刪除鍵(返回的結果是成功刪除的個數,刪除一個不存在的鍵,返回0):del key [key ...]
注意:del key表示刪除一個,del key1 key2 key3表示刪除3個
(5)鍵過時:expire key seconds
注意:redis支持對鍵添加過時時間,超過過時時間後,會自動刪除鍵;ttl key 命令會返回鍵的剩餘過時時間,返回值>=0表示鍵的剩餘過時時間,返回值-1表示鍵沒有設置過時時間,返回值-2表示鍵不存在。
(6)鍵的數據結構類型:type key
注意:若是鍵是字符串類型,返回string,若是鍵是列表類型,返回list,其餘幾種相似。若是鍵不存在,返回none。
每種數據結構都有本身底層的內部編碼實現,並且是多種實現,redis會在合適的場景選擇合適的內部編碼。好比zset包含skiplist和ziplist兩種內部編碼。這樣設計的好處是:能夠改進內部編碼,而對外的數據結構和命令沒有影響;多種內部編碼實現能夠在不一樣場景下發揮各自的優點,好比ziplist比較節省內存,可是在列表元素比較多的狀況下,性能會有所降低,這個時候redis會根據配置選項將列表類型的內部實現轉換爲linkedlist。
redis使用單線程架構和I/O多路複用模型來實現高性能的內存數據庫服務。一條命令從客戶端達到服務端不會馬上執行,全部命令都會進入到一個隊列中,而後逐個被執行。不會有兩條命令被同時執行。redis使用了I/O多路複用技術來解決I/O的問題。
redis使用單線程模式那麼快的緣由:純內存訪問,這個最重要;非阻塞I/O,redis使用epoll做爲I/O多路複用技術的實現,而且redis加上自身的事件處理模型將epoll中的鏈接、讀寫、關閉都轉換爲事件,不在網絡I/O上浪費過多的時間;單線程避免了線程切換和競爭產生的消耗。
注意:單線程會有一個問題,對於每一個命令的執行時間是有要求的,若是執行時間過長,會形成其餘命令的阻塞,對於redis來講是致命的,因此redis是面向快速執行場景的數據庫。
(1)設置值:set key value [ex seconds] [px milliseconds] [nx|xx]
注意:nx 鍵必須不存在,才能夠設置成功,用於添加; xx 鍵必須存在,才能夠設置成功,用於更新
(2)獲取值:get key
批量設置值:mset key value [key value ...]
批量獲取值:mget key [key ...]
注意:批量操做能夠減小網絡時間(n次網絡時間+n次命令時間 ---> 1次網絡時間+n次命令時間),可是每次批量操做所發送的命令不是無節制的,若是數量過多可能形成redis阻塞或者網絡阻塞。
(3)計數:incr key
incr命令用於對值作自增操做,若是值不是整數,返回錯誤;若是值是整數,返回自增後的結果;若是鍵不存在,按照值爲0自增,返回結果1。
不少存儲系統和編程語言內部使用CAS機制實現計數功能,會有必定的CPU開銷,但redis中不存在這個問題,由於redis單線程架構,任何命令到了redis服務端都要順序執行。
(4)內部編碼(redis會根據當前值的類型和長度決定使用哪一種內部編碼實現)
int(8個字節的長整形) embstr(小於等於39個字節的字符串) raw(大於39個字節的字符串)
(5)典型應用場景
緩存功能、計數、共享session、限速
(1)設置值
hset key field value
(2)獲取值
hget key field
(3)批量設置或獲取field-value
hmget key field [field ...]
hmset key field value [field value ...]
(4)內部編碼(ziplist、hashtable)
當哈希類型的field個數小於512,而且全部的value小於64字節,使用ziplist做爲哈希的內部實現,不然使用hashtable。512和64是默認的,能夠配置。
(5)應用場景
好比:用戶信息
列表是用來存儲多個有序的字符串,能夠對列表兩端插入和彈出。列表類型有兩個特色:(1)列表中的元素是有序的;(2)列表中的元素能夠是重複的。
(1)從右端插入、從左端插入
rpush key value [value ...] lpush key value [value ...]
lrange 0 -1 表示從左到右獲取列表的全部元素
(2)內部編碼(ziplist、linkedlist、quicklist)
當列表的元素個數小於512個,而且列表的每一個元素值都小於64字節,redis會選用ziplist來做爲列表的內部實現,不然選用linkedlist。Redis3.2版本提供了quicklist內部編碼,它是以一個ziplist爲節點的linkedlist,結合了ziplist和linkedlist二者的優點。
(3)使用場景
例如:消息隊列、文章列表
集合中不容許有重複元素,而且集合中的元素是無序的。
(1)添加元素
sadd key elements [elements ...]
(2)刪除元素
srem key elements [elements ...]
(3)內部編碼(intset、hashtable)
當集合中的元素都是整數且元素個數小於512(默認值,可配置),redis選用intset做爲集合內部實現,不然選用hashtable。
(4)使用場景
標籤、社交等,好比一個用戶對可樂、體育感興趣,另外一個用戶對歷史、新聞感興趣,這些興趣點就是標籤。
不能有重複成員,元素能夠排序,每一個元素設置一個分數(score)做爲排序的依據。有序集合的元素不能重複,可是分數能夠重複。
(1)添加成員
zadd key score member [score member ...]
(2)內部編碼(ziplist、skiplist)
當有序集合的元素個數小於128個,而且每一個元素的值都小於64字節,Redis使用ziplist做爲有序集合的內部實現。不然使用skiplist。
(3)使用場景
排行榜系統
(1)單個健管理
返回鍵類型、鍵重命名、鍵過時、遷移鍵等。
注意:遷移鍵有三種方式:move、dump+restore、migrate。move命令用於redis內部進行數據遷移,從一個數據庫遷移到另外一個數據庫,不建議生產環境使用redis多數據庫功能;dump+restore能夠實如今不一樣redis實例之間進行數據遷移,分爲dump和restore兩步,其中在源redis上dump會將鍵值序列化,採用RDB格式,在目標redis上,restore會將上面序列化的值復原;migrate命令用於redis實例之間進行數據遷移,實際上migrate是將dump、restore、del三個命令進行了整合。migrate命令的數據傳輸直接在源redis和目標redis上完成。
move命令做用於redis實例內部,是原子性的,不支持多個鍵;dump+restore做用於redis實例之間,不是原子性,不支持多個鍵;migrate做用於redis實例之間,是原子性的,支持多個鍵。
(2)遍歷鍵(keys和scan)
keys會全量遍歷全部鍵,可能形成redis阻塞。scan能夠想象成只掃描字典中的一部分鍵,直到將字典中的全部鍵遍歷完畢。scan能夠有效解決
keys命令可能產生的阻塞問題,可是scan的過程當中,若是有鍵的變化(增長、刪除、修改),就可能新鍵沒有遍歷到或者遍歷了重複的健。因此scan不能保證完整的遍歷出來全部的健。
(3)數據庫管理
select dbIndex 切換數據庫
flushdb/flushall 清除數據庫,flushdb只清除當前數據庫,flushall清除全部數據庫。