第71篇
極客時間《從0開始學(xué)架構(gòu)》課程筆記。
一、高性能NoSQL
關(guān)系數(shù)據(jù)庫的缺點
- 關(guān)系數(shù)據(jù)庫存儲的是行記錄,無法存儲數(shù)據(jù)結(jié)構(gòu)
- 關(guān)系數(shù)據(jù)庫的 schema 擴(kuò)展很不方便
- 關(guān)系數(shù)據(jù)庫在大數(shù)據(jù)場景下 I/O 較高
- 關(guān)系數(shù)據(jù)庫的全文搜索功能比較弱
NoSQL 技術(shù)是為了彌補(bǔ)關(guān)系型數(shù)據(jù)庫缺陷而產(chǎn)生的,NoSQL 不是銀彈,而應(yīng)該將 NoSQL 作為 SQL 的一個有力補(bǔ)充。
NoSQL != No SQL,而是 NoSQL = Not Only SQL。
常見的 NoSQL 方案分為 4 類
- K-V 存儲:解決關(guān)系數(shù)據(jù)庫無法存儲數(shù)據(jù)結(jié)構(gòu)的問題,以 Redis 為代表。
- 文檔數(shù)據(jù)庫:解決關(guān)系數(shù)據(jù)庫強(qiáng) schema 約束的問題,以 MongoDB 為代表。
- 列式數(shù)據(jù)庫:解決關(guān)系數(shù)據(jù)庫大數(shù)據(jù)場景下的 I/O 問題,以 HBase 為代表。
- 全文搜索引擎:解決關(guān)系數(shù)據(jù)庫的全文搜索性能問題,以 Elasticsearch 為代表。
各種高性能 NoSQL 方案的典型特征和應(yīng)用場景
K-V 存儲
定義:K-V 存儲的全稱是 Key-Value 存儲,其中 Key 是數(shù)據(jù)的標(biāo)識,和關(guān)系數(shù)據(jù)庫中的主鍵含義一樣,Value 就是具體的數(shù)據(jù)。
Redis 是 K-V 存儲的典型代表。Redis 的 Value 是具體的數(shù)據(jù)結(jié)構(gòu),包括 string、hash、list、set、sorted set、bitmap 和 hyperloglog,所以常常被稱為數(shù)據(jù)結(jié)構(gòu)服務(wù)器。
缺點:不支持完整的 ACID 事務(wù),Redis 的事務(wù)只能保證隔離性和一致性(I 和 C),無法保證原子性和持久性(A 和 D)。
文檔數(shù)據(jù)庫
定義:為了解決關(guān)系數(shù)據(jù)庫schema不易修改問題而產(chǎn)生的新型數(shù)據(jù)庫。絕大部分文檔數(shù)據(jù)庫存儲的數(shù)據(jù)格式是 JSON(或者 BSON),因為 JSON 數(shù)據(jù)是自描述的,能夠描述復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。適合電商和游戲這類的業(yè)務(wù)場景。
優(yōu)勢: no-schema,可以存儲和讀取任意的數(shù)據(jù)。
- 新增字段簡單
- 歷史數(shù)據(jù)不會出錯
- 可以很容易存儲復(fù)雜數(shù)據(jù)
缺點:不支持事務(wù),無法實現(xiàn)關(guān)系數(shù)據(jù)庫的 join 操作。注:最新版MongoDB已經(jīng)支持join操作。
列式數(shù)據(jù)庫
定義:按照列來存儲數(shù)據(jù)的數(shù)據(jù)庫,與之對應(yīng)的傳統(tǒng)關(guān)系數(shù)據(jù)庫被稱為“行式數(shù)據(jù)庫”,因為關(guān)系數(shù)據(jù)庫是按照行來存儲數(shù)據(jù)的。
一般將列式存儲應(yīng)用在離線的大數(shù)據(jù)分析和統(tǒng)計場景中,因為這種場景主要是針對部分列單列進(jìn)行操作,且數(shù)據(jù)寫入后就無須再更新刪除
優(yōu)勢:節(jié)省 I/O,并且列式存儲還具備更高的存儲壓縮比,能夠節(jié)省更多的存儲空間。典型的場景就是海量數(shù)據(jù)進(jìn)行統(tǒng)計。
缺點:列式存儲的隨機(jī)寫效率要遠(yuǎn)遠(yuǎn)低于行式存儲的寫效率,另外列式存儲高壓縮率在更新場景下也會成為劣勢,因為更新時需要將存儲數(shù)據(jù)解壓后更新,然后再壓縮,最后寫入磁盤。
全文搜索引擎
定義:全文搜索引擎的技術(shù)原理被稱為“倒排索引”(Inverted index),也常被稱為反向索引、置入檔案或反向檔案,是一種索引方法,其基本原理是建立單詞到文檔的索引。全文搜索引擎的索引對象是單詞和文檔,而關(guān)系數(shù)據(jù)庫的索引對象是鍵和行。
全文搜索的業(yè)務(wù)場景下,通過索引也無法達(dá)到快速查詢的目標(biāo)時,使用全文搜索引擎。因為全文搜索的條件可以隨意排列組合,而且全文搜索的模糊匹配通過like查詢方式效率很低。
優(yōu)勢:全文搜索引擎能夠基于 JSON 文檔建立全文索引,然后快速進(jìn)行全文搜索。
缺點:為了讓全文搜索引擎支持關(guān)系型數(shù)據(jù)的全文搜索,需要做一些轉(zhuǎn)換操作,即將關(guān)系型數(shù)據(jù)轉(zhuǎn)換為文檔數(shù)據(jù)。目前常用的轉(zhuǎn)換方式是將關(guān)系型數(shù)據(jù)按照對象的形式轉(zhuǎn)換為 JSON 文檔,然后將 JSON 文檔輸入全文搜索引擎進(jìn)行索引。
二、高性能緩存架構(gòu)
適用場景
- 經(jīng)過復(fù)雜運算后得出數(shù)據(jù),如同時在線人數(shù)
- 讀多寫少的數(shù)據(jù),如微博
緩存基本原理
將可能重復(fù)使用的數(shù)據(jù)放到內(nèi)存中,一次生成、多次使用,避免每次使用都去訪問存儲系統(tǒng),減輕存儲系統(tǒng)壓力。
架構(gòu)設(shè)計要點
緩存穿透
定義:是指緩存沒有發(fā)揮作用,業(yè)務(wù)系統(tǒng)雖然去緩存查詢數(shù)據(jù),但緩存中沒有數(shù)據(jù),業(yè)務(wù)系統(tǒng)需要再次去存儲系統(tǒng)查詢數(shù)據(jù)。
情形1:存儲數(shù)據(jù)不存在。
解決方案:如果查詢存儲系統(tǒng)的數(shù)據(jù)沒有找到,則直接設(shè)置一個默認(rèn)值(可以是空值,也可以是具體的值)存到緩存中,這樣第二次讀取緩存時就會獲取到默認(rèn)值,而不會繼續(xù)訪問存儲系統(tǒng)。
情形2:緩存數(shù)據(jù)生成耗費大量時間或者資源
解決方案:識別爬蟲然后禁止訪問,要么就是做好監(jiān)控,發(fā)現(xiàn)問題后及時處理。
緩存雪崩
定義:是指當(dāng)緩存失效(過期)后引起系統(tǒng)性能急劇下降的情況。即當(dāng)舊的緩存已經(jīng)被清除,新的緩存還未生成,并且處理這些請求的線程都不知道另外有一個線程正在生成緩存,因此所有的請求都會去重新生成緩存,都會去訪問存儲系統(tǒng),從而對存儲系統(tǒng)造成巨大性能壓力。
常見解決方法:更新鎖機(jī)制和后臺更新機(jī)制。
1、更新鎖
對緩存更新操作進(jìn)行加鎖保護(hù),保證只有一個線程能夠進(jìn)行緩存更新,未能獲取更新鎖的線程要么等待鎖釋放后重新讀取緩存,要么就返回空值或者默認(rèn)值。分布式集群的業(yè)務(wù)系統(tǒng)要實現(xiàn)更新鎖機(jī)制,需要用到分布式鎖,如 ZooKeeper。
2、后臺更新
由后臺線程來更新緩存,而不是由業(yè)務(wù)線程來更新緩存,緩存本身的有效期設(shè)置為永久,后臺線程定時更新緩存。后臺更新既適應(yīng)單機(jī)多線程的場景,也適合分布式集群的場景,相比更新鎖機(jī)制要簡單一些。
緩存熱點
定義:對于一些特別熱點的數(shù)據(jù),如果大部分甚至所有的業(yè)務(wù)請求都命中同一份緩存數(shù)據(jù),則這份數(shù)據(jù)所在的緩存服務(wù)器的壓力也很大。
解決方案:復(fù)制多份緩存副本,將請求分散到多個緩存服務(wù)器上,減輕緩存熱點導(dǎo)致的單臺緩存服務(wù)器壓力。并且設(shè)定一個過期時間范圍,不同的緩存副本的過期時間是指定范圍內(nèi)的隨機(jī)值。