首頁 資料庫 Redis 為什麼Redis是單線程,為什麼這麼快?

為什麼Redis是單線程,為什麼這麼快?

May 12, 2021 am 10:57 AM
redis 單執行緒

為什麼Redis是單線程,為什麼這麼快?

近乎所有與Java相關的面試都會問到快取的問題,基礎一點的會問到什麼是“二八定律”、什麼是“熱數據和冷數據”,複雜一點的會問到快取雪崩、快取穿透、快取預熱、快取更新、快取降級等問題,這些看似不常見的概念,都與我們的快取伺服器相關,一般常用的快取伺服器有Redis、Memcached等,而筆者目前最常用的也只有Redis這一種。

如果你在以前面試的時候還沒有遇到過面試官問你《為什麼說Redis是單線程的以及Redis為什麼這麼快! 》,那你看到這篇文章的時候,你應該覺得是一件很幸運的事!如果你剛好是一位高逼格的面試官,你也可以拿這題去面試對面「望穿秋水」般的小夥伴,測試一下他的掌握程度。

好啦!步入正題!我們先探討Redis是什麼,Redis為什麼這麼快、然後在探討為什麼Redis是單線的? 【相關推薦:Redis影片教學

#一.Redis簡介

Redis是一個開源的記憶體中的資料結構儲存系統,它可用作:資料庫、快取和訊息中間件。

它支援多種類型的資料結構,如字串(String),雜湊(Hash),列表(List),集合(Set),有序集合(Sorted Set或是ZSet)與範圍查詢,Bitmaps,Hyperloglogs 和地理空間(Geospatial)索引半徑查詢。其中常見的資料結構類型有:String、List、Set、Hash、ZSet這5種。

Redis 內建了複製(Replication),LUA腳本(Lua scripting), LRU驅動事件(LRU eviction),事務(Transactions) 和不同級別的磁碟持久化(Persistence),並通過Redis哨兵(Sentinel )和自動分區(Cluster)提供高可用性(High Availability)。

Redis也提供了持久化的選項,這些選項可以讓使用者將自己的資料儲存到磁碟上面進行儲存。根據實際情況,可以每隔一定時間將資料集匯出到磁碟(快照),或是追加到命令日誌中(AOF只追加檔案),他會在執行寫入命令時,將被執行的寫入命令複製到硬碟裡面。您也可以關閉持久化功能,將Redis作為一個高效的網路的快取資料功能。

Redis不使用表,他的資料庫不會預先定義或強制去要求使用者對Redis儲存的不同資料進行關聯。

資料庫的工作模式以儲存方式可分為:硬碟資料庫和記憶體資料庫。 Redis 將資料儲存在記憶體裡面,讀寫資料的時候都不會受到硬碟 I/O 速度的限制,所以速度極快。

(1)硬碟資料庫的工作模式:

為什麼Redis是單線程,為什麼這麼快?

(2)記憶體資料庫的工作模式:

為什麼Redis是單線程,為什麼這麼快?

看完上述的描述,對於一些常見的Redis相關的面試題,是否有所認識了,例如:什麼是Redis、Redis常見的資料結構類型有哪些、Redis是如何進行持久化的等。

二.Redis到底有多快?

Redis採用的是基於記憶體的採用的是單進程單執行緒模型的KV 資料庫,由C語言編寫,官方提供的資料是可以達到100000 的QPS(每秒內查詢次數) 。

這個資料不比採用單一行程多執行緒的同樣基於記憶體的 KV 資料庫 Memcached 差!

為什麼Redis是單線程,為什麼這麼快?

橫軸是連接數,縱軸是QPS。此時,這張圖反映了一個數量級,希望大家在面試的時候可以正確的描述出來,不要問你的時候,你回答的數量級相差甚遠!

三.Redis為什麼這麼快?

1、完全基於內存,絕大部分請求是純粹的內存操作,而且非常快速。資料存在記憶體中,類似HashMap,HashMap的優勢就是查找和操作的時間複雜度都是O(1);

2、資料結構簡單,對資料操作也簡單,Redis中的資料結構是專門進行設計的;

3、採用單線程,避免了不必要的上下文切換和競爭條件,也不存在多進程或者多線程導致的切換而消耗CPU,不用去考慮各種鎖的問題,不存在加鎖釋放鎖定操作,沒有因為可能出現死鎖而導致的效能消耗;

4、使用多路I/O復用模型,非阻塞IO;

5.使用底層模型不同,它們之間底層實現方式以及與客戶端之間通信的應用協議不一樣,Redis直接自己構建了VM 機制,因為一般的系統調用系統函數的話,會浪費一定的時間去移動和請求;

以上幾點都比較好理解,下邊我們針對多路I/O 復用模型進行簡單的探討:

(1)多路I/O 復用模型

多路I/O復用模型是利用select、poll、epoll 可以同時監察多個流的I/O 事件的能力,在空閒的時候,會把當前線程阻塞掉,當有一個或多個流有I /O 事件時,就從阻塞態中喚醒,於是程式就會輪詢一遍所有的流(epoll 是只輪詢那些真正發出了事件的流),並且只依次順序的處理就緒的流,這種做法就避免了大量的無用操作。

這裡「多路」指的是多個網路連接,「重複使用」指的是複用同一個執行緒。

採用多路I/O 復用技術可以讓單一執行緒高效的處理多個連線請求(盡量減少網路IO 的時間消耗),且Redis 在記憶體中操作資料的速度非常快,也就是說記憶體內的操作不會成為影響Redis效能的瓶頸,主要由以上幾點造就了Redis 具有很高的吞吐量。

四.那為什麼Redis是單執行緒的?

我們首先要明白,上邊的種種分析,都是為了營造一個Redis很快的氛圍!官方FAQ表示,因為Redis是基於記憶體的操作,CPU不是Redis的瓶頸,Redis的瓶頸最有可能是機器記憶體的大小或網路頻寬。既然單線程容易實現,而且CPU不會成為瓶頸,那就順理成章地採用單線程的方案了(畢竟採用多線程會有很多麻煩!)。

看到這裡,你可能會氣哭!本來以為會有什麼重大的技術要點才使得Redis使用單線程就可以這麼快,沒想到就是一句官方看似糊弄我們的回答!但是,我們已經可以很清楚的解釋了為什麼Redis這麼快,並且正是由於在單線程模式的情況下已經很快了,就沒有必要在使用多線程了!

但是,我們使用單執行緒的方式是無法發揮多核心CPU 效能,不過我們可以透過在單機開啟多個Redis 實例來完善!

警告1:這裡我們一直在強調的單線程,只是在處理我們的網路請求的時候只有一個線程來處理,一個正式的Redis Server運行的時候肯定是不止一個線程的,這裡需要大家明確的注意一下!例如Redis進行持久化的時候會以子進程或子執行緒的方式執行(具體是子執行緒還是子程序待讀者深入研究);例如我在測試伺服器上查看Redis進程,然後找到該進程下的執行緒:

為什麼Redis是單線程,為什麼這麼快?

ps指令的「-T」參數表示顯示執行緒(Show threads, possibly with SPID column.)「SID」欄表示執行緒ID,而「CMD」欄則顯示了線程名稱。

警告2:在上圖中FAQ中的最後一段,表述了從Redis 4.0版本開始會支援多執行緒的方式,但是,只是在某一些操作上進行多執行緒的操作!所以該篇文章在以後的版本中是否還是單線程的方式需要讀者考證!

#五.注意點

1、我們知道Redis是用」單執行緒-多路復用IO模型」來實現高效能的記憶體資料服務的,這種機制避免了使用鎖,但是同時這種機制在進行sunion之類的比較耗時的指令時會使redis的並發下降。

因為是單一線程,所以同一時刻只有一個操作在進行,所以,耗時的命令會導致並發的下降,不只是讀並發,寫並發也會下降。而單一執行緒也只能用到一個CPU核心,所以可以在同一個多核心的伺服器中,可以啟動多個實例,組成master-master或master-slave的形式,耗時的讀取指令可以完全在slave進行。

需要改的redis.conf項目:

pidfile /var/run/redis/redis_6377.pid #pidfile要加上連接埠號碼

#port 6377 #這個是必須改的

logfile /var/log/redis/redis_6377.log #logfile的名稱也加上連接埠號碼

dbfilename dump_6377.rdb #rdbfile也加上連接埠號碼

2、「我們不能任由作業系統負載平衡,因為我們自己更了解自己的程序,所以,我們可以手動地為其分配CPU核,而不會過多地佔用CPU,或是讓我們關鍵進程和一堆別的進程擠在一起。」

CPU 是一個重要的影響因素,由於是單線程模型,Redis 更喜歡大緩存快速CPU, 而不是多核心。

在多核心 CPU 伺服器上面,Redis 的效能也依賴NUMA 配置和處理器綁定位置。最明顯的影響是 redis-benchmark 會隨機使用CPU核心。為了獲得精準的結果,需要使用固定處理器工具(在 Linux 上可以使用 taskset)。最有效的辦法是將客戶端和服務端分離到兩個不同的 CPU 來高校使用三級快取。

六.延伸

以下也是你該知道的幾種模型,祝你的面試一臂之力!

1、單一進程多執行緒模型:MySQL、Memcached、Oracle(Windows版本);

2、多進程模型:Oracle(Linux版本);

3、Nginx有兩類進程,一類稱為Master進程(相當於管理進程),另一類稱為Worker進程(實際工作進程)。啟動方式有兩種:

(1)單一進程啟動:此時系統中僅有一個進程,該進程既扮演Master進程的角色,也扮演Worker進程的角色。

(2)多進程啟動:此時系統有且只有一個Master進程,至少有一個Worker進程工作。

(3)Master流程主要進行一些全域性的初始化工作和管理Worker的工作;事件處理是在Worker中進行的。

為什麼Redis是單線程,為什麼這麼快?

更多程式相關知識,請造訪:程式設計入門! !

以上是為什麼Redis是單線程,為什麼這麼快?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

redis集群模式怎麼搭建 redis集群模式怎麼搭建 Apr 10, 2025 pm 10:15 PM

Redis集群模式通過分片將Redis實例部署到多個服務器,提高可擴展性和可用性。搭建步驟如下:創建奇數個Redis實例,端口不同;創建3個sentinel實例,監控Redis實例並進行故障轉移;配置sentinel配置文件,添加監控Redis實例信息和故障轉移設置;配置Redis實例配置文件,啟用集群模式並指定集群信息文件路徑;創建nodes.conf文件,包含各Redis實例的信息;啟動集群,執行create命令創建集群並指定副本數量;登錄集群執行CLUSTER INFO命令驗證集群狀態;使

redis數據怎麼清空 redis數據怎麼清空 Apr 10, 2025 pm 10:06 PM

如何清空 Redis 數據:使用 FLUSHALL 命令清除所有鍵值。使用 FLUSHDB 命令清除當前選定數據庫的鍵值。使用 SELECT 切換數據庫,再使用 FLUSHDB 清除多個數據庫。使用 DEL 命令刪除特定鍵。使用 redis-cli 工具清空數據。

redis怎麼讀取隊列 redis怎麼讀取隊列 Apr 10, 2025 pm 10:12 PM

要從 Redis 讀取隊列,需要獲取隊列名稱、使用 LPOP 命令讀取元素,並處理空隊列。具體步驟如下:獲取隊列名稱:以 "queue:" 前綴命名,如 "queue:my-queue"。使用 LPOP 命令:從隊列頭部彈出元素並返回其值,如 LPOP queue:my-queue。處理空隊列:如果隊列為空,LPOP 返回 nil,可先檢查隊列是否存在再讀取元素。

centos redis如何配置Lua腳本執行時間 centos redis如何配置Lua腳本執行時間 Apr 14, 2025 pm 02:12 PM

在CentOS系統上,您可以通過修改Redis配置文件或使用Redis命令來限制Lua腳本的執行時間,從而防止惡意腳本佔用過多資源。方法一:修改Redis配置文件定位Redis配置文件:Redis配置文件通常位於/etc/redis/redis.conf。編輯配置文件:使用文本編輯器(例如vi或nano)打開配置文件:sudovi/etc/redis/redis.conf設置Lua腳本執行時間限制:在配置文件中添加或修改以下行,設置Lua腳本的最大執行時間(單位:毫秒)

redis指令怎麼用 redis指令怎麼用 Apr 10, 2025 pm 08:45 PM

使用 Redis 指令需要以下步驟:打開 Redis 客戶端。輸入指令(動詞 鍵 值)。提供所需參數(因指令而異)。按 Enter 執行指令。 Redis 返迴響應,指示操作結果(通常為 OK 或 -ERR)。

redis怎麼使用鎖 redis怎麼使用鎖 Apr 10, 2025 pm 08:39 PM

使用Redis進行鎖操作需要通過SETNX命令獲取鎖,然後使用EXPIRE命令設置過期時間。具體步驟為:(1) 使用SETNX命令嘗試設置一個鍵值對;(2) 使用EXPIRE命令為鎖設置過期時間;(3) 當不再需要鎖時,使用DEL命令刪除該鎖。

redis命令行怎麼用 redis命令行怎麼用 Apr 10, 2025 pm 10:18 PM

使用 Redis 命令行工具 (redis-cli) 可通過以下步驟管理和操作 Redis:連接到服務器,指定地址和端口。使用命令名稱和參數向服務器發送命令。使用 HELP 命令查看特定命令的幫助信息。使用 QUIT 命令退出命令行工具。

redis過期策略怎麼設置 redis過期策略怎麼設置 Apr 10, 2025 pm 10:03 PM

Redis數據過期策略有兩種:定期刪除:定期掃描刪除過期鍵,可通過 expired-time-cap-remove-count、expired-time-cap-remove-delay 參數設置。惰性刪除:僅在讀取或寫入鍵時檢查刪除過期鍵,可通過 lazyfree-lazy-eviction、lazyfree-lazy-expire、lazyfree-lazy-user-del 參數設置。

See all articles