首頁>技術>

Redis 的基本概念及背景知識五種常用資料物件及應用場景資料物件的底層實現方式Redis 的使用Redis 持久化策略Redis 的事務機制分散式鎖的實現及改進策略Redis 的刪除策略Cluster 叢集模式快取穿透、快取雪崩、快取擊穿Redis 的基本概念及背景

首先我們要知道什麼是 NoSQL,什麼又是 Redis,為什麼需要用 Redis,Redis 有哪些使用場景?

什麼是非關係型資料庫

NoSQL = Not Only SQL,也就是非關係型資料庫,既然有了 SQL,為什麼還需要 NoSQL?這和時代背景有很大的關係,我們所處的時代可以劃分為 Web1.0 和 Web2.0 時代:

Web1.0,是基於瀏覽器,使用者透過瀏覽器獲取內容資訊。Web2.0,是基於 1.0,增加了使用者與系統的互動,使用者既是網路內容的獲取者,也是網路資料的製造者,例如:論壇、部落格、微博等相關社交型別的平臺。

我們當前身處 Web2.0 時代,面對很多問題:

[ ] High performance - 高併發讀寫,在 Web2.0 時代,需要依據使用者個性化需要高併發讀寫,關係型資料庫讀還可以,寫就很難做到了。例如論壇這樣的站點, 網站的使用者併發性非常高,往往達到每秒上萬次讀寫請求,對於傳統關係型資料庫來說,硬碟 I/O 是一個很大的瓶頸[ ] Huge Storage - 海量資料的高效率儲存和訪問,海量資料高效率儲存和訪問, 網站每天產生的資料量是巨大的,對於關係型資料庫來說,在一張包含海量資料的表中查詢,效率是非常低的,類似 FaceBook 這樣的社交網站、社群。[ ] High Scalability &High Availability - 高可拓展性和高可用性, 在基於 Web 的結構當中,資料庫是最難進行橫向擴充套件的,當一個應用系統的使用者量和訪問量與日俱增的時候,資料庫卻沒有辦法像 Web server 和 App Server 那樣簡單的透過新增更多的硬體和服務節點來擴充套件效能和負載能力。對於很多需要提供 24 小時不間斷服務的網站來說,對資料庫系統進行升級和擴充套件是非常痛苦的事情,往往需要停機維護和資料遷移。

這些問題主要是由於關係型資料庫要求的:事務一致性、讀寫實時性、和複雜 SQL 的查詢,這些都是導致關係型資料庫效能差的原因,而這些場景和嚴格的要求在很多場景下不必要了,例如社交網路。NoSQL 因為它的易擴充套件、大資料量高效能、靈活的資料模型和高可用在社群時代可以發揮很大的作用。

NoSQL 的分類

NoSQL 依據儲存的內容也分很多種,讓我們從這些類別裡來定位 Redis 吧!依據使用場景來劃分類別,按照上面我們提到的三種優點,看看哪種能發揮極致:

面向高效能併發讀寫的 key-value 資料庫:key-value 資料庫的主要特點是具有極高的併發讀寫效能,Redis,Tokyo Cabinet,Flare 就是這類的代表面向海量資料訪問的面向文件資料庫:這類資料庫的特點是,可以在海量的資料中快速的查詢資料,典型代表為 MongoDB 以及 CouchDB面向可擴充套件性的分散式資料庫:這類資料庫想解決的問題就是傳統資料庫存在可擴充套件性上的缺陷,這類資料庫可以適應資料量的增加以及資料結構的變化

也正是因為 Redis 極高的併發讀寫能力,所以被常用作快取。

Redis 的應用場景

Redis 有著廣泛的應用場景。典型應用是:內容快取,主要用於處理大量資料的高訪問負載,優點就是快速查詢

快取,快取現在幾乎是所有中大型網站都在用的必殺技,合理的利用快取不僅能夠提升網站訪問速度,還能大大降低資料庫的壓力。Redis 提供了鍵過期功能,也提供了靈活的鍵淘汰策略,所以,現在 Redis 用在快取的場合非常多。排行榜,很多網站都有排行榜應用的,如京東的月度銷量榜單、商品按時間的上新排行榜等。Redis 提供的有序集合資料類構能實現各種複雜的排行榜應用。計數器,什麼是計數器,如電商網站商品的瀏覽量、影片網站影片的播放數等。為了保證資料實時效,每次瀏覽都需+1,併發量高時如果每次都請求資料庫操作無疑是種挑戰和壓力。Redis 提供的 incr 命令來實現計數器功能,記憶體操作,效能非常好,非常適用於這些計數場景。分散式會話,叢集模式下,在應用不多的情況下一般使用容器自帶的 session 複製功能就能滿足,當應用增多相對複雜的系統中,一般都會搭建以 Redis 等記憶體資料庫為中心的 session 服務,session 不再由容器管理,而是由 session 服務及記憶體資料庫管理。分散式鎖,很多網際網路公司中都使用了分散式技術,分散式技術帶來的技術挑戰是對同一個資源的併發訪問,如全域性 ID、減庫存、秒殺等場景,併發量不大的場景可以使用資料庫的悲觀鎖、樂觀鎖來實現,但在併發量高的場合中,利用資料庫鎖來控制資源的併發訪問是不太理想的,大大影響了資料庫的效能。社交網路,點贊、踩、關注/被關注、共同好友等是社交網站的基本功能,社交網站的訪問量通常來說比較大,而且傳統的關係資料庫型別不適合儲存這種型別的資料,Redis 提供的雜湊、集合等資料結構能很方便的的實現這些功能。最新列表,Redis 列表結構,LPUSH 可以在列表頭部插入一個內容 ID 作為關鍵字,LTRIM 可用來限制列表的數量,這樣列表永遠為 N 個 ID,無需查詢最新的列表,直接根據 ID 去到對應的內容頁即可。訊息系統,訊息佇列是大型網站必用中介軟體,如 ActiveMQ、RabbitMQ、Kafka 等流行的訊息佇列中介軟體,主要用於業務解耦、流量削峰及非同步處理實時性低的業務。Redis 提供了釋出/訂閱及阻塞佇列功能,能實現一個簡單的訊息佇列系統。

這些場景都是當下大型電商網站和社交網站需要的。所以 Reids 火也不奇怪,其它的 NoSQL 資料庫的應用場景都比較窄,類似文件儲存和圖片儲存等,都在特定應用場景下使用

五種常用資料物件及應用場景

Redis 是高效能鍵值對資料庫,支援的鍵值資料型別:字串型別 、雜湊型別、列表型別 、集合型別、有序集合型別 , 這些型別的操作方式和結構需要詳細瞭解。

字串型別

字串的操作命令有很多,常用的操作命令有如下幾種,涉及到:設定及獲取值,獲取並修改值,自增值,自減值,追加字串等操作:

set key value:設定指定 key 的值。get key:獲取指定 key 的值。getset key value:將給定 key 的值設為 value ,並返回 key 的舊值(old value)。incr key:將 key 中儲存的數字值增一。incr key increment:將 key 所儲存的值加上給定的增量值(increment)decr key :將 key 中儲存的數字值減一。decr key decrement:key 所儲存的值減去給定的減量值(decrement) 。append key value:如果 key 已經存在並且是一個字串, APPEND 命令將指定的 value 追加到該 key 原來值(value)的末尾。del key:刪除該 key。

需要注意的是,操作狀態返回的 0 和 1 要和返回結果做區分,並且 set 操作其實是有則更新,無則新增。常用場景如下:

場景一:利用數值操作特性 Incr 指令為分散式資料庫主鍵自增,例如資料庫做分庫分表後仍然希望所有資料能保持主鍵單調遞增。場景二:利用 key 的生命週期做投票系統,在投票的場景中,我們經常會有一天可投幾次票這樣的限制,那麼這個就需要一個過期時間,例如每天最多可以投 5 張票,可以把使用者 id 作為 key,當 value 大於 5 時不允許繼續投,24 小時後 key 銷燬,重新設定。場景三:利用數值操作特性 Incr 指令重新整理熱點資料,例如分別設定微博大 V 的粉絲數、點贊數為 key,然後重新整理數量。

以上就是字串型別的介紹。String 的場景利用了 String 的Incr 指令、過期 Key 的特性

雜湊型別

Hash 是一個 String 型別的 Field 和 Value 的對映表,Hash 特別適合用於儲存物件。Redis 中每個 hash 可以儲存 2^32 - 1 個鍵值對(40 多億),常用操作如下

hset key field value:將雜湊表 key 中的欄位 field 的值設為 value 。hget key field:獲取儲存在雜湊表中指定欄位的值。hmset key field1 value1 field2 value2 ...:同時將多個 field-value (域-值)對設定到雜湊表 key 中。時間複雜度為 O(n)hmget key field1 field2...:獲取所有給定欄位的值。時間複雜度為 O(n)hgetall key:獲取在雜湊表中指定 key 的所有欄位和值 。時間複雜度為 O(n)hdel key field1 field2... :刪除一個或多個雜湊表字段。返回值為 0 則表示刪除的屬性不存在del key:刪除該 key,也就是刪除該雜湊。

還有一些自增及判斷的命令:

hincrby key field increment:為雜湊表 key 中的指定欄位的整數值加上增量 increment 。hlen key:獲取雜湊表中欄位的數量hvals key:同時將多個 field-value (域-值)對設定到雜湊表 key 中。時間複雜度為 O(n)hexists key field:檢視雜湊表 key 中,指定的欄位是否存在。時間複雜度為 O(n)

由於 Hash 的這些特性,常有如下的應用場景:

場景一:利用 hash 的物件儲存特性設定使用者的購物車,一個人的購物車可以看做一個物件,而商品可以當做 field,數量可以當做 value,然後對購物車進行各種操作。場景二 :利用 hash 作為商品秒殺計數物件完成商品秒殺系統,一個商品秒殺系統可以看作一個物件,而秒殺的商品可以當作 field,數量可以當作 value,設定 value 為該商品的餘量,然後使用 hincrby 來進行秒殺業務,降低數量。

和 String 型別相比,Hash 更適合資料的呈現,而不適合資料的更新,具體為什麼,可以在下一小節其底層結構上一窺究竟。Hash 的場景利用了 Hash 的結構特性儲存物件資訊

列表型別

List 的核心特點是順序性,其底層主要實現為一個雙向連結串列,為什麼說主要,因為本節提到的各種資料物件底層都有不止一種實現方式。簡單常用的一些相關相關命令:

lpush key value1 [value2]:將一個或多個值插入到列表頭部,從左側新增,最後新增的在最左邊lrange key start stop:獲取列表指定範圍內的元素, 假如共有 6 個元素,[0,-2]表示從列表頭到倒數第二個,[0,-1]和[0,5]效果一樣。rpush key value1 [value2]:將一個或多個值插入到列表尾部,從右側新增,最後新增的在最右邊lpop key:移出並獲取列表的第一個元素,彈出列表頭rpop key:移除列表的最後一個元素,返回值為移除的元素。llen key:獲取列表長度。lpushx key value:將一個值插入到已存在的列表頭部,僅佇列存在時有效。當佇列不存在時,不進行任何操作。rpushx key value:將一個值插入到已存在的列表尾部,僅佇列存在時有效。當佇列不存在時,不進行任何操作。

當然還有些相對複雜的命令:

lrem key count value:移除 count 個為 value 的元素,如果 count 大於 0,則從左向右數,如果 count 小於 0,從右向左數,如果 count 等於 0,刪除全部為 value 的元素。lset key index value:透過索引設定列表元素的值,列表頭的索引是 0.linsert key before|after pivot value:在列表的元素前或者後插入元素

列表有如下的一些應用場景:

場景一:利用 blpop 特性實現任務佇列,輪詢從任務佇列裡取資料【可以同時從多個佇列獲取】,如果取到資料就返回,如果沒有資料就等待設定時間持續獲取,直到資料過期場景二:利用 list 順序特性實現朋友圈點贊,因為點贊等資訊都是有順序性的,而且修改的效率高,適合使用 list 來操作,點贊用rpush,取消點贊用lrem場景三:利用 list 順序特性進行分散式日誌順序性展示,使用 list 順序性實現多路資料彙總展示,利用其棧的特性實現最新的訊息最先展示,即組合使用 rpush 和 rpop

在 List 的場景下,主要利用了 List 的順序性、佇列和棧的雙重特性

集合型別

Set 是 String 型別的無序集合集合成員是唯一的,這就意味著集合中不能出現重複的資料。集合中最大的成員數為 2^32 - 1 (40 多億個成員),常用操作如下:

sadd key member1 [member2]:向集合新增一個或多個成員srem key member1 [member2]:移除集合中一個或多個成員smembers key:返回集合中的所有成員sismember key member:判斷 member 元素是否是集合 key 的成員scard key:獲取集合的成員數srandmember key [count]:返回集合中一個或多個隨機數spop key:移除並返回集合中的一個隨機元素

set 集合之間的操作透過如下命令實現:

sdiff key1 [key2]:返回給定所有集合的差集,兩個集合的第一個不同數字。sdiffstore destination key1 [key2]:返回給定所有集合的差集並存儲在 destination 中sinter key1 [key2]:返回給定所有集合的交集sinterstore destination key1 [key2]:返回給定所有集合的交集並存儲在 destination 中sunion key1 [key2]:返回所有給定集合的並集sunionstore destination key1 [key2]:返回所有給定集合的並集儲存在 destination 集合中smove source destination member:將 member 元素從 source 集合移動到 destination 集合

set 的主要特性是不重複性,我們看基於這樣的特性,常用的有哪些場景呢?

場景一:利用 set 特性隨機獲取不重複資料實現簡單推薦系統,系統彙集好讀者的所有愛好標籤後,使用srandmember 指令實現隨機推送三個使用者喜歡的標籤資料場景二:利用 set 交併差實現推薦系統池,例如獲取中老年群體使用者中共同的愛好,可以用sinter來實現,獲取我在中國地質大學中的一度人脈、二度人脈等可以使用sunion來實現,獲取我喜歡但是我媽不喜歡的電視節目,可以用sdiff來實現。場景三:利用 set 不重複特徵獲取所有業務系統許可權,我們想要獲取所有使用者的所有許可權,取出其中補充五的業務系統許可權該怎麼做?我們可以設定使用者為一個 set 集合,他的許可權為 value,然後用sinter合併所有使用者就可以拿到所有不重複許可權場景四:利用 set 不重複特徵獲取 UV 和 IP 資料,UV 即網站被不同使用者訪問的次數,相同使用者切換 IP 地址,UV 不變,使用 set 儲存使用者 cookie 資訊,統計 UV 量。IP 即網站被不同 IP 的訪問次數,相同 IP 訪問,不同使用者訪問,IP 不變。使用 set 儲存 IP 資訊,統計 IP 量。場景五:利用 set 不重複特徵實現黑白名單,可以在黑名單中新增 IP 或裝置或使用者,透過不重複特性,設定唯一的黑名單

Set 的場景主要利用了 set 的不重複特性、隨機取值特性和並交差集的特性

有序集合型別

Zset 和集合一樣也是 string 型別元素的集合,且不允許重複的成員。不同的是每個元素都會關聯一個 double 型別的分數。Redis 正是透過分數來為集合中的成員進行從小到大的排序。有序集合的成員是唯一的,但分數(score)卻可以重複,常用操作如下:

zadd key score1 member1 [score2 member2]:向有序集合新增一個或多個成員,或者更新已存在成員的分數zscore key member:返回有序集中,成員的分數值zcard key:獲取有序集合的成員數zrem key member [member ...]:移除有序集合中的一個或多個成員zrange key start stop [withscores]:透過索引區間返回有序集合成指定區間內的成員,如果需要同時返回 scores ,帶上後邊那段,預設分數從低到高zrevrange key start stop [withscores]:返回索引區間集中指定區間內的成員,分數從高到底zrangebyscore key min max [withscores] [limit]:透過分數區間返回有序集合指定區間內的成員,預設分數從低到高zremrangebyrank key start stop:移除有序集合中給定的排名區間的所有成員zremrangebyscore key min max:移除有序集合中給定的分數區間的所有成員zincrby key increment member:有序集合中對指定成員的分數加上增量 incrementzcount key min max:計算在有序集合中指定區間分數的成員數

Zset 最經典的應用場景就是進行排行榜設定了。當然除此之外還有些帶權重的操作都類似:

場景一:利用 set 不重複排序特徵實現計數器組合排序排行榜功能,為所有參與排名的資源進行排序場景二:利用 set 不重複排序特徵實現基於時效性任務提醒,佇列中全部為 vip,按照會員時間長短排序,短時間到期後提醒下一個快到期的任務。場景三:利用 set 不重複排序特徵實現帶權重任務佇列,僅是任務佇列可以透過佇列,但是如果佇列中的任務有優先順序,則需要使用帶權重的

ZSet 的場景主要利用了 set 的不重複特性和分數排序特性

文章到這裡就結束了!

下節更新資料物件的底層實現方式!

總結

2020馬上就要過去了,小編這裡整理一些 Redis實戰300多頁的集錦文件;整理好的JAVA核心知識點整理200多頁的學習筆記;2020最新總結的Java面試題禮包!還有 微服務、SSM、 Redis、等技術真題資料,關注小編+轉發文章+私信【Redis】獲取上述資料~ 重要的事情說三遍,轉發+轉發+轉發,一定要記得轉發哦!!!

14
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • Python中文亂碼的2種解決方案