Redis
Redis五種資料類型和消息訂閱
String指令
String是最常用的一種資料類型,普通的key/value存儲都可以歸為此類
1:set/get
設定key對應的值為String類型的value
擷取key對應的值
2:mget
批量擷取多個key的值,如果可以不存在則傳回nil
3:incr && incrby
incr對key對應的值進行加加操作,并傳回新的值;incrby加指定值
4:incr && incrby
incr對key對應的值進行加加操作,并傳回新的值;incrby加指定值
5:setnx
設定key對應的值為String類型的value,如果key已經存在則傳回0
6:setex
設定key對應的值為String類型的value,并設定有效期
其他指令
getrange 擷取key對應value的子字元串
mset 批量設定多個key的值,如果成功表示所有值都被設定,否則傳回0表示沒有任何值被設定 msetnx,同mset,不存在就設定,不會覆寫已有的key
getset 設定key的值,并傳回key舊的值 append:給指定key的value追加字元串,并傳回新字元串的長度
Hash的指令
hash是一個String類型的field和value之間的映射表 (雙層Hash)
redis的Hash資料類型的key(hash表名稱)對應的value實際的内部存儲結構為一個HashMap
Hash特别适合存儲對象
相對于把一個對象的每個屬性存儲為String類型,将整個對象存儲在Hash類型中會占用更少記憶體。
所存儲的成員較少時資料存儲為zipmap,當成員數量增大時會自動轉成真正的HashMap,此時encoding為ht
運用場景: 如用一個對象來存儲使用者資訊,商品資訊,訂單資訊等等。
hset:設定key對應的HashMap中的field的value
hget:擷取key對應的HashMap中的field的value
hgetall:擷取key對應的HashMap中的所有field的value
hlen:傳回key對應的HashMap中的field的數量
List的指令
lpush:在key對應的list的頭部添加一個元素
lrange:擷取key對應的list的指定下标範圍的元素,-1表示擷取所有元素
lpop:從key對應的list的尾部删除一個元素,并傳回該元素
rpush:在key對應的list的尾部添加一個元素
rpop:從key對應的list的尾部删除一個元素,并傳回該元素
Set的指令
sadd:在key對應的set中添加一個元素
smembers:擷取key對應的set的所有元素
spop:随機傳回并删除key對應的set中的一個元素
suion:求給定key對應的set并集
sinter:求給定key對應的set交集
SortSet的指令
set的基礎增加順序score,再根據score進行排序
zadd:在key對應的zset中添加一個元素
zrange:擷取key對應的zset中指定範圍的元素,-1表示擷取所有元素
zrem:删除key對應的zset中的一個元素
zrangebyscore:傳回有序集key中,指定分數範圍的元素清單,排行榜中運用
zrank:傳回key對應的zset中指定member的排名。其中member按score值遞增(從小到大); 排名以0為 底,也就是說,score值最小的成員排名為0,排行榜中運用
set是通過hashmap存儲,key對應set的元素,value是空對象 sortset是怎麼存儲并實作排序的呢,hashmap 存儲,還加了一層跳躍表 跳躍表:相當于雙向連結清單,在其基礎上添加前往比目前元素大的跳轉連結
Redis 是一個開源(BSD許可)的,記憶體中的資料結構存儲系統,它可以用作資料庫、緩存和消息中間 件。 它支援多 種類型的資料結構,如 字元串(strings)、散列(hashes)、 清單(lists)、 集合 (sets)、 有序集合(sorted sets)等。
Redis消息訂閱釋出
作用:釋出訂閱類似于資訊管道,用來進行系統之間消息解耦,類似于mq,rabbitmq、rocketmq、kafka、 activemq主要有消息釋出者和消息訂閱者。比如運用于:訂單支付成功,會員系統加積分、錢包進行扣錢操 作、發貨系統(下發商品)
PUBLISH:将資訊message發送到指定的頻道channel。傳回收到消息的用戶端數量
SUBSCRIBE: 訂閱給指定頻道的資訊
UNSUBSCRIBE: 取消訂閱指定的頻道,如果不指定,則取消訂閱所有的頻道。
Redis的消息訂閱釋出和mq對比? 答:redis釋出訂閱功能比較薄弱但比較輕量級,mq消息持久化,資料可靠 性比較差,無背景功能可msgId、msgKey進行查詢消息
Redis事務機制
MULTI 與 EXEC指令
以 MULTI 開始一個事務,然後将多個指令入隊到事務中, 最後由 EXEC 指令觸發事務, 一并執行事 務中的所有指令
DISCARD指令
DISCARD 指令用于取消一個事務, 它清空用戶端的整個事務隊列,然後将用戶端從事務狀态調整回 非事務狀态, 最後傳回字元串 OK 給用戶端, 說明事務已被取消
WATCH指令
WATCH 指令用于在事務開始之前監視任意數量的鍵: 當調用 EXEC 指令執行事務時, 如果任意一個
被監視的鍵已經被其他用戶端修改了, 那麼整個事務不再執行, 直接傳回失敗
redis事務與傳統關系型事務的比較
原子性(Atomicity)
單個 Redis 指令的執行是原子性的,但 Redis 沒有在事務上增加任何維持原子性的機制,是以 Redis 事務的執行并不是原子性的。如果一個事務隊列中的所有指令都被成功地執行,那麼稱這個事務執行成 功
一緻性(Consistency)
入隊錯誤
在指令入隊的過程中,如果用戶端向伺服器發送了錯誤的指令,比如指令的參數數量不對,等 等, 那麼伺服器将向用戶端傳回一個出錯資訊, 并且将用戶端的事務狀态設為 REDIS_DIRTY_EXEC 。
執行錯誤
如果指令在事務執行的過程中發生錯誤,比如說,對一個不同類型的 key 執行了錯誤的操作, 那麼 Redis 隻會将錯誤包含在事務的結果中, 這不會引起事務中斷或整個失敗,不會影響已執 行事務指令的結果,也不會影響後面要執行的事務指令, 是以它對事務的一緻性也沒有影響
隔離性(Isolation)
WATCH 指令用于在事務開始之前監視任意數量的鍵: 當調用 EXEC 指令執行事務時, 如果任
意一個被監視的鍵已經被其他用戶端修改了, 那麼整個事務不再執行, 直接傳回失敗
持久性(Durability)
因為事務不過是用隊列包裹起了一組 Redis 指令,并沒有提供任何額外的持久性功能,是以事 務的持久性由 Redis 所使用的持久化模式決定
持久化
RDB持久化是指在指定的時間間隔内将記憶體中的資料集快照寫入磁盤,實際操作過程是fork一個子程序,先将資料集寫入臨時檔案,寫入成功後,再替換之前的檔案,用二進制壓縮存儲。
AOF持久化以日志的形式記錄伺服器所處理的每一個寫、删除操作,查詢操作不會記錄,以文本的方式記錄,可以打開檔案看到詳細的操作記錄。
二者優缺點
RDB存在哪些優勢呢?
1). 一旦采用該方式,那麼你的整個Redis資料庫将隻包含一個檔案,這對于檔案備份而言是非常完美的。比如,你可能打算每個小時歸檔一次最近24小時的數 據,同時還要每天歸檔一次最近30天的資料。通過這樣的備份政策,一旦系統出現災難性故障,我們可以非常容易的進行恢複。
2). 對于災難恢複而言,RDB是非常不錯的選擇。因為我們可以非常輕松的将一個單獨的檔案壓縮後再轉移到其它存儲媒體上。
3). 性能最大化。對于Redis的服務程序而言,在開始持久化時,它唯一需要做的隻是fork出子程序,之後再由子程序完成這些持久化的工作,這樣就可以極大的避免服務程序執行IO操作了。
4). 相比于AOF機制,如果資料集很大,RDB的啟動效率會更高。
RDB又存在哪些劣勢呢?
1). 如果你想保證資料的高可用性,即最大限度的避免資料丢失,那麼RDB将不是一個很好的選擇。因為系統一旦在定時持久化之前出現當機現象,此前沒有來得及寫入磁盤的資料都将丢失。
2). 由于RDB是通過fork子程序來協助完成資料持久化工作的,是以,如果當資料集較大時,可能會導緻整個伺服器停止服務幾百毫秒,甚至是1秒鐘。
AOF的優勢有哪些呢?
1). 該機制可以帶來更高的資料安全性,即資料持久性。Redis中提供了3中同步政策,即每秒同步、每修改同步和不同步。事實上,每秒同步也是異步完成的,其 效率也是非常高的,所差的是一旦系統出現當機現象,那麼這一秒鐘之内修改的資料将會丢失。而每修改同步,我們可以将其視為同步持久化,即每次發生的資料變 化都會被立即記錄到磁盤中。可以預見,這種方式在效率上是最低的。至于無同步,無需多言,我想大家都能正确的了解它。
2). 由于該機制對日志檔案的寫入操作采用的是append模式,是以在寫入過程中即使出現當機現象,也不會破壞日志檔案中已經存在的内容。然而如果我們本次操 作隻是寫入了一半資料就出現了系統崩潰問題,不用擔心,在Redis下一次啟動之前,我們可以通過redis-check-aof工具來幫助我們解決資料 一緻性的問題。
3). 如果日志過大,Redis可以自動啟用rewrite機制。即Redis以append模式不斷的将修改資料寫入到老的磁盤檔案中,同時Redis還會創 建一個新的檔案用于記錄此期間有哪些修改指令被執行。是以在進行rewrite切換時可以更好的保證資料安全性。
4). AOF包含一個格式清晰、易于了解的日志檔案用于記錄所有的修改操作。事實上,我們也可以通過該檔案完成資料的重建。
AOF的劣勢有哪些呢?
1). 對于相同數量的資料集而言,AOF檔案通常要大于RDB檔案。RDB 在恢複大資料集時的速度比 AOF 的恢複速度要快。
2). 根據同步政策的不同,AOF在運作效率上往往會慢于RDB。總之,每秒同步政策的效率是比較高的,同步禁用政策的效率和RDB一樣高效。
二者選擇的标準,就是看系統是願意犧牲一些性能,換取更高的緩存一緻性(aof),還是願意寫操作頻繁的時候,不啟用備份來換取更高的性能,待手動運作save的時候,再做備份(rdb)。rdb這個就更有些 eventually consistent的意思了。
redisTemplate api
opsForValue 操作String,Key,Value,包含過期key,setBit位操作等 opsForSet 操作set
opsForHash 操作hash
opsForZset 操作SortSet
opsForList 操作list隊列
opsForHash 操作hash opsForZset 操作SortSet opsForList 操作list隊列
緩存雪崩
什麼是緩存雪崩?你有什麼解決方案來防止緩存雪崩?
如果緩存集中在一段時間内失效,發生大量的緩存穿透,所有的查詢都落在資料庫上,造成了緩存雪 崩。 由于原有緩存失效,新緩存未到期間所有原本應該通路緩存的請求都去查詢資料庫了,而對資料 庫CPU 和記憶體造成巨大壓力,嚴重的會造成資料庫當機
你有什麼解決方案來防止緩存雪崩?
1:加鎖排隊
key: whiltList value:1000w個uid 指定setNx whiltList value nullValue mutex互斥鎖解 決,Redis的SETNX去set一個mutex key, 當操作傳回成功時,再進行load db的操作并 回設緩存; 否則,就重試整個get緩存的方法
2:資料預熱
緩存預熱就是系統上線後,将相關的緩存資料直接加載到緩存系統。這樣就可以避免在 使用者請求的時候,先查詢資料庫,然後再将資料緩存的問題!使用者直接查詢事先被預熱的 緩存資料!可以通過緩存reload機制,預先去更新緩存,再即将發生大并發通路前手動觸 發加載緩存不同的key
3:雙層緩存政策
C1為原始緩存, C2為拷貝緩存, C1失效時, 可以通路C2, C1緩存失效時間設為短期, C2設定為長期
4: 定時更新緩存政策
失效性要求不高的緩存,容器啟動初始化加載,采用定時任務更新或移除緩存
設定不同的過期時間,讓緩存失效的時間點盡量均勻
緩存穿透
什麼是緩存穿透?你有什麼解決方案來防止緩存穿透?
緩存穿透是指使用者查詢資料,在資料庫沒有,自然在緩存中也不會有。這樣就導緻使用者查詢的時候, 在緩存中找不到對應key的value,每次都要去資料庫再查詢一遍,然後傳回空(相當于進行了兩次 無用 的查詢)。這樣請求就繞過緩存直接查資料庫
你有什麼解決方案來防止緩存穿透?
1:采用布隆過濾器BloomFilter
将所有可能存在的資料哈 希到一個足夠大的 bitmap 中,一個一定不存在的資料會被這個
bitmap 攔截掉,進而避免了對底層存儲系統的查詢壓力
2:緩存空值
如果一個查詢傳回的資料為空(不管是資料不 存在,還是系統故障)我們仍然把這個空結果進行 緩存,但它的過期時間會很短,最長不超過五分鐘。 通過這個直接設定的預設值存放到緩存, 這樣第二次到緩沖中擷取就有值了,而不會繼續通路資料庫
緩存的收益和成本
緩存帶來的回報 :
1:高速讀寫 緩存加速讀寫速度:CPU L1/L2/L3 Cache、Linux page Cache加速硬碟讀寫、浏覽器緩存、 Ehcache緩存資料庫結果
2:降低後端負載 後端伺服器通過前端緩存降低負載: 業務端使用Redis降低後端MySQL負載等 緩存帶來的代價 :
1:資料不一緻 緩存層和資料層有時間視窗不一緻,和更新政策有關
2:代碼維護成本 原本隻需要讀寫MySQL就能實作功能,但加入了緩存之後就要去維護緩存的資料,增加了代碼複雜度。 堆内緩存可能帶來記憶體溢出的風險影響使用者程序,如ehCache、loadingCache
堆内緩存和遠端伺服器緩存redis的選擇 :
堆内緩存一般性能更好,遠端緩存需要套接字傳輸
使用者級别緩存盡量采用遠端緩存
大資料量盡量采用遠端緩存,服務節點化原則
redis作為資料庫和作為記憶體緩存的兩種使用方法
redis作為資料庫的使用有什麼優缺點
優點 :沒有Scheme限制,資料結構的變更相對容易,一開始确定資料類型, 抗壓能力強,性能極 高,10萬/qps
缺點:沒有索引,沒有外鍵,缺少int/date等基本資料類型,多條件查詢需要通過集合内聯 (sinter,zinterstore) 和連接配接間接實作開發效率低,可維護性不佳
redis作為緩存的使用,搭配資料庫使用的兩種方案
jedis整合使用方案 set key,value ["11","22"] 第一層在緩存進行查詢,如果得到資料則直接傳回, 第二 層在資料庫進行查詢,并且重新整理緩存,友善下次查詢 ["33,"44"] 作為mybatis/hibernate二級緩存使用方案,一級緩存:sqlSession,程序緩存,單次連結有效
事務隔離機制
文法:set global transaction isolation level read uncommitted;
種類:read uncommitted、read committed、repeatable read、serializable