本文由葡萄城技術團隊編撰並首發node
轉載請註明出處:葡萄城官網,葡萄城爲開發者提供專業的開發工具、解決方案和服務,賦能開發者。git
引言
在Web應用發展的初期,那時關係型數據庫受到了較爲普遍的關注和應用,緣由是由於那時候Web站點基本上訪問和併發不高、交互也較少。而在後來,隨着訪問量的提高,使用關係型數據庫的Web站點多多少少都開始在性能上出現了一些瓶頸,而瓶頸的源頭通常是在磁盤的I/O上。而隨着互聯網技術的進一步發展,各類類型的應用層出不窮,這致使在當今雲計算、大數據盛行的時代,對性能有了更多的需求,主要體如今如下四個方面:github
- 低延遲的讀寫速度:應用快速地反應能極大地提高用戶的滿意度
- 支撐海量的數據和流量:對於搜索這樣大型應用而言,須要利用PB級別的數據和能應對百萬級的流量
- 大規模集羣的管理:系統管理員但願分佈式應用能更簡單的部署和管理
- 龐大運營成本的考量:IT部門但願在硬件成本、軟件成本和人力成本可以有大幅度地下降
爲了克服這一問題,NoSQL應運而生,它同時具有了高性能、可擴展性強、高可用等優勢,受到普遍開發人員和倉庫管理人員的青睞。數據庫
Redis是什麼
Redis是如今最受歡迎的NoSQL數據庫之一,Redis是一個使用ANSI C編寫的開源、包含多種數據結構、支持網絡、基於內存、可選持久性的鍵值對存儲數據庫,其具有以下特性:json
- 基於內存運行,性能高效
- 支持分佈式,理論上能夠無限擴展
- key-value存儲系統
- 開源的使用ANSI C語言編寫、遵照BSD協議、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API
相比於其餘數據庫類型,Redis具有的特色是:後端
- C/S通信模型
- 單進程單線程模型
- 豐富的數據類型
- 操做具備原子性
- 持久化
- 高併發讀寫
- 支持lua腳本
哪些大廠在使用Redis?數組
- github
- 微博
- Stack Overflow
- 阿里巴巴
- 百度
- 美團
- 搜狐
Redis的應用場景有哪些?緩存
Redis 的應用場景包括:緩存系統(「熱點」數據:高頻讀、低頻寫)、計數器、消息隊列系統、排行榜、社交網絡和實時系統。安全
Redis的數據類型及主要特性
Redis提供的數據類型主要分爲5種自有類型和一種自定義類型,這5種自有類型包括:String類型、哈希類型、列表類型、集合類型和順序集合類型。服務器
String類型:
它是一個二進制安全的字符串,意味着它不只可以存儲字符串、還能存儲圖片、視頻等多種類型, 最大長度支持512M。
對每種數據類型,Redis都提供了豐富的操做命令,如:
- GET/MGET
- SET/SETEX/MSET/MSETNX
- INCR/DECR
- GETSET
- DEL
哈希類型:
該類型是由field和關聯的value組成的map。其中,field和value都是字符串類型的。
Hash的操做命令以下:
- HGET/HMGET/HGETALL
- HSET/HMSET/HSETNX
- HEXISTS/HLEN
- HKEYS/HDEL
- HVALS
列表類型:
該類型是一個插入順序排序的字符串元素集合, 基於雙鏈表實現。
List的操做命令以下:
- LPUSH/LPUSHX/LPOP/RPUSH/RPUSHX/RPOP/LINSERT/LSET
- LINDEX/LRANGE
- LLEN/LTRIM
集合類型:
Set類型是一種無順序集合, 它和List類型最大的區別是:集合中的元素沒有順序, 且元素是惟一的。
Set類型的底層是經過哈希表實現的,其操做命令爲:
- SADD/SPOP/SMOVE/SCARD
- SINTER/SDIFF/SDIFFSTORE/SUNION
Set類型主要應用於:在某些場景,如社交場景中,經過交集、並集和差集運算,經過Set類型能夠很是方便地查找共同好友、共同關注和共同偏好等社交關係。
順序集合類型:
ZSet是一種有序集合類型,每一個元素都會關聯一個double類型的分數權值,經過這個權值來爲集合中的成員進行從小到大的排序。與Set類型同樣,其底層也是經過哈希表實現的。
ZSet命令:
- ZADD/ZPOP/ZMOVE/ZCARD/ZCOUNT
- ZINTER/ZDIFF/ZDIFFSTORE/ZUNION
Redis的數據結構
Redis的數據結構以下圖所示:
關於上表中的部分釋義:
- 壓縮列表是列表鍵和哈希鍵的底層實現之一。當一個列表鍵只包含少許列表項,而且每一個列表項要麼就是小整數,要麼就是長度比較短的字符串,Redis就會使用壓縮列表來作列表鍵的底層實現
- 整數集合是集合鍵的底層實現之一,當一個集合只包含整數值元素,而且這個集合的元素數量很少時,Redis就會使用整數集合做爲集合鍵的底層實現
以下是定義一個Struct數據結構的例子:
簡單動態字符串SDS (Simple Dynamic String)
基於C語言中傳統字符串的缺陷,Redis本身構建了一種名爲簡單動態字符串的抽象類型,簡稱SDS,其結構以下:
SDS幾乎貫穿了Redis的全部數據結構,應用十分普遍。
SDS的特色
和C字符串相比,SDS的特色以下:
1. 常數複雜度獲取字符串長度
Redis中利用SDS字符串的len屬性能夠直接獲取到所保存的字符串的長
度,直接將獲取字符串長度所需的複雜度從C字符串的O(N)下降到了O(1)。
2. 減小修改字符串時致使的內存從新分配次數
經過C字符串的特性,咱們知道對於一個包含了N個字符的C字符串來講,其底層實現老是N+1個字符長的數組(額外一個空字符結尾)
那麼若是這個時候須要對字符串進行修改,程序就須要提早對這個C字符串數組進行一次內存重分配(多是擴展或者釋放)
而內存重分配就意味着是一個耗時的操做。
Redis巧妙的使用了SDS避免了C字符串的缺陷。在SDS中,buf數組的長度不必定就是字符串的字符數量加一,buf數組裏面能夠包含未使用的字節,而這些未使用的字節由free屬性記錄。
與此同時,SDS採用了空間預分配的策略,避免C字符串每一次修改時都須要進行內存重分配的耗時操做,將內存重分配從原來的每修改N次就分配N次——>下降到了修改N次最多分配N次。
以下是Redis對SDS的簡單定義:
Redis特性1:事務
- 命令序列化,按順序執行
- 原子性
- 三階段: 開始事務 - 命令入隊 - 執行事務
- 命令:MULTI/EXEC/DISCARD
Redis特性2:發佈訂閱(Pub/Sub)
- Pub/sub是一種消息通信模式
- Pub發送消息, Sub接受消息
- Redis客戶端能夠訂閱任意數量的頻道
- 「fire and forgot」, 發送即遺忘
- 命令:Publish/Subscribe/Psubscribe/UnSub
Redis特性3:Stream
- Redis 5.0新增
- 等待消費
- 消費組(組內競爭)
- 消費歷史數據
- FIFO
以上就是Redis的基本概念,下面咱們將介紹在開發過程當中可能會踩到的「坑」。
Redis常見問題解析:擊穿
概念:在Redis獲取某一key時, 因爲key不存在, 而必須向DB發起一次請求的行爲, 稱爲「Redis擊穿」。
引起擊穿的緣由:
- 第一次訪問
- 惡意訪問不存在的key
- Key過時
合理的規避方案:
- 服務器啓動時, 提早寫入
- 規範key的命名, 經過中間件攔截
- 對某些高頻訪問的Key,設置合理的TTL或永不過時
Redis常見問題解析:雪崩
概念:Redis緩存層因爲某種緣由宕機後,全部的請求會涌向存儲層,短期內的高併發請求可能會致使存儲層掛機,稱之爲「Redis雪崩」。
合理的規避方案:
- 使用Redis集羣
- 限流
Redis在產品開發中的應用實踐
爲此,我很高興的爲你們介紹,葡萄城架構師Jim將在2019-11-27 14:00 爲你們帶來一場公開課,其中 Jim除了爲你們講解Redis的基礎,同時也會實際演示他所在的項目組使用Redis時碰到的問題以及解決方案,對於剛接觸Redis的同窗來講,更具參考意義和學習價值,歡迎你們屆時參加,公開課地址:https://live.vhall.com/661463644。
- 後端採用nodeJS
- 使用Azure的Redis服務
- Redis的使用場景
- token緩存, 用於令牌驗證
- IP白名單
碰到的問題
- 「網絡抖動」或者Redis服務異常致使Redis訪問超時
- Redis客戶端驅動穩定性問題
- 鏈接池 「Broken connection」 問題
- JS的Promise引出的Redis重置問題
下面咱們來簡單瞭解一下Redis的進階知識。
進階之Redis協議簡介
Redis客戶端通信協議:RESP(Redis Serialization Protocol),其特色是:
- 簡單
- 解析速度快
- 可讀性好
Redis集羣內部通信協議:RECP(Redis Cluster Protocol ) ,其特色是:
- 每個node兩個tcp 鏈接
- 一個負責client-server通信(P: 6379)
- 一個負責node之間通信(P: 10000 + 6379)
Redis協議支持的數據類型:
- 簡單字符(首字節: 「+」)
「+OK\r\n」
- 錯誤(首字節: 「-」)
「-error msg\r\n」
- 數字(首字節: 「:」)
「:123\r\n」
- 批量字符(首字節: 「$」)
「&hello\r\nWhoa re you\r\n」
- 數組(首字節: 「*」)
「*0\r\n」
「*-1\r\n」
除了Redis,還有什麼NoSQL型數據庫
市面上相似於Redis,一樣是NoSQL型的數據庫有不少,以下圖所示,除了Redis,還有MemCache、Cassadra和Mongo。下面,咱們就分別對這幾個數據庫作一下簡要的介紹:
Memcache:這是一個和Redis很是類似的數據庫,可是它的數據類型沒有Redis豐富。Memcache由LiveJournal的Brad Fitzpatrick開發,做爲一套分佈式的高速緩存系統,被許多網站使用以提高網站的訪問速度,對於一些大型的、須要頻繁訪問數據庫的網站訪問速度的提高效果十分顯著。
Apache Cassandra:(社區內通常簡稱爲C*)這是一套開源分佈式NoSQL數據庫系統。它最初由Facebook開發,用於儲存收件箱等簡單格式數據,集Google BigTable的數據模型與Amazon Dynamo的徹底分佈式架構於一身。Facebook於2008將 Cassandra 開源,因爲其良好的可擴展性和性能,被 Apple、Comcast、Instagram、Spotify、eBay、Rackspace、Netflix等知名網站所採用,成爲了一種流行的分佈式結構化數據存儲方案。
MongoDB:是一個基於分佈式文件存儲、面向文檔的NoSQL數據庫,由C++編寫,旨在爲WEB應用提供可擴展的高性能數據存儲解決方案。MongoDB是一個介於關係數據庫和非關係數據庫之間的產品,是非關係數據庫當中功能最豐富,最像關係型數據庫的,它支持的數據結構很是鬆散,是一種相似json的BSON格式。