读书笔记之《Redis开发与运维》—— 一
前言
????讀書筆記系列主要記錄自己看的書籍中的知識點,算是一個歸納整理吧。Redis在我們的日常開發中可以說是很常用了,《Redis開發與運維》這本書講解了Redis開發和運維的方方面面,很系統、全面,關鍵是實用。特來擼擼它,記錄一番。全書分為14章,下面將記錄個人認為每章中重要的知識點。
一、Redis初識
????Redis是一種基于鍵值對(key-value)的NoSQL數據庫,Redis中的值可以是由string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)、Bitmaps(位圖)、HyperLogLog、GEO(地理信息定位)等多種數據結構和算法構成,可以滿足很多的應用場景。因為Redis會將所有數據都放在內存里,所以它的讀寫性能非常好。Redis還可以將內存的數據利用快照和日志的形式保存到硬盤上,這樣發生斷電或者機器故障,內存中的數據就不會丟失。當然Redis還提供了其他很多附加功能。
1、Redis特性
(1)速度快
Redis的所有數據都是放在內存里的,這是速度快的最主要原因;
Redis是用C語言實現的,“距離”操作系統更近,執行速度相對會更快;
Redis采用單線程架構,預防了多線程可能產生的競爭問題;
(2)基于鍵值對的數據結構
Redis中的值不僅可以是字符串,還可以是具體的數據結構,方面在不同應用場景的開發。Redis主要提供五種數據結構:字符串、哈希、列表、集合、有序列表,并且在字符串的基礎上演變出來了位圖(Bitmaps)和HyperLogLog倆種“數據結構”。Redis3.2版本加入了GEO(地理信息定位)的功能。
(3)豐富的功能
除了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真正的分布式實現,提供了高可用、讀寫和容量的擴展性。
2、Redis使用場景
緩存、排行榜系統、計數器應用(redis天然支持計數功能,且計數性能很好)、社交網絡(粉絲、共同喜好、推送等,社交網站的訪問量比較大,傳統的關系型數據庫不太適合保存這種類型的數據,可用redis實現)、消息隊列系統(消息隊列具有業務解耦、非實時業務削峰等特性,redis可以滿足一般的消息隊列功能,不過一般項目中還是使用專業的消息隊列,更加強大)。
redis也有不適合它解決的問題場景,站在數據規模和數據冷熱角度來分析的話:數據規模角度,數據可分為大規模數據和小規模數據,redis的數據是放在內存里的,如果數據規模非常大,不適合使用redis存儲;站在數據冷熱角度,數據分為熱數據和冷數據,熱數據是指需要頻繁操作的數據,如果將冷數據放在redis中,浪費內存。
二、API的理解和使用
1、全局命令
(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。
2、數據結構的內部編碼
每種數據結構都有自己底層的內部編碼實現,而且是多種實現,redis會在合適的場景選擇合適的內部編碼。比如zset包含skiplist和ziplist兩種內部編碼。這樣設計的好處是:可以改進內部編碼,而對外的數據結構和命令沒有影響;多種內部編碼實現可以在不同場景下發揮各自的優勢,比如ziplist比較節省內存,但是在列表元素比較多的情況下,性能會有所下降,這個時候redis會根據配置選項將列表類型的內部實現轉換為linkedlist。
3、單線程架構
redis使用單線程架構和I/O多路復用模型來實現高性能的內存數據庫服務。一條命令從客戶端達到服務端不會立刻執行,所有命令都會進入到一個隊列中,然后逐個被執行。不會有兩條命令被同時執行。redis使用了I/O多路復用技術來解決I/O的問題。
redis使用單線程模式那么快的原因:純內存訪問,這個最重要;非阻塞I/O,redis使用epoll作為I/O多路復用技術的實現,并且redis加上自身的事件處理模型將epoll中的連接、讀寫、關閉都轉換為事件,不在網絡I/O上浪費過多的時間;單線程避免了線程切換和競爭產生的消耗。
注意:單線程會有一個問題,對于每個命令的執行時間是有要求的,如果執行時間過長,會造成其他命令的阻塞,對于redis來說是致命的,所以redis是面向快速執行場景的數據庫。
4、字符串
(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、限速
5、哈希
(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)應用場景
比如:用戶信息
6、列表
列表是用來存儲多個有序的字符串,可以對列表兩端插入和彈出。列表類型有兩個特點:(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)使用場景
例如:消息隊列、文章列表
7、集合
集合中不允許有重復元素,并且集合中的元素是無序的。
(1)添加元素
sadd key elements [elements …]
(2)刪除元素
srem key elements [elements …]
(3)內部編碼(intset、hashtable)
當集合中的元素都是整數且元素個數小于512(默認值,可配置),redis選用intset作為集合內部實現,否則選用hashtable。
(4)使用場景
標簽、社交等,比如一個用戶對可樂、體育感興趣,另一個用戶對歷史、新聞感興趣,這些興趣點就是標簽。
8、有序集合
不能有重復成員,元素可以排序,每個元素設置一個分數(score)作為排序的依據。有序集合的元素不能重復,但是分數可以重復。
(1)添加成員
zadd key score member [score member …]
(2)內部編碼(ziplist、skiplist)
當有序集合的元素個數小于128個,并且每個元素的值都小于64字節,Redis使用ziplist作為有序集合的內部實現。否則使用skiplist。
(3)使用場景
排行榜系統
9、健管理
(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清除所有數據庫。
總結
以上是生活随笔為你收集整理的读书笔记之《Redis开发与运维》—— 一的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 内核理解
- 下一篇: 剑客决斗(NYOJ 110)