www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > > 架構(gòu)師社區(qū)
[導(dǎo)讀]提到Redis,大家一定會想到的幾個點是什么呢?高并發(fā)、KV存儲、內(nèi)存數(shù)據(jù)庫、豐富的數(shù)據(jù)結(jié)構(gòu)、單線程(版本6之前)等。那么,接下來,上面提到的這些,都會一一給大家解答,帶大家系統(tǒng)剖析一下Redis的架構(gòu)設(shè)計魅力!

-? ? ? 01、不一樣的Redis? ? -

提到Redis,大家一定會想到的幾個點是什么呢?

高并發(fā)、KV存儲、內(nèi)存數(shù)據(jù)庫、豐富的數(shù)據(jù)結(jié)構(gòu)、單線程(版本6之前)等。

那么,接下來,上面提到的這些,都會一一給大家解答,帶大家系統(tǒng)剖析一下Redis的架構(gòu)設(shè)計魅力!


深度剖析不一樣的Redis架構(gòu)設(shè)計

-? ? ? 02、為什么會出現(xiàn)緩存?? ? -



一般情況下,數(shù)據(jù)都是在數(shù)據(jù)庫中,應(yīng)用系統(tǒng)直接操作數(shù)據(jù)庫。當(dāng)訪問量上萬,數(shù)據(jù)庫壓力增大,這個時候,怎么辦呢?


有小伙伴會說,分庫分表、讀寫分離。的確,這些確實是解決比較高的訪問量的解決辦法,但是,如果訪問量更大,10萬,100萬呢?怎么分似乎都不解決問題吧,所以我們需要用到其他辦法,來解決高并發(fā)帶來的數(shù)據(jù)庫壓力。


這個時候,緩存出現(xiàn)了,顧名思義,就是先把數(shù)據(jù)緩存在內(nèi)存中一份,當(dāng)訪問的時候,我們會先訪問內(nèi)存的數(shù)據(jù),如果內(nèi)存中的數(shù)據(jù)不存在,這個時候,我們再去讀取數(shù)據(jù)庫,之后把數(shù)據(jù)庫中的數(shù)據(jù)再備份一份到內(nèi)存中,這樣下次讀請求過來的時候,還是會直接先從內(nèi)存中訪問,訪問到內(nèi)存的數(shù)據(jù)了之后就直接返回了。這樣做就完美的降低了數(shù)據(jù)庫的壓力,可能十萬個請求進來,全部都訪問了內(nèi)存中備份的數(shù)據(jù),而沒有去訪問數(shù)據(jù)庫,或者說只有少量的請求訪問到了數(shù)據(jù)庫,這樣真的是大大降低了數(shù)據(jù)庫的壓力,而且這樣做也提高了系統(tǒng)響應(yīng),大家想一下,內(nèi)存的讀寫速度是遠(yuǎn)遠(yuǎn)大于硬盤的讀寫速度的,一個請求進來讀取的內(nèi)存可以比讀取硬盤快很多很多,用戶的體驗也會很高。


深度剖析不一樣的Redis架構(gòu)設(shè)計

-? ? ? 03、什么是緩存?? ? -



緩存原指CPU上的一種高速存儲器,它先于內(nèi)存與CPU交換數(shù)據(jù),速度很快。

現(xiàn)在泛指存儲在計算機上的原始數(shù)據(jù)的復(fù)制集,便于快速訪問。

在互聯(lián)網(wǎng)技術(shù)中,緩存是系統(tǒng)快速響應(yīng)的關(guān)鍵技術(shù)之一。


深度剖析不一樣的Redis架構(gòu)設(shè)計

-? ? ? 04、緩存的三種讀寫模式? ? -



1、Cache Aside Pattern(常用)

Cache Aside Pattern(旁路緩存),是最經(jīng)典的緩存+數(shù)據(jù)庫讀寫模式。

讀的時候,先讀緩存,緩存沒有的話,就讀數(shù)據(jù)庫,然后取出數(shù)據(jù)后放入緩存,同時返回響應(yīng)。


深度剖析不一樣的Redis架構(gòu)設(shè)計


更新的時候,先更新數(shù)據(jù)庫,然后再刪除緩存。


深度剖析不一樣的Redis架構(gòu)設(shè)計


為什么是刪除緩存,而不是更新緩存呢?

1、緩存的值是一個結(jié)構(gòu),hash、list等更新數(shù)據(jù)需要遍歷;

2、懶加載,使用的時候才更新緩存,也可以采用異步的方式填充緩存。


高并發(fā)臟讀的三種情況:

1、先更新數(shù)據(jù)庫,在更新緩存;

深度剖析不一樣的Redis架構(gòu)設(shè)計


update與commit之間,更新緩存,commit失敗,則DB與緩存數(shù)據(jù)不一致。


2、先刪除緩存,再更新數(shù)據(jù)庫

深度剖析不一樣的Redis架構(gòu)設(shè)計


update與commit之間,有新的讀,緩存空,讀DB數(shù)據(jù)到緩存,數(shù)據(jù)是舊的數(shù)據(jù);

commit后DB為新的數(shù)據(jù);

則DB與緩存數(shù)據(jù)不一致。


3、先更新數(shù)據(jù)庫,再刪除緩存(推薦)


深度剖析不一樣的Redis架構(gòu)設(shè)計


update與commit之間,有新的讀,緩存空,讀DB數(shù)據(jù)到緩存,數(shù)據(jù)是舊的數(shù)據(jù);

commit后DB為新的數(shù)據(jù);

則DB與緩存數(shù)據(jù)不一致;

采用延時雙刪策略。


2、Read/Write Through Pattern

應(yīng)用程序只操作緩存,緩存操作數(shù)據(jù)庫;

Read-Through(穿透讀模式/直讀模式):應(yīng)用程序讀緩存,緩存沒有,由緩存回源到數(shù)據(jù)庫,并寫入緩存;

Write-Through(穿透寫模式/直寫模式):應(yīng)用程序?qū)懢彺?,緩存寫?shù)據(jù)庫。該種模式需要提供數(shù)據(jù)庫的handler,開發(fā)較為復(fù)雜。


3、Write Behind Caching Pattern

應(yīng)用程序只更新緩存;

緩存通過異步的方式將數(shù)據(jù)批量或合并后更新到DB中,不能時時同步,甚至?xí)G數(shù)據(jù)。

深度剖析不一樣的Redis架構(gòu)設(shè)計

-? ? ? 05、Redis又是什么?? ? -


Redis是一個高性能的開源的,C語言寫的NoSQL(非關(guān)系型數(shù)據(jù)庫)也叫做緩存數(shù)據(jù)庫,數(shù)據(jù)保存在內(nèi)存中。Redis是以key-value形式存儲,和傳統(tǒng)的關(guān)系型數(shù)據(jù)庫不一樣。不一定遵循傳統(tǒng)數(shù)據(jù)庫的那些基本要求。比如,不遵循SQL標(biāo)準(zhǔn)、事務(wù)、表結(jié)構(gòu)等。Redis有非常豐富的數(shù)據(jù)類型,比如String,list,set,zset,hash等。


深度剖析不一樣的Redis架構(gòu)設(shè)計

-? ? ? 06、Redis可以做什么?? ? -


1、減輕數(shù)據(jù)庫壓力,提高并發(fā)量,提高系統(tǒng)響應(yīng)時間


2、做Session分離

傳統(tǒng)的Session是由自己的tomcat進行維護和管理的,在集群和分布式情況下,不同的tomcat要管理不同的session,只能在各個tomcat之間,通過網(wǎng)絡(luò)和IO進行session復(fù)制,極大的影響了系統(tǒng)的性能。


Redis解決了這一個問題,將登陸成功后的session信息,存放在Redis中,這樣多個tomcat就可以共享Session信息。


深度剖析不一樣的Redis架構(gòu)設(shè)計


3、做分布式鎖

一般Java中的鎖都是多線程鎖,是在一個進程中的,多個進程在并發(fā)的時候也會產(chǎn)生問題,也要控制時序性,這個時候Redis可以用來做分布式鎖,使用Redis的setnx命令來實現(xiàn)。


4、電商購物車:

1、以用戶id為key

2、商品id為field

3、商品數(shù)量為value

電商購物車操作:

1、添加商品:hset cart:1001 10088 1

2、增加數(shù)量:hincrby cart:1001 10088 1

3、商品總數(shù):hlen cart:1001

4、刪除商品:hdel cart:1001 10088

5、獲取購物車所有商品:hgetall cart:1001


深度剖析不一樣的Redis架構(gòu)設(shè)計




5、zset集合操作實現(xiàn)排行榜

1、點擊新聞

ZINCRBY hotNews:20190819 1 守護香港

2、展示當(dāng)日排行前十

ZREVRANGE hotNews:20190819 0 9 WITHSCORES

3、七日搜索榜單計算

ZUNIONSTORE hotNews:20190813-20190819 7

hotNews:20190813 hotNews:20190814... hotNews:20190819

4、展示七日排行前十

ZREVRANGE hotNews:20190813-201908109 0 9 WITHSCORES


深度剖析不一樣的Redis架構(gòu)設(shè)計



用Redis做緩存,有這么有多優(yōu)點,那么,缺點是不是也會對應(yīng)的有很多呢?

1、額外的硬件支出

緩存是一種軟件系統(tǒng)中以空間換時間的技術(shù),需要額外的磁盤空間和內(nèi)存空間來存儲數(shù)據(jù)。


2、高并發(fā)緩存失效

在高并發(fā)的情況下,會出現(xiàn)緩存失效(緩存穿透,緩存雪崩,緩存擊穿等問題)造成瞬間數(shù)據(jù)庫訪問量增大,甚至崩潰,所以這些問題是一定要去解決。


3、緩存與數(shù)據(jù)庫數(shù)據(jù)同步

緩存與數(shù)據(jù)庫無法做到數(shù)據(jù)的實時同步。


4、緩存并發(fā)競爭

多個Redis客戶端同時對一個key進行set值的時候由于執(zhí)行順序引起的并發(fā)的問題。


深度剖析不一樣的Redis架構(gòu)設(shè)計

-? ? ? 07、Redis高性能設(shè)計? ? -

1、Redis是單線程的么?

Redis的單線程主要是指Redis的網(wǎng)絡(luò)IO和鍵值對讀寫是由一個線程來完成的,這也是Redis對外提供鍵值存儲服務(wù)的主要流程。但Redis的其他功能,比如持久化,異步刪除,集群數(shù)據(jù)同步等,都是由額外的線程執(zhí)行的。


2、Redis單線程為什么還能這么快?

這里我們在本地測試一下Redis支持的并發(fā)。

執(zhí)行這條命令:./redis-benchmark get
結(jié)果:
============ get ==========
100000 requests completed in 1.02 seconds
50 parallel clients
3 bytes payload
keep alive: 1
host configuration "save": 900 1 300 10 60 10000
host configuration "appendonly": no

multi-thread: no


0.00% <= 0.1 milliseconds
13.00% <= 0.2 milliseconds
55.85% <= 0.3 milliseconds
80.60% <= 0.4 milliseconds
92.57% <= 0.5 milliseconds
97.12% <= 0.6 milliseconds
99.06% <= 0.7 milliseconds
99.68% <= 0.8 milliseconds
99.86% <= 0.9 milliseconds
99.90% <= 1.0 milliseconds
99.90% <= 1.1 milliseconds

13.00% <= 0.2 milliseconds
55.85% <= 0.3 milliseconds
80.60% <= 0.4 milliseconds
92.57% <= 0.5 milliseconds
97.12% <= 0.6 milliseconds
99.06% <= 0.7 milliseconds
99.68% <= 0.8 milliseconds
99.86% <= 0.9 milliseconds
99.90% <= 1.0 milliseconds
99.90% <= 1.1 milliseconds
99.90% <= 1.2 milliseconds
99.91% <= 1.3 milliseconds
99.93% <= 1.4 milliseconds
99.95% <= 1.5 milliseconds
99.97% <= 1.6 milliseconds
99.98% <= 1.7 milliseconds
99.99% <= 1.8 milliseconds
99.99% <= 1.9 milliseconds
100.00% <= 2 milliseconds
100.00% <= 2 milliseconds
98328.42 requests per second

這里我們可以看到,每秒的話,差不多可以支持小10萬的并發(fā),這已經(jīng)是一個很恐怖的數(shù)據(jù)了。


因為它的所有數(shù)據(jù)都在內(nèi)存中,所有的運算都是內(nèi)存級別的運算,而且單線程避免了多線程的切換性能消耗問題。正因為Redis是單線程的,所以要小心使用Redis命令,對于那些耗時的指令(比如keys),一定要謹(jǐn)慎使用,一不小心就可能導(dǎo)致Redis卡頓。

Redis單線程如何處理那么多并發(fā)客戶端連接?


Redis的IO多路復(fù)用:Redis利用epoll來實現(xiàn)IO多路復(fù)用,將連接信息和事件放到隊列中,一次放到文件事件分派器,事件分派器將事件分發(fā)給事件處理器。


深度剖析不一樣的Redis架構(gòu)設(shè)計

-? ? ? 08、Redis核心設(shè)計原理? ? -



Redis作為key-value存儲系統(tǒng),數(shù)據(jù)結(jié)構(gòu)如下:

深度剖析不一樣的Redis架構(gòu)設(shè)計


一個Redis實例對應(yīng)多個DB,一個DB對應(yīng)多個key,key一般都是string的,后面的value叫做RedisObject,不是說value就是string,list,map這些,而是說這些所有的類型,都被Redis封裝成了一個叫RedisObjcet,具體是哪個類型呢?這里是用指針的方式來指向具體是哪個類型。

深度剖析不一樣的Redis架構(gòu)設(shè)計


為什么要這么做,主要是為了提高Redis的性能。

PS:這里插一句,為什么使用指針的方式要比使用對象本身的方式性能更好呢?


這里有兩點:

第一點是動態(tài)分配;第二是指針一大特點在于你只需要在前面聲明一下指針指向的類型(而如果要使用實際的對象,你還需要定義一下)。這樣你就能降低你的編譯單元之間的耦合性從而減少編譯時間。


1、RedisDB結(jié)構(gòu)

Redis沒有表的概念,Redis實例所對應(yīng)的DB以編號區(qū)分,DB本身就是key的命名空間

比如:user:1000作為key的值,表示在user這個命名空間下id為1000的元素,類似于user表的id=1000的行。


2、SDS字符串

眾所周知,Redis是用C語言來實現(xiàn)的,在C語言中,String這個類型,其實就是一個char數(shù)組,比如char data[]="xxx\0",但是,客戶端往Redis發(fā)送set命令,是可以發(fā)任意的字符串的,是沒有校驗的,所以假如我們發(fā)了一個字符串xx\0xx,那么\0后面的xx是不會讀的,只會讀前面的xx(C語言中用"\0"表示字符串結(jié)束,如果字符串本身就有"\0"字符,字符串就會被截斷)。


所以Redis自實現(xiàn)了一個string叫sds,sds中記錄了一個len和一個char buf[],len用來記錄buf的長度,比如char buf[] = "xx\0xx",那么len就是5,sds中還有一個比較重要的屬性就是free,表示還剩余多少。


free是通過改變len來計算,比如"xxx1234" 改成 "xxx123456",那么會按照(len+addlen)*2=18 來擴容,這個時候len變成了9,free就是18-9也變成了9。


例如:

char buf[] = "xxx1234" 改成 "xxx123456" //這里的buf是柔性數(shù)組
free:12 變成free:10
len:8 變成len:10

Redis這樣設(shè)計SDS有什么好處:

1、二進制安全的數(shù)據(jù)結(jié)構(gòu);

2、提供了內(nèi)存預(yù)分配機制,避免了頻繁的內(nèi)存分配;

3、兼容C語言的函數(shù)庫;

4、有單獨的統(tǒng)計變量len和free,可以方便的得到字符串長度,這樣就避免了讀取不完整的風(fēng)險;

5、內(nèi)容存放在柔性數(shù)組buf中,SDS對上層暴露的指針不是指向結(jié)構(gòu)體SDS的指針,而是直接指向柔性數(shù)組buf的指針。上層可像讀取C字符串一樣讀取SDS的內(nèi)容,兼容C語言處理字符串的各種函數(shù)。


這里解釋一下什么叫柔型數(shù)組?

柔型數(shù)組即數(shù)組大小待定的數(shù)組,C語言中結(jié)構(gòu)體的最后一個元素可以是大小未知的數(shù)組,也就是所謂的0長度,所以我們可以用結(jié)構(gòu)體來創(chuàng)建柔性數(shù)組。柔性數(shù)組主要用途是為了滿足需要變長度的結(jié)構(gòu)體,為了解決使用數(shù)組時內(nèi)存的冗余和數(shù)組的越界問題

這也是Redis3.2之前所實現(xiàn)的。


未完待續(xù),敬請期待下篇分析。

特別推薦一個分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長按關(guān)注一下:

深度剖析不一樣的Redis架構(gòu)設(shè)計

深度剖析不一樣的Redis架構(gòu)設(shè)計

深度剖析不一樣的Redis架構(gòu)設(shè)計

長按訂閱更多精彩▼

深度剖析不一樣的Redis架構(gòu)設(shè)計

如有收獲,點個在看,誠摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉