Redis的性能瓶頸多是網絡 優化方案:html
在Redis中String稱爲動態字符串(檢測SDS Simple Dynamic String),內部數據結構相似ArrayList,維護着一個字節數組,而且內部預分配了必定的空間,減小內存頻繁分配。java
struct SDS{
T capacity; //數組容量
T len; //實際長度
byte flages; //標誌位,低三位表示類型
byte[] content; //數組內容
}
複製代碼
capacity 和 len兩個屬性都是泛型,爲何不直接用int類型?由於Redis內部有不少優化方案,爲更合理的使用內存,不一樣長度的字符串採用不一樣的數據類型表示,且在建立字符串的時候 len 會和 capacity 同樣大,不產生冗餘的空間,因此String值能夠是字符串、數字(整數、浮點數) 或者 二進制。面試
set [key] [value] 給指定key設置值(set 可覆蓋老的值)
get [key] 獲取指定key 的值
del [key] 刪除指定key
exists [key] 判斷是否存在指定key
mset [key1] [value1] [key2] [value2] ...... 批量存鍵值對
mget [key1] [key2] ...... 批量取key
expire [key] [time] 給指定key 設置過時時間 單位秒
setex [key] [time] [value] 等價於 set + expire 命令組合
setnx [key] [value] 若是key不存在則set 建立,不然返回0
incr [key] 若是value爲整數 可用 incr命令每次自增1
incrby [key] [number] 使用incrby命令對整數值 進行增長 number
複製代碼
Redis中的List和Java的LinkedList很像,底層都是鏈表結構,插入和刪除操做很是快時間複雜度O(1)。當數據量較少時底層的結構爲一塊連續的累成,稱爲ziplist(壓縮列表),它講全部的元素緊挨一塊兒存儲,分配的是一塊連續的內存。當數據較多的時候回變成quicklist(快速與列表)。單純鏈表須要維護prev和next指針須要佔用較多內存。在redis3.2以後採用ziplist+鏈表的混合結構。簡稱爲quicklistredis
rpush [key] [value1] [value2] ...... 鏈表右側插入
rpop [key] 移除右側列表頭元素,並返回該元素
lpop [key] 移除左側列表頭元素,並返回該元素
llen [key] 返回該列表的元素個數
lrem [key] [count] [value] 刪除列表中與value相等的元素,count是刪除的個數。 count>0 表示從左側開始查找,刪除count個元素,count<0 表示從右側開始查找,刪除count個相同元素,count=0 表示刪除所有相同的元素
(PS: index 表明元素下標,index 能夠爲負數, index= 表示倒數第一個元素,同理 index=-2 表示倒數第二 個元素。)
lindex [key] [index] 獲取list指定下標的元素 (須要遍歷,時間複雜度爲O(n))
lrange [key] [start_index] [end_index] 獲取list 區間內的全部元素 (時間複雜度爲 O(n))
ltrim [key] [start_index] [end_index] 保留區間內的元素,其餘元素刪除(時間複雜度爲 O(n))
複製代碼
Redis中的Hash和Java中的HashMap很類似,採用數組+鏈表的結構,當發生hash碰撞時將元素追加到鏈表上。但Redis的Hash 只能是字符串 Hash和String均可以存儲用戶數據。可是Hash能夠對用戶信息的每一個字段單獨存儲;String存儲的是序列化以後的字符串。從修改角度考慮,使用hash存儲可針對某個字段進行修改,網絡帶寬。可是Hash的內存佔用要大於String算法
hset [key] [field] [value] 新建字段信息
hget [key] [field] 獲取字段信息
hdel [key] [field] 刪除字段
hlen [key] 保存的字段個數
hgetall [key] 獲取指定key 字典裏的全部字段和值 (字段信息過多,會致使慢查詢 慎用:親身經歷 曾經用過這個這個指令致使線上服務故障)
hmset [key] [field1] [value1] [field2] [value2] ...... 批量建立
hincr [key] [field] 對字段值自增
hincrby [key] [field] [number] 對字段值增長number
複製代碼
Redis中的Set和HashSet相似,內部的鍵值對是無序惟一的。它的內部實現至關於一個特殊的字典,字典中全部的vlaue都是一個值null.當集合最後一個元素被移除以後,數據結構自動刪除,內存被回收。數據庫
sadd [key] [value] 向指定key的set中添加元素
smembers [key] 獲取指定key 集合中的全部元素
sismember [key] [value] 判斷集合中是否存在某個value
scard [key] 獲取集合的長度
spop [key] 彈出一個元素
srem [key] [value] 刪除指定元素
複製代碼
Zset保證了內部value的惟一性,另外能夠給每一個value賦值score,表明這個value的權重。內部實現用的是一種叫作跳躍列表的數據結構。數組
zadd [key] [score] [value] 向指定key的集合中增長元素
zrange [key] [start_index] [end_index] 獲取下標範圍內的元素列表,按score 排序輸出
zrevrange [key] [start_index] [end_index] 獲取範圍內的元素列表 ,按score排序 逆序輸出
zcard [key] 獲取集合列表的元素個數
zrank [key] [value] 獲取元素再集合中的排名
zrangebyscore [key] [score1] [score2] 輸出score範圍內的元素列表
zrem [key] [value] 刪除元素
zscore [key] [value] 獲取元素的score
複製代碼
RDB持久化是把當前進程數據生成快照保存到硬盤的過程,觸發RDB持久化的過程分爲手動觸發(bgsave命令)緩存
save 900 1
save 300 10
save 60 10000
900秒以內,若是超過1個key被修改,則發起快照保存;
300秒內,若是超過10個key被修改,則發起快照保存;
1分鐘以內,若是1萬個key被修改,則發起快照保存;
複製代碼
優勢安全
AOF(append only file)持久化;以獨立日誌的方式記錄每次寫命令,重啓時再衝洗執行AOF命令文件達到回覆數據的目的。bash
appendfsync yes #默認不開啓
appendfsync always #每次有數據修改發生時都會寫入AOF文件。
appendfsync everysec #每秒鐘同步一次,該策略爲AOF的缺省策略。
複製代碼
能保存較實時的數據,存儲的數據文件較大,速度慢於RDB
maxmemory限制的是Redis實際使用的內存量,也就是used_memory統計項對應的內存,因爲內存碎片率的存在,實際消費的內存可能迴避maxmemory設置更大。
config set maxmemory 6GB
緩存雪崩是指一段時間內緩存集中失效的問題。全部的查詢都落到的數據庫上,對數據庫CPU和內存形成巨大壓力,嚴重的會形成數據庫宕機。 解決方案:
緩存穿透指緩存和數據庫中都沒有數據用戶要查詢的數據,每次都進行2次查詢。如有人惡意攻擊,對數據庫形成壓力可能會壓垮數據庫。 解決方案:
緩存擊透是指緩存中沒有可是數據庫中有的數據,因爲併發量大,同時讀取緩存沒有數據而致使同時去數據庫中取數據,形成數據庫壓力過大。 解決方案:
緩存降級指當訪問量忽然劇增,服務出現問題或者非核心業務影響到核心業務性能時,須要包裝服務仍是可用。系統可用根據一些關鍵數據進行降級,來保證核心業務的可用。例如redis中適當刪除非關鍵緩存數據。
付磊、張益軍《Redis開發與運維》
#TODO 針對Redis數據結構學習+針對分佈式和運維相關的瞭解