目錄
各命令及底層實現
遠程 redis 服務上執行命令:
redis-cli -h host -p port -a password
字符串(String)
字符串數據類型的相關命令用於管理 redis 字符串值
SET key value |
設置指定 key 的值 |
GET key |
獲取指定 key 的值 |
GETRANGE kay start end |
返回 key 中字符串值的子字符 |
GETSET key value |
將給定 key 的值設爲 value ,並返回 key 的舊值(old value)。 |
哈希(Hash)
Redis hash 是一個string類型的field和value的映射表,hash特別適合用於存儲對象。
Redis 中每個 hash 可以存儲 232 - 1 鍵值對(40多億)。
HSET key field value |
將哈希表 key 中的字段 field 的值設爲 value 。 |
HGET key field |
獲取存儲在哈希表中指定字段的值。 |
HDELETE key field1[field2] |
刪除一個或多個哈希表字段 |
列表(List)
Redis列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)
一個列表最多可以包含 232 - 1 個元素 (4294967295, 每個列表超過40億個元素)。
LPUSH key value1[value2] |
將一個或多個值插入到列表頭部 |
LPUSHX key value |
將一個值插入到已存在的列表頭部 |
LPOP key |
移出並獲取列表的第一個元素 |
LLEN key |
獲取列表長度 |
集合(Set)
Redis 的 Set 是 String 類型的無序集合。集合成員是唯一的,這就意味着集合中不能出現重複的數據。
Redis 中集合是通過哈希表實現的,所以添加,刪除,查找的複雜度都是 O(1)。
集合中最大的成員數爲 232 - 1 (4294967295, 每個集合可存儲40多億個成員)。
SADD key member1 [member2] |
向集合添加一個或多個成員 |
SMEMBERS key |
返回集合中的所有成員 |
SISMEMBER key member |
判斷 member 元素是否是集合 key 的成員 |
SPOP key |
移除並返回集合中的一個隨機元素 |
有序集合
Redis 有序集合和集合一樣也是string類型元素的集合,且不允許重複的成員。
不同的是每個元素都會關聯一個double類型的分數。redis正是通過分數來爲集合中的成員進行從小到大的排序。
有序集合的成員是唯一的,但分數(score)卻可以重複。
集合是通過哈希表實現的,所以添加,刪除,查找的複雜度都是O(1)。 集合中最大的成員數爲 232 - 1 (4294967295, 每個集合可存儲40多億個成員)。
ZADD key score1 member1 [score2 member2] |
向有序集合添加一個或多個成員,或者更新已存在成員的分數
|
ZCARD key |
獲取有序集合的成員數 |
ZCOUNT key min max |
計算在有序集合中指定區間分數的成員數 |
發佈訂閱
Redis 發佈訂閱(pub/sub)是一種消息通信模式:發送者(pub)發送消息,訂閱者(sub)接收消息。
Redis 客戶端可以訂閱任意數量的頻道。
頻道Channel1,以及訂閱這三個頻道的客戶端—— client2 、 client5 和 client1 之間的關係:
當有新消息通過 PUBLISH 命令發送給頻道 channel1 時, 這個消息就會被髮送給訂閱它的三個客戶端:
SUBSCRIBE channel [channel ...] |
訂閱給定的一個或多個頻道的信息。 |
PSUBSCRIBE pattern [pattern ...] |
訂閱一個或多個符合給定模式的頻道。 |
UNSUBSCRIBE [channel [channel ...]] |
退訂給定的頻道。 |
PUNSUBSCRIBE [pattern [pattern ...]] |
退訂所有給定模式的頻道。 |
PUBLISH channel message |
將信息發送到指定的頻道。 |
PUBSUB subcommand [argument [argument ...]] |
查看訂閱與發佈系統狀態。 |
redis和memcache的區別
memcache是分佈式高速緩存系統。
共同點:都是內存數據庫
區別:
memcache:
- 可以利用多核優勢,單實例吞吐量極高,可以達到幾十萬QPS,適用於大數據量
- 只支持簡單的key/value數據結構,redis支持豐富的數據類型
- 無法進行持久化,數據不能備份,只能用於緩存,重啓後數據全部丟失
redis:
- 支持多種數據結構,如string、list、set、zset、dict等
- 單線程請求,所有命令串行執行,併發情況下不需要考慮數據一致性
- 支持持久化,可以是使用AOF及RDB數據持久化到磁盤,從而進行數據的備份或數據恢復等操作,防止數據的丟失。
- 支持通過Replication進行數據複製,通過master-slave機制,可以實現實時進行數據的同步複製,支持多級複製和增量複製。
- 支持pub/sub消息訂閱機制,可以用來進行消息訂閱與通知
- 支持簡單的事務,使用場景很少,還不成熟
穿透、緩存雪崩
穿透 |
描述: 指在redis中查詢一個一定不存在的數據時,需要從數據庫中查詢。查詢到數據不存在時則不寫入緩存,這將導致每次在redis中獲取不存在的數據時都會去數據庫中查詢,這將導致緩存穿透。 |
解決方法:
|
|
緩存雪崩 |
描述: Redis的緩存集中在一段時間內失效,發生大量的穿透,將所有的查詢落到數據庫中,造成了緩存雪崩。 |
解決方法: 1、緩存失效後,通過加鎖或隊列來控制數據庫寫緩存的線程數量。如一個key只允許一個線程查詢數據和寫緩存,其他線程等待。 2、可以通過緩存reload機制,預先去更新緩存,再即將發生大併發訪問前手動觸發加載緩存。 3、不同的key設置不同的過期失效時間,讓緩存失效時間點儘量均勻。 4、做好二級緩存或者雙緩存策略。A1爲原始緩存,A2爲拷貝緩存,A1失效時,可以訪問A2,A1緩存失效時間設置爲短期,A2設置爲長期。 |
使用redis實現分佈式鎖
分佈式鎖一般有三種實現方式:1. 數據庫樂觀鎖;2. 基於Redis的分佈式鎖;3. 基於ZooKeeper的分佈式鎖。
1、SETNX是set if not exist的縮寫,如果不存在就返回保存value並返回1,如果存在就返回0。將key設置值爲value,如果key不存在,這種情況下等同SET命令。 當key存在時,什麼也不做。
2、GETSET其實就是兩個指令GET和SET,首先會GET到當前key的值並返回,然後在設置當前Key爲要設置Value。
public class RedisLock { |
併發競爭問題
Redis的併發競爭問題,主要是發生在併發寫競爭。
- 可以使用獨佔鎖的方式,類似操作系統的mutex機制。
- 使用樂觀鎖的方式進行解決(成本較低,非阻塞,性能較高)。
watch stock get stock $stock $stock = $stock - 10 multi set stock $stock exec |
watch這裏表示監控該key值,後面的事務是有條件的執行,如果從watch的exec語句執行時,watch的key對應的value值被修改了,則事務不會執行。
WATCH key [key ...] |
監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那麼事務將被打斷。 |
UNWATCH |
取消 WATCH 命令對所有 key 的監視。 |
MULTI |
標記一個事務塊的開始。 |
EXEC |
執行所有事務塊內的命令。 |
DISCARD |
取消事務,放棄執行事務塊內的所有命令。 |
持久化的幾種方式、優缺點、怎麼實現
- RDB持久化:將Reids在內存中的數據庫記錄定時dump到磁盤上的RDB持久化。
配置:
通過配置文件來修改Redis服務器dump快照的頻率,在打開6379.conf文件之後,搜索save
save 900 1 #在900秒(15分鐘)之後,如果至少有1個key發生變化,則dump內存快照。 save 300 10 #在300秒(5分鐘)之後,如果至少有10個key發生變化,則dump內存快照。 save 60 10000 #在60秒(1分鐘)之後,如果至少有10000個key發生變化,則dump內存快照。 |
- AOF(append only file)持久化:原理是將Reids的操作日誌以追加的方式寫入文件。
配置:
在Redis的配置文件中存在三種同步方式,它們分別是:
appendfsync always #每次有數據修改發生時都會寫入AOF文件。 appendfsync everysec #每秒鐘同步一次,該策略爲AOF的缺省策略。 appendfsync no #從不同步。高效但是數據不會被持久化。 |
緩存失敗策略
穿透、緩存雪崩
redis集羣高可用原理
兩種方式:
- 主備方式
一臺主機、一臺或多臺備機,在正常情況下主機對外提供服務,並把數據同步到備機,當主機宕機後,備機立刻開始服務。
優點:對客戶端無影響
缺點:絕大數情況下備機沒有使用。一直空閒浪費。
- 主從方式
主從之間進行數據同步。 當Master宕機後,通過選舉算法(Paxos、Raft)從slave中選舉出新Master繼續對外提供服務,主機恢復後以slave的身份重新加入。
優點:另一個目的是進行讀寫分離,這是當單機讀寫壓力過高的一種通用型解決方案。 其主機的角色只提供寫操作或少量的讀,把多餘讀請求通過負載均衡算法分流到單個或多個slave服務器上。
缺點:主機宕機後,Slave雖然被選舉成新Master了,但對外提供的IP服務地址卻發生變化了,意味着會影響到客戶端。 解決這種情況需要一些額外的工作,在當主機地址發生變化後及時通知到客戶端,客戶端收到新地址後,使用新地址繼續發送新請求
數據同步方式:
1、異步
2、同步
redis緩存分片(分區)
分區是分割數據到多個Redis實例的處理過程,因此每個實例只保存key的一個子集。
優點 |
缺點 |
|
|
分區類型:
- 範圍分區
最簡單的分區方式是按範圍分區,映射一定範圍的對象到特定的Redis實例
比如,ID從0到10000的用戶會保存到實例R0,ID從10001到 20000的用戶會保存到R1,以此類推。
這種方式是可行的,並且在實際中使用,不足就是要有一個區間範圍到實例的映射表。這個表要被管理,同時還需要各 種對象的映射表,通常對Redis來說並非是好的方法。
- 哈希分區
用一個hash函數將key轉換爲一個數字,比如使用crc32 hash函數。對key foobar執行crc32(foobar)會輸出類似93024922的整數。
對這個整數取模,將其轉化爲0-3之間的數字,就可以將這個整數映射到4個Redis實例中的一個了。93024922 % 4 = 2,就是說key foobar應該被存到R2實例中。注意:取模操作是取除的餘數,通常在多種編程語言中用%操作符實現。
redis的數據淘汰策略
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(驅逐):禁止驅逐數據。