亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Redis為何速度這么快

發布時間:2021-09-17 09:39:31 來源:億速云 閱讀:176 作者:小新 欄目:關系型數據庫

小編給大家分享一下Redis為何速度這么快,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

我們都知道Redis很快,它QPS可達10萬(每秒請求數)。那Redis為什么這么快呢

Redis為何速度這么快

基于內存實現

我們都知道內存讀寫是比磁盤讀寫快很多的。Redis是基于內存存儲實現的數據庫,相對于數據存在磁盤的數據庫,就省去磁盤磁盤I/O的消耗。MySQL等磁盤數據庫,需要建立索引來加快查詢效率,而Redis數據存放在內存,直接操作內存,所以就很快。

Redis為何速度這么快

高效的數據結構

我們知道,MySQL索引為了提高效率,選擇了B+樹的數據結構。其實合理的數據結構,就是可以讓你的應用/程序更快。先看下Redis的數據結構&內部編碼圖:

Redis為何速度這么快

SDS簡單動態字符串

Redis為何速度這么快

struct sdshdr { //SDS簡單動態字符串
    int len;    //記錄buf中已使用的空間
    int free;   // buf中空閑空間長度
    char buf[]; //存儲的實際內容
}
字符串長度處理

在C語言中,要獲取撿田螺的小男孩這個字符串的長度,需要從頭開始遍歷,復雜度為O(n); 在Redis中, 已經有一個len字段記錄當前字符串的長度啦,直接獲取即可,時間復雜度為O(1)。

減少內存重新分配的次數

在C語言中,修改一個字符串,需要重新分配內存,修改越頻繁,內存分配就越頻繁,而分配內存是會消耗性能的。而在Redis中,SDS提供了兩種優化策略:空間預分配和惰性空間釋放。

空間預分配

當SDS簡單動態字符串修改和空間擴充時,除了分配必需的內存空間,還會額外分配未使用的空間。分配規則是醬紫的:

  • SDS修改后,len的長度小于1M,那么將額外分配與len相同長度的未使用空間。比如len=100,重新分配后,buf 的實際長度會變為100(已使用空間)+100(額外空間)+1(空字符)=201。

  • SDS修改后, len長度大于1M,那么程序將分配1M的未使用空間。

惰性空間釋放

當SDS縮短時,不是回收多余的內存空間,而是用free記錄下多余的空間。后續再有修改操作,直接使用free中的空間,減少內存分配。

哈希

Redis 作為一個K-V的內存數據庫,它使用用一張全局的哈希來保存所有的鍵值對。這張哈希表,有多個哈希桶組成,哈希桶中的entry元素保存了*key*value指針,其中*key指向了實際的鍵,*value指向了實際的值。

Redis為何速度這么快

哈希表查找速率很快的,有點類似于Java中的HashMap,它讓我們在O(1) 的時間復雜度快速找到鍵值對。首先通過key計算哈希值,找到對應的哈希桶位置,然后定位到entry,在entry找到對應的數據。

有些小伙伴可能會有疑問:你往哈希表中寫入大量數據時,不是會遇到哈希沖突問題嘛,那效率就會降下來啦。

哈希沖突: 通過不同的key,計算出一樣的哈希值,導致落在同一個哈希桶中。

Redis為了解決哈希沖突,采用了鏈式哈希。鏈式哈希是指同一個哈希桶中,多個元素用一個鏈表來保存,它們之間依次用指針連接。

Redis為何速度這么快

有些小伙伴可能還會有疑問:哈希沖突鏈上的元素只能通過指針逐一查找再操作。當往哈希表插入數據很多,沖突也會越多,沖突鏈表就會越長,那查詢效率就會降低了。

為了保持高效,Redis 會對哈希表做rehash操作,也就是增加哈希桶,減少沖突。為了rehash更高效,Redis還默認使用了兩個全局哈希表,一個用于當前使用,稱為主哈希表,一個用于擴容,稱為備用哈希表。

跳躍表

跳躍表是Redis特有的數據結構,它其實就是在鏈表的基礎上,增加多級索引,以提高查找效率。跳躍表的簡單原理圖如下:

Redis為何速度這么快

  • 每一層都有一條有序的鏈表,最底層的鏈表包含了所有的元素。

  • 跳躍表支持平均 O(logN),最壞 O(N)復雜度的節點查找,還可以通過順序性操作批量處理節點。

壓縮列表ziplist

壓縮列表ziplist是列表鍵和字典鍵的的底層實現之一。它是由一系列特殊編碼的內存塊構成的列表, 一個ziplist可以包含多個entry, 每個entry可以保存一個長度受限的字符數組或者整數,如下:

Redis為何速度這么快

  • zlbytes :記錄整個壓縮列表占用的內存字節數

  • zltail: 尾節點至起始節點的偏移量

  • zllen : 記錄整個壓縮列表包含的節點數量

  • entryX: 壓縮列表包含的各個節點

  • zlend : 特殊值0xFF(十進制255),用于標記壓縮列表末端

由于內存是連續分配的,所以遍歷速度很快。。

合理的數據編碼

Redis支持多種數據基本類型,每種基本類型對應不同的數據結構,每種數據結構對應不一樣的編碼。為了提高性能,Redis設計者總結出,數據結構最適合的編碼搭配。

Redis是使用對象(redisObject)來表示數據庫中的鍵值,當我們在 Redis 中創建一個鍵值對時,至少創建兩個對象,一個對象是用做鍵值對的鍵對象,另一個是鍵值對的值對象。

//關注公眾號:撿田螺的小男孩
typedef struct redisObject{
    //類型
   unsigned type:4;
   //編碼
   unsigned encoding:4;
   //指向底層數據結構的指針
   void *ptr;
    //...
 }robj;

redisObject中,type 對應的是對象類型,包含String對象、List對象、Hash對象、Set對象、zset對象。encoding 對應的是編碼。

  • String:如果存儲數字的話,是用int類型的編碼;如果存儲非數字,小于等于39字節的字符串,是embstr;大于39個字節,則是raw編碼。

  • List:如果列表的元素個數小于512個,列表每個元素的值都小于64字節(默認),使用ziplist編碼,否則使用linkedlist編碼

  • Hash:哈希類型元素個數小于512個,所有值小于64字節的話,使用ziplist編碼,否則使用hashtable編碼。

  • Set:如果集合中的元素都是整數且元素個數小于512個,使用intset編碼,否則使用hashtable編碼。

  • Zset:當有序集合的元素個數小于128個,每個元素的值小于64字節時,使用ziplist編碼,否則使用skiplist(跳躍表)編碼

合理的線程模型

單線程模型:避免了上下文切換

Redis是單線程的,其實是指Redis的網絡IO和鍵值對讀寫是由一個線程來完成的。但Redis的其他功能,比如持久化、異步刪除、集群數據同步等等,實際是由額外的線程執行的。

Redis的單線程模型,避免了CPU不必要的上下文切換競爭鎖的消耗。也正因為是單線程,如果某個命令執行過長(如hgetall命令),會造成阻塞。Redis是面向快速執行場景的內存數據庫,所以要慎用如lrange和smembers、hgetall等命令。

什么是上下文切換?舉個粟子:

  • 比如你在看一本英文小說,你看到某一頁,發現有個單詞不會讀,你加了個書簽,然后去查字典。查完字典后,你回來從書簽那里繼續開始讀,這個流程就很舒暢。

  • 如果你一個人讀這本書,肯定沒啥問題。但是如果你去查字典的時候,別的小伙伴翻了一下你的書,然后溜了。你再回來看的時候,發現書不是你看的那一頁了,你得花時間找到你的那一頁。

  • 一本書,你一個人怎么看怎么打標簽都沒事,但是人多了翻來翻去,這本書各種標記就很亂了。可能這個解釋很粗糙,但是道理應該是一樣的。

Redis為何速度這么快

I/O 多路復用

什么是I/O多路復用?

  • I/O :網絡 I/O

  • 多路 :多個網絡連接

  • 復用:復用同一個線程。

  • IO多路復用其實就是一種同步IO模型,它實現了一個線程可以監視多個文件句柄;一旦某個文件句柄就緒,就能夠通知應用程序進行相應的讀寫操作;而沒有文件句柄就緒時,就會阻塞應用程序,交出cpu。

Redis為何速度這么快

多路I/O復用技術可以讓單個線程高效的處理多個連接請求,而Redis使用用epoll作為I/O多路復用技術的實現。并且Redis自身的事件處理模型將epoll中的連接、讀寫、關閉都轉換為事件,不在網絡I/O上浪費過多的時間。

虛擬內存機制

Redis直接自己構建了VM機制 ,不會像一般的系統會調用系統函數處理,會浪費一定的時間去移動和請求。

Redis的虛擬內存機制是啥呢?

虛擬內存機制就是暫時把不經常訪問的數據(冷數據)從內存交換到磁盤中,從而騰出寶貴的內存空間用于其它需要訪問的數據(熱數據)。通過VM功能可以實現冷熱數據分離,使熱數據仍在內存中、冷數據保存到磁盤。這樣就可以避免因為內存不足而造成訪問速度下降的問題。

以上是“Redis為何速度這么快”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

宁安市| 平南县| 栾城县| 连州市| 汾阳市| 花垣县| 游戏| 大宁县| 衡阳市| 汝城县| 雅江县| 恩平市| 水富县| 攀枝花市| 宝鸡市| 华亭县| 吴川市| 双牌县| 寻甸| 巧家县| 逊克县| 拉孜县| 罗田县| 河曲县| 五指山市| 琼结县| 大连市| 拉孜县| 蒲城县| 莒南县| 疏附县| 新巴尔虎左旗| 蓝山县| 海晏县| 平陆县| 七台河市| 沾化县| 屏边| 吴桥县| 林西县| 桓台县|