### Redis
#### Redis常見數據結構以及使用場景分析
##### String
> 常用命令:set,get,decr,incr,mget等
String數據結構是簡單的key-value類型,value其實不僅可以是String,也可以是數字。常規key-value緩存應用;常規計數:微博數,粉絲數等。
##### Hash
> 常用命令:hget,hset,hgetall等
hash是一個String類型的field和value的映射表,hash特別適合用于存儲對象,后續操作的時候。
##### List
> 常用命令:lpush,rpush,lpop,rpop,lrange
list 就是鏈表,Redis list 的應用場景非常多,也是Redis最重要的數據結構之一,比如微博的關注列表,粉絲列表,消息列表等功能都可以用Redis的 list 結構來實現。
Redis list 的實現為一個雙向鏈表,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷。
另外可以通過 lrange 命令,就是從某個元素開始讀取多少個元素,可以基于 list 實現分頁查詢,這個很棒的一個功能,基于 redis 實現簡單的高性能分頁,可以做類似微博那種下拉不斷分頁的東西(一頁一頁的往下走),性能高。
##### Set
> 常用命令: sadd,spop,smembers,sunion 等
set 對外提供的功能與list類似是一個列表的功能,特殊之處在于 set 是可以自動排重的。
當你需要存儲一個列表數據,又不希望出現重復數據時,set是一個很好的選擇,并且set提供了判斷某個成員是否在一個set集合內的重要接口,這個也是list所不能提供的。可以基于 set 輕易實現交集、并集、差集的操作。
比如:在微博應用中,可以將一個用戶所有的關注人存在一個集合中,將其所有粉絲存在一個集合。Redis可以非常方便的實現如共同關注、共同粉絲、共同喜好等功能。
##### ZSet
> 常用命令:zadd,zrange,zrem,zcard等
和set相比,sorted set增加了一個權重參數score,使得集合中的元素能夠按score進行有序排列。
#### 為什么要用redis或者為什么要用緩存
主要從“高性能”和“高并發”兩點來看待這個問題。
##### 高性能
假如用戶第一次訪問數據庫中的某些數據。這個過程會比較慢,因為是從硬盤上讀取的。將該用戶訪問的數據存在緩存中,這樣下一次再訪問這些數據的時候就可以直接從緩存中獲取了。操作緩存就是直接操作內存,所以速度相當快。如果數據庫中的對應數據改變的之后,同步改變緩存中相應的數據即可!
##### 高并發
直接操作緩存能夠承受的請求是遠遠大于直接訪問數據庫的,所以我們可以考慮把數據庫中的部分數據轉移到緩存中去,這樣用戶的一部分請求會直接到緩存這里而不用經過數據庫。
#### 緩存雪崩和緩存穿透問題解決方案
##### 緩存雪崩
簡介:緩存同一時間大面積的失效,所以后面的請求都會落在數據庫上,造成數據庫短時間內承受大量請求而崩掉。
解決辦法:
事前:盡量保證整個redis集群的高可用性,發現機器宕機盡快補上。選擇合適的內存淘汰策略。
事中:本地ehcache緩存+hystrix限流&降級,避免MySQL崩掉
事后:利用redis持久化機制保存的數據庫盡快恢復緩存
##### 緩存穿透
簡介:一般是黑客故意去請求緩存中不存在的數據,導致所有的請求都落到數據庫上,造成數據庫短時間內承受大量的請求而崩掉。
解決辦法:常見的則是采用布隆過濾器,將所有可能存在的數據哈希到一個足夠大的bitmap中,一個一定不存在的數據會被這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。
如果查詢返回的數據為空(不管是數據不存在,還是系統故障),我們仍把這個空結果進行緩存,但它的過期時間會很短,最長不超過5分鐘。