當前位置:首頁 » 硬碟大全 » redis緩存樹形結構
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

redis緩存樹形結構

發布時間: 2023-07-17 06:37:27

⑴ redis源碼解讀:單線程的redis是如何實現高速緩存

redis可能是最近幾年最火的緩存資料庫方案了,在各個高並發領域都有應用。

這篇文章,我們將從源代碼的角度來分析一下,為何如此一個高性能,高應用的緩存,會是單線程的方案,當然一個方案的高性能,高並發是多方面的綜合因素,其它的因素我們將在後續解讀。後續分析主要以LINUX操作系統為基礎,這也是redis應用最廣的平台。

單線程最大的受限是什麼?就是CPU,現在伺服器一般已經是多CPU,而單線程只能使用到其中的一個核。

redis作為一個網路內存緩存資料庫,在實現高性能時,主要有4個點。

1.網路高並發,高流量的數據處理。

一個非同步,高效,且對CPU要求不高的網路模型,這個模型主要是由OS來提供的,目前在LINUX最主流使用的是EPOLL,這個網上介紹很多,主要是基於事件驅動的一個非同步模型。

2.程序內部的合理構架,調用邏輯,內存管理。

redis在採用純C實現時,整體調用邏輯很短,但在內存方面,適當的合並了一些對象和對齊,比如sds等,在底層使用了內存池,在不同情況下使用的不太一樣。

但整體處理上沒有NGINX的內池設計巧妙,當然二者不太一樣,NGINX是基於請求釋放的邏輯來設計的,因此針對請求,可以一次申請大塊,分量使用,再最後統一釋放。

3.數據復制的代價,不管是讀取數據或是寫入數據,一般都是需要有數據復制的過程。

數據復制其實就是一次內存,真正的代價是在於存在大VALUE,當value值長度超過16KB時,性能會開始下降。因為單線程的原因,如果存在一個超大VALUE,比如20MB,則會因為這個請求卡住整個線程,導致後續的請求進不來,雖然後面的請求是能快速處理的小請求。

4.redis中數據結構中演算法的代價,有些結構在大數據量時,代價是很高的。

很多時間,大家忽略了演算法的運算代碼,因為像memcached等這類是完全的KV緩存,不存在什麼演算法,除了一個KEY的查找定位HASH演算法。

而redis不一樣,提供了不少高階的數據對象,這些對象具有上層的一些演算法能力,而這些能力是需要比如GEO模塊。

⑵ redis緩存原理

1、Redis是一種內存高速cache,如果使用redis緩存,那經常被訪問的內容會被緩存在內存中,需要使用的時候直接從內存調取,不知道比硬碟調取快了多少倍,並且支持復雜的數據結構,應用於許多高並發的場景中。
2、Redis支持主從同步。數據可以從主伺服器向任意數量的從伺服器上同步,從伺服器可以是關聯其他從伺服器的主伺服器。這使得Redis可執行單層樹復制。存檔可以有意無意的對數據進行寫操作。由於完全實現了發布/訂閱機制,使得從資料庫在任何地方同步樹時,可訂閱一個頻道並接收主伺服器完整的消息發布記錄。同步對讀取操作的可擴展性和數據冗餘很有幫助。zset是set的一個升級版本,他在set的基礎上增加了一個順序屬性,這一屬性在添加修改元素的時候可以指定,每次指定後,zset會自動重新按新的值調整順序。可以理解了有兩列的mysql表,一列存value,一列存順序。操作中key理解為zset的名字。
更多關於redis緩存原理,進入:https://www.abcgonglue.com/ask/66eab61616100681.html?zd查看更多內容

⑶ 基於redis做緩存分頁

在實際業務中我們會將一些熱空兄數據緩存到redis裡面,這時候數據量比較大的話,我們就要對這些熱數據進行分頁,分頁的方式有2種:

第一:從redis拿出所有數據後,再做內存分頁(不推薦),熱點數據小的時候可以這樣做,性能相差不是很大,但是當數據量大的時候,分頁期間就會佔用大量內存,或撐爆;

第二:基於redis的數據結構做緩存分頁,這里又分2種

①:基於redis的list數據結構,直接通過list的數據結構,用range方法可以進行分頁,在數據量大的時候,性能也很可觀,但是當存在介面高並發訪問時,這個list可能會無限延長,且裡面的數據會存在很多重復,這就會影響到正常的業務(不是很推薦);

②:基於redis的ZSet數據結構,通過Zset這個有序集合我們也可以做分頁,同樣也是用range方法,但是這里比較麻煩的是在初始化數據的時候Zset必須存放TypedTuple類型的數據,這個類型是一個value和score的鍵值對,具體可以查網路,這個score的生成比較麻煩我這邊測試時用的是當前數據在這個list的位置,然後Zset是根據這個score值來排序的,默認是從小到大;用這個的好處是,即使在高並發情況下Zset中也不會存在重復數據從而影響正常的業務;而且分頁效率也和list結構差不多;

③:用hash和Zset來一起實現;這個是問了一個朋友和得知的,Zset中存儲有序灶高的id欄位,通過分頁後拿到id,然後再用id去hash中取,感覺應該效率相差不大的,只是中間多了層從hash結構取,還需要維護又一個hash;(為何這樣做我也不清楚);

貼一張我斗辯襲測試list和ZSet的結果圖

⑷ Redis底層數據結構解密

一:摘要概述
很多 redis 的使用者都可以清晰明白的道出Redis中常用的對象如string、list、hash、set、zset,一些場景比較豐富的使用者可能會說布隆過濾器、geo、Hash等。但是對於這些對象底層實現的數據結構卻是知之甚少,將會詳細闡述redis中的底層數據結構。為了彌補大家的創傷,今天分享Redis底層數據結構內容。
二:SDS
string作為redis中常用對象之一,普遍用於用戶信息緩存等場景。當string對象中encoding編碼為embstr或raw時都是採用sds作為其底層實現
2.1 SDS結構
源碼文件位於redis安裝目錄src下的sds.h,sds聲明了五種頭部類型,分別為sdshdr5、sdshdr8、sdshdr16、sdshdr32、sdshdr64。根據字元串長度創建不同頭部的sds實例
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len;
uint8_t alloc;
unsigned char flags;
char buf[];
};
屬性名稱作用含義
len字元串長度
alloc預分配空間大小
flags低三位用於表示sds類型,可以查看sds.h文件76-82行定義
buf[]存儲字元串用數組
2.2 SDS與C字元串區別
區別描述
長度計算 c中的字元串長度計算需要數組遍歷,但是redis中的sds自身維護了len屬性。所以O(1)時間復雜度即可
緩沖區溢出c中字元串更改如果未提前做好內存分配則會內存溢出,但是sds則會根據alloc與len計算預留內存是否足夠分配重新申請內存
動態擴展 緩沖區溢出已經闡述這個概念,sds的內存空間會在字元串內容變更時自動擴展計算。策略為當字元換小於1M時*2翻倍,大於1M時每次擴容1M
惰性釋放 與空間預分配相似操作的還有內存惰性釋放,即字元串刪除某些內容後所佔用的內存空間並不會立即釋放,後續字元串變更擴展就無需再申請內存
二:ZipList
ziplist可以說把redis對於內存的極致操作體現的淋漓盡致,鏈表除了節點值之外還需要維護前後節點兩個指針,並且還會造成內存碎片。壓縮列表緊湊的內存布局,所有節點都維護在整塊內存中處理
2.1 ZipList結構
屬性名稱作用含義
zlbytes列表健佔用內存的總位元組數,在對列表健內存重分配或者是計算zlend的時候使用
zltail 指向壓縮列表起始地址的指針
zllen 壓縮列表的節點數量
entry壓縮列表保存的節點數據
zlend壓縮列表的尾節點
2.2 Entry節點結構
屬性名稱作用含義
previous_entry_length 位元組為單位記錄上一個節點的長度,如果上一個位元組長度小於254佔用1位元組。大於254佔用5位元組,第一個位元組設置為OxFE(十進制254),後面四個位元組儲存長度
encoding 記錄content記錄的數據類型以及長度。長度一、二、五位元組,值的最高位為00、01、10表示類型為位元組數組,長度使用除去最高位的其它位記錄。11開頭表示儲存整數,除去最高位其他位置表示content數據長度
content 記錄壓縮列表記錄的數據

⑸ 怎麼實現redis的資料庫的緩存(redis實現緩存的流程)

大致為兩種措施:

一、腳本同步:

1、自己寫腳本將資料庫數據寫入到redis/memcached。

2、這就涉及到實時數據變更的問題(mysqlrowbinlog的實時分析),binlog增量訂閱Alibaba的canal,以及緩存層數據丟失/失效後的數據同步恢復問題。

二、純賀業務層實現:

1、先讀取nosql緩存層,沒有數據再讀取mysql層,並寫入數據到nosql。

2、nosql層做好多節點分布式(一致性hash),以及節點失效後替代方案(多層hash尋找相鄰替代節點),和數據震盪恢復了。

redis實現資料庫緩存的分析:

對於變化頻率非常快的數據來說,如果還選擇傳統的靜態緩存方式(Memocached、FileSystem等)展示數據,可能在緩存的存取上會有很大的開銷則褲差,並不能很好的滿足需要,而Redis這樣基於內存的NoSQL資料庫,就非常適合擔任實時數據的容器。

但是往往又有數據可靠性的需求,採用MySQL作為數據存儲,不會因為內存問題而引起數據丟失,同時也可以利用關系資料庫的特性實現很多功能。所以就會很自然的想到是否可以採用MySQL作為數據存孫皮儲引擎,Redis則作為Cache。

MySQL到Redis數據復制方案,無論MySQL還是Redis,自身都帶有數據同步的機制,比較常用的MySQL的Master/Slave模式,就是由Slave端分析Master的binlog來實現的,這樣的數據復制其實還是一個非同步過程,只不過當伺服器都在同一內網時,非同步的延遲幾乎可以忽略。那麼理論上也可用同樣方式,分析MySQL的binlog文件並將數據插入Redis。

因此這里選擇了一種開發成本更加低廉的方式,借用已經比較成熟的MySQLUDF,將MySQL數據首先放入Gearman中,然後通過一個自己編寫的PHPGearmanWorker,將數據同步到Redis。比分析binlog的方式增加了不少流程,但是實現成本更低,更容易操作。

⑹ redis做mysql的緩存

redis緩存其實就是把經常訪問的數據放到redis裡面,用戶查詢的時候先去redis查詢,沒有查到就執行sql語句查詢,同時把數據同步到redis裡面。redis只做讀操作,在內存中查詢速度快。

使用redis做緩存必須解決兩個問題,首先就是確定用何種數據結構存儲來自mysql的數據;確定數據結構之後就是需要確定用什麼標識來作為數據的key。
mysql是按照表存儲數據的,這些表是由若干行組成。每一次執行select查詢,mysql都會返回一個結果集,這個結果是由若干行組成的。redis有五種數據結構:列表list,哈希hash,字元串string,集合set,sorted set(有序集合),對比幾種數據結構,string和hash是比較適合存儲行的數據結構,可以把數據轉成json字元串存入redis。

全量遍歷鍵: keys pattern keys *
有人說 KEYS 相當於關系性數據的庫的 select * ,在生產環境幾乎是要禁用的

不管上面說的對不對, keys 肯定是有風險的。那我們就換一種方案,在存數據的時候。把數據的鍵存一下,也存到redis裡面選hash類型,那麼取的時候就可以直接通過這個hash獲取所有的值,自我感覺非常好用!

⑺ redis數據結構

redis數據結構

Redis是一種存儲key-value的內存型資料庫,它的key都是字元串類型,value支持存儲5種類型的數據:String(字元串類型)、List(列表類型)、Hash(哈希表類型、即key-value類型)、Set(無序集合類型,元素不可重復)、Zset(有序集合類型,元素不可重復)。

針對這5種數據類型,Redis在底層都是使用的redisObject對象表示的。redisObject有3個重要的屬性:type、encoding、ptr。

redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字元串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。

在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁碟或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。

⑻ 緩存-redis 三種模式搭建和運行原理

標簽: redis 緩存 主從 哨兵 集群

本文簡單的介紹redis三種模式在linux的安裝部署和數據存儲的總結,希望可以相互交流相互提升。

對於Centos7在安裝redis之前需要進行一些常用工具的安裝:

關閉防火牆

正式安裝redis

在redis進行maketest時候會出現一系列的異常,有如下解決方案:

用redis-server啟動一下redis,做一些實驗沒什麼意義。

要把redis作為一個系統的daemon進程去運行的,每次系統啟動,redis進程一起啟動,操作不走如下:

RDB和AOF是redis的一種數據持久化的機制。 持久化 是為了避免系統在發生災難性的系統故障時導致的系統數據丟失。我們一般會將數據存放在本地磁碟,還會定期的將數據上傳到雲伺服器。
RDB 是redis的snapshotting,通過redis.conf中的save配置進行設置,如 save 60 1000:

AOF 是以appendonly方式進行數據的儲存的,開啟AOF模式後,所有存進redis內存的數據都會進入os cache中,然後默認1秒執行一次fsync寫入追加到appendonly.aof文件中。一般我們配置redis.conf中的一下指令:

AOF和RDB模式我們一般在生產環境都會打開,一般而言,redis服務掛掉後進行重啟會優先家在aof中的文件。

當啟動一個slave node的時候,它會發送一個PSYNC命令給master node,如果這是slave node重新連接master node,那麼master node僅僅會復制給slave部分缺少的數據;否則如果是slave node第一次連接master node,那麼會觸發一次full resynchronization;
開始full resynchronization的時候,master會啟動一個後台線程,開始生成一份RDB快照文件,同時還會將從客戶端收到的所有寫命令緩存在內存中。RDB文件生成完畢之後,master會將這個RDB發送給slave,slave會先寫入本地磁碟,然後再從本地磁碟載入到內存中。然後master會將內存中緩存的寫命令發送給slave,slave也會同步這些數據。
slave node如果跟master node有網路故障,斷開了連接,會自動重連。master如果發現有多個slave node都來重新連接,僅僅會啟動一個rdb save操作,用一份數據服務所有slave node。

從redis 2.8開始,就支持主從復制的斷點續傳,如果主從復制過程中,網路連接斷掉了,那麼可以接著上次復制的地方,繼續復制下去,而不是從頭開始復制一份。

master node會在內存中常見一個backlog,master和slave都會保存一個replica offset還有一個master id,offset就是保存在backlog中的。如果master和slave網路連接斷掉了,slave會讓master從上次的replica offset開始繼續復制,但是如果沒有找到對應的offset,那麼就會執行一次resynchronization。

master在內存中直接創建rdb,然後發送給slave,不會在自己本地落地磁碟了,可以有如下配置:

slave不會過期key,只會等待master過期key。如果master過期了一個key,或者通過LRU淘汰了一個key,那麼會模擬一條del命令發送給slave。

在redis.conf配置文件中,上面的參數代表至少需要3個slaves節點與master節點進行連接,並且master和每個slave的數據同步延遲不能超過10秒。一旦上面的設定沒有匹配上,則master不在提供相應的服務。

sdown達成的條件很簡單,如果一個哨兵ping一個master,超過了 is-master-down-after-milliseconds 指定的毫秒數之後,就主觀認為master宕機
sdown到odown轉換的條件很簡單,如果一個哨兵在指定時間內,收到了 quorum 指定數量的其他哨兵也認為那個master是sdown了,那麼就認為是odown了,客觀認為master宕機

如果一個slave跟master斷開連接已經超過了down-after-milliseconds的10倍,外加master宕機的時長,那麼slave就被認為不適合選舉為master

(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

每次一個哨兵要做主備切換,首先需要quorum數量的哨兵認為odown,然後選舉出一個slave來做切換,這個slave還得得到majority哨兵的授權,才能正式執行切換;

(2)SENTINEL RESET *,在所有sentinal上執行,清理所有的master狀態
(3)SENTINEL MASTER mastername,在所有sentinal上執行,查看所有sentinal對數量是否達成了一致

4.3.2 slave的永久下線

讓master摘除某個已經下線的slave:SENTINEL RESET mastername,在所有的哨兵上面執行.

redis的集群模式為了解決系統的橫向擴展以及海量數據的存儲問題,如果你的數據量很大,那麼就可以用redis cluster。
redis cluster可以支撐N個redis master,一個master上面可以掛載多個slave,一般情況我門掛載一個到兩個slave,master在掛掉以後會主動切換到slave上面,或者當一個master上面的slave都掛掉後,集群會從其他master上面找到冗餘的slave掛載到這個master上面,達到了系統的高可用性。

2.1 redis cluster的重要配置

2.2 在三台機器上啟動6個redis實例

將上面的配置文件,在/etc/redis下放6個,分別為: 7001.conf,7002.conf,7003.conf,7004.conf,7005.conf,7006.conf

每個啟動腳本內,都修改對應的埠號

2.3 創建集群

解決辦法是 先安裝rvm,再把ruby版本提升至2.3.3

使用redis-trib.rb命令創建集群

--replicas: 表示每個master有幾個slave

redis-trib.rb check 192.168.31.187:7001 查看狀體

3.1 加入新master

以上相同配置完成後,設置啟動腳本進行啟動;然後用如下命令進行node節點添加:

3.2 reshard一些數據過去

3.3 添加node作為slave

3.4 刪除node