日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

极客时间 Redis核心技术与实战 笔记(基础篇)

發布時間:2023/12/14 数据库 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 极客时间 Redis核心技术与实战 笔记(基础篇) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Redis 概覽

Redis 知識全景圖

Redis 問題畫像圖

基礎篇

基本架構

數據結構

數據類型和底層數據結構映射關系

全局哈希表


鏈式哈希解決哈希沖突

漸進式 rehash

不同數據結構查找操作的時間復雜度

不同操作的復雜度

  • 單元素操作是基礎;
  • 范圍操作非常耗時;
  • 統計操作通常高效;
  • 例外情況只有幾個。

第一,單元素操作,是指每一種集合類型對單個數據實現的增刪改查操作。例如,Hash 類型的 HGET、HSET 和 HDEL,Set 類型的 SADD、SREM、SRANDMEMBER 等。這些操作的復雜度由集合采用的數據結構決定,例如,HGET、HSET 和 HDEL 是對哈希表做操作,所以它們的復雜度都是 O(1);Set 類型用哈希表作為底層數據結構時,它的 SADD、SREM、SRANDMEMBER 復雜度也是 O(1)。這里,有個地方你需要注意一下,集合類型支持同時對多個元素進行增刪改查,例如 Hash 類型的 HMGET 和 HMSET,Set 類型的 SADD 也支持同時增加多個元素。此時,這些操作的復雜度,就是由單個元素操作復雜度和元素個數決定的。例如,HMSET 增加 M 個元素時,復雜度就從 O(1) 變成 O(M) 了。

第二,范圍操作,是指集合類型中的遍歷操作,可以返回集合中的所有數據,比如 Hash 類型的 HGETALL 和 Set 類型的 SMEMBERS,或者返回一個范圍內的部分數據,比如 List 類型的 LRANGE 和 ZSet 類型的 ZRANGE。這類操作的復雜度一般是 O(N),比較耗時,我們應該盡量避免

不過,Redis 從 2.8 版本開始提供了 SCAN 系列操作(包括 HSCAN,SSCAN 和 ZSCAN),這類操作實現了漸進式遍歷,每次只返回有限數量的數據。這樣一來,相比于 HGETALL、SMEMBERS 這類操作來說,就避免了一次性返回所有元素而導致的 Redis 阻塞。

第三,統計操作,是指集合類型對集合中所有元素個數的記錄,例如 LLEN 和 SCARD。這類操作復雜度只有 O(1),這是因為當集合類型采用壓縮列表、雙向鏈表、整數數組這些數據結構時,這些結構中專門記錄了元素的個數統計,因此可以高效地完成相關操作。

第四,例外情況,是指某些數據結構的特殊記錄,例如壓縮列表和雙向鏈表都會記錄表頭和表尾的偏移量。這樣一來,對于 List 類型的 LPOP、RPOP、LPUSH、RPUSH 這四個操作來說,它們是在列表的頭尾增刪元素,這就可以通過偏移量直接定位,所以它們的復雜度也只有 O(1),可以實現快速操作。

高性能IO模型

通常說,Redis 是單線程,主要是指 Redis 的網絡 IO 和鍵值對讀寫是由一個線程來完成的,這也是 Redis 對外提供鍵值存儲服務的主要流程。但 Redis 的其他功能,比如持久化、異步刪除、集群數據同步等,其實是由額外的線程執行的。

Redis 為什么用單線程?

多線程存在開銷

  • 多線程編程模式面臨共享資源的并發訪問控制問題。
  • 線程上下文切換的開銷
  • 單線程 Redis 為什么那么快?

    多路復用機制

    基本 IO 模型與阻塞點


    在這里的網絡 IO 操作中,有潛在的阻塞點,分別是 accept() 和 recv()。當 Redis 監聽到一個客戶端有連接請求,但一直未能成功建立起連接時,會阻塞在 accept() 函數這里,導致其他客戶端無法和 Redis 建立連接。類似的,當 Redis 通過 recv() 從一個客戶端讀取數據時,如果數據一直沒有到達,Redis 也會一直阻塞在 recv()。

    這就導致 Redis 整個線程阻塞,無法處理其他客戶端請求,效率很低。不過,幸運的是,socket 網絡模型本身支持非阻塞模式。

    非阻塞模式

    在 socket 模型中,不同操作調用后會返回不同的套接字類型。socket() 方法會返回主動套接字,然后調用 listen() 方法,將主動套接字轉化為監聽套接字,此時,可以監聽來自客戶端的連接請求。最后,調用 accept() 方法接收到達的客戶端連接,并返回已連接套接字。

    針對監聽套接字,我們可以設置非阻塞模式:當 Redis 調用 accept() 但一直未有連接請求到達時,Redis 線程可以返回處理其他操作,而不用一直等待。但是,你要注意的是,調用 accept() 時,已經存在監聽套接字了。

    雖然 Redis 線程可以不用繼續等待,但是總得有機制繼續在監聽套接字上等待后續連接請求,并在有請求時通知 Redis。

    類似的,我們也可以針對已連接套接字設置非阻塞模式:Redis 調用 recv() 后,如果已連接套接字上一直沒有數據到達,Redis 線程同樣可以返回處理其他操作。我們也需要有機制繼續監聽該已連接套接字,并在有數據達到時通知 Redis。

    這樣才能保證 Redis 線程,既不會像基本 IO 模型中一直在阻塞點等待,也不會導致 Redis 無法處理實際到達的連接請求或數據。

    到此,Linux 中的 IO 多路復用機制就要登場了。

    基于多路復用的高性能 I/O 模型

    Linux 中的 IO 多路復用機制是指一個線程處理多個 IO 流,就是我們經常聽到的 select/epoll 機制。簡單來說,在 Redis 只運行單線程的情況下,該機制允許內核中,同時存在多個監聽套接字和已連接套接字

    下圖就是基于多路復用的 Redis IO 模型。圖中的多個 FD 就是剛才所說的多個套接字。Redis 網絡框架調用 epoll 機制,讓內核監聽這些套接字。此時,Redis 線程不會阻塞在某一個特定的監聽或已連接套接字上,也就是說,不會阻塞在某一個特定的客戶端請求處理上。正因為此,Redis 可以同時和多個客戶端連接并處理請求,從而提升并發性。

    為了在請求到達時能通知到 Redis 線程,select/epoll 提供了基于事件的回調機制即針對不同事件的發生,調用相應的處理函數

    那么,回調機制是怎么工作的呢?其實,select/epoll 一旦監測到 FD 上有請求到達時,就會觸發相應的事件。

    這些事件會被放進一個事件隊列,Redis 單線程對該事件隊列不斷進行處理。這樣一來,Redis 無需一直輪詢是否有請求實際發生,這就可以避免造成 CPU 資源浪費。同時,Redis 在對事件隊列中的事件進行處理時,會調用相應的處理函數,這就實現了基于事件的回調。因為 Redis 一直在對事件隊列進行處理,所以能及時響應客戶端請求,提升 Redis 的響應性能。

    持久化

    參考:極客時間 Redis核心技術與實戰 筆記(基礎篇 AOF和RDB)

    主從同步、哨兵機制、切片集群

    參考:極客時間 Redis核心技術與實戰 筆記(基礎篇 集群)

    總結

    以上是生活随笔為你收集整理的极客时间 Redis核心技术与实战 笔记(基础篇)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。