進程同步之信號量機制

信號量機制

信號量機制是一種用于進程同步和互斥的基本工具,特別是在并發編程中,廣泛用于控制對共享資源的訪問,避免數據競爭和死鎖等問題。信號量機制由荷蘭計算機科學家Edsger Dijkstra在1965年提出,并在操作系統的進程同步中發揮了重要作用。經歷了整型信號量、 記錄型信號量、AND型信號量和信號量集。

1)整型信號量

Dijkstra最初提出的信號量為表示臨界資源的一個整型量S。S>0時表示有S個資源可用;S<=0表示該資源已被分配完。另外,定義了兩個原語wait(S)和signal(S)用于資源的分配和釋放,這兩個原語的C語言偽代碼如下:

?wait(int &S){while (S<=0);S=S-1;}?signal(int &S){S=S+1;}

wait原語(也叫作P操作)首先通過while循環測試是否S<=0,如果是則繼續等待,否則將S的值減1,資源分配成功,可以進入臨界區訪問。 signal原語(也叫做V操作)只有一條語句,即將S值加1,表示釋放1個資源。

示例:使用整型信號量進行互斥控制

// 信號量 S,初始化為1,表示有1個資源
int S = 1;// wait原語(P操作)
void wait(int *S) {while (*S <= 0);  *S = *S - 1; 
}// signal原語(V操作)
void signal(int *S) {*S = *S + 1; 
}// 臨界區函數
void *p1(void *p) {wait(&S); printf("線程1進入臨界區\n");signal(&S);  return NULL;
}void *p2(void *p) {wait(&S); printf("線程2進入臨界區\n");signal(&S); return NULL;
}

解釋:

信號量 S:它是一個整型變量,表示可用的資源數量,初始化為1,表示有一個資源可以分配。

wait 操作(P操作): wait操作會檢查信號量S的值。如果 S小于等于0,表示資源不可用,當前線程將進入等待狀態。如果 S 大于0,表示有資源可用,信號量 S會減1,表示資源已被分配給當前線程,線程可以訪問共享資源。

signal操作(V操作): signal操作會釋放一個資源,信號量 S增加1。如果有等待的線程,它們會根據信號量的值重新獲得資源。

線程 p1和 p2: 這兩個線程都訪問共享資源,每個線程在進入臨界區前都調用 wait(S)請求資源,執行完任務后調用 signal(S) 釋放資源。 由于信號量的控制,線程 p1和 p2 會互斥地訪問共享資源。

2.)記錄型信號量

為了解決整型信號量中的“忙等”問題,即當沒有資源可用時,進程不斷等待而不釋放CPU,可以采用記錄型信號量(semaphore)。在這種信號量機制中,我們引入了阻塞進程隊列來管理等待資源的進程。記錄型信號量由一個結構體組成,包含兩個成員:整型變量value和進程阻塞隊列Lvalue表示當前可用的資源數量,當value > 0時,表示有可用資源;當value < 0時,value的絕對值表示正在等待資源的進程數量。

此外,L是一個進程隊列,包含那些因無法獲取資源而被阻塞的進程。當資源可用時,這些被阻塞的進程可以被喚醒,繼續執行。因此,記錄型信號量通過引入阻塞隊列來避免了“忙等”,實現了進程的高效調度。

偽代碼如下:

typedef struct{int value;struct process_control_block *L
}semaphore;
//value>O時,value為資源可用數目
//value<O,|value|為已阻塞進程的數目
//L為阻塞進程隊列首指針wait(int &S){S.value = S.value -1;if (S.value<0) block(S.L);
}
//阻塞到隊尾,
//程序計數器定位在Wait之后signal(int &S){S.value = S.value+1;if(S.value<=0) wake(S.L);//喚醒隊首
}

示例:

#include <stdio.h>
#include <pthread.h>typedef struct process_control_block {pthread_t thread;  // 阻塞進程的線程IDstruct process_control_block *next;  // 指向下一個進程
} PCB;typedef struct {int value;  // 信號量的值,表示資源的數量PCB *L;     // 阻塞進程隊列的頭指針
} semaphore;semaphore S = {1, NULL};  // 初始化信號量,資源數量為1// 模擬進程被阻塞
void block(PCB *L) {PCB *new_pcb = (PCB *)malloc(sizeof(PCB));new_pcb->thread = pthread_self();  // 獲取當前進程的線程IDnew_pcb->next = NULL;// 將新進程加入到阻塞隊列的尾部if (L == NULL) {L = new_pcb;} else {PCB *temp = L;while (temp->next != NULL) {temp = temp->next;}temp->next = new_pcb;}// 阻塞進程的代碼邏輯printf("進程 %lu 被阻塞。\n", pthread_self());pthread_exit(NULL);  // 當前線程掛起
}// 模擬進程被喚醒
void wake(PCB *L) {if (L != NULL) {PCB *temp = L;L = L->next;  // 喚醒隊列中的第一個進程printf("進程 %lu 被喚醒。\n", temp->thread);free(temp);  // 釋放喚醒的進程}
}// wait原語
void wait(semaphore *S) {S->value = S->value - 1;  // 請求資源,信號量值減1if (S->value < 0) {block(S->L);  // 資源不足,進程被阻塞}
}// signal原語
void signal(semaphore *S) {S->value = S->value + 1;  // 釋放資源,信號量值加1if (S->value <= 0) {wake(S->L);  // 喚醒阻塞隊列中的一個進程}
}// 線程函數
void *process(void *param) {printf("進程 %lu 正在嘗試進入臨界區。\n", pthread_self());wait(&S);  // 請求資源printf("進程 %lu 已進入臨界區。\n", pthread_self());signal(&S);  // 釋放資源return NULL;
}int main() {pthread_t t1, t2;// 創建兩個線程pthread_create(&t1, NULL, process, NULL);pthread_create(&t2, NULL, process, NULL);// 等待線程結束pthread_join(t1, NULL);pthread_join(t2, NULL);return 0;
}
3)AND型信號量

記錄型信號量一次只能申請一種資源,而當一個進程需要同時獲取多種臨界資源時,若資源申請順序不當,很容易導致死鎖的發生。為了解決這個問題,引入了AND信號量,它允許一次申請多種資源,每種資源申請一個單位。只有當所有申請的資源都滿足要求時,才會全部分配,否則一種資源也不會分配。

AND型信號量通過SwaitSsignal兩個原語進行資源的申請和釋放。Swait的參數為涉及的n種資源的信號量,分別定義為S_1S_n。在Swait操作中,首先檢查n種資源的可用數量(即信號量的value)是否都大于或等于1。如果滿足條件,則將所有信號量的value值減1,表示資源分配成功;如果不滿足條件,則從S_1S_n中查找第一個value值小于1的信號量S_i,并將當前進程阻塞到S_i的阻塞隊列S_i.L中。此時,程序的計數器將重新定位到Swait操作的起點,等待資源滿足條件后繼續執行。

偽代碼如下:

// Swait原語:請求多個資源
void Swait(semaphore S_1, semaphore S_2, ..., semaphore S_n) {// 判斷所有信號量的value是否都大于等于1if (S_1.value >= 1 && S_2.value >= 1 && ... && S_n.value >= 1) {// 如果所有資源都可用,則將每個資源的value值減1for (int i = 1; i <= n; i++) {S_i.value = S_i.value - 1;}} else {// 否則,找到第一個不可用的資源for (int i = 1; i <= n && S_i.value >= 1; i++);// 將進程阻塞到第一個不可用資源的阻塞隊列中block(S_i.L);// 程序計數器重新定位到Swait操作的起點,等待資源可用}
}// Ssignal原語:釋放多個資源
void Ssignal(semaphore S_1, semaphore S_2, ..., semaphore S_n) {// 釋放每個資源并將value加1for (int i = 1; i <= n; i++) {S_i.value = S_i.value + 1;// 如果該資源的value小于等于0,表示有阻塞的進程,需要喚醒if (S_i.value <= 0) {wake(S_i.L);}}
}

示例:

#include <stdio.h>
#include <pthread.h>typedef struct process_control_block {pthread_t thread;  // 阻塞進程的線程IDstruct process_control_block *next;  // 指向下一個進程
} PCB;typedef struct {int value;  // 信號量的值,表示資源的數量PCB *L;     // 阻塞進程隊列的頭指針
} semaphore;semaphore S1 = {1, NULL};  // 資源1,初始值為1
semaphore S2 = {1, NULL};  // 資源2,初始值為1
semaphore S3 = {1, NULL};  // 資源3,初始值為1// 模擬進程被阻塞
void block(PCB *L) {PCB *new_pcb = (PCB *)malloc(sizeof(PCB));new_pcb->thread = pthread_self();  // 獲取當前進程的線程IDnew_pcb->next = NULL;// 將新進程加入到阻塞隊列的尾部if (L == NULL) {L = new_pcb;} else {PCB *temp = L;while (temp->next != NULL) {temp = temp->next;}temp->next = new_pcb;}// 阻塞進程的代碼邏輯printf("進程 %lu 被阻塞。\n", pthread_self());pthread_exit(NULL);  // 當前線程掛起
}// 模擬進程被喚醒
void wake(PCB *L) {if (L != NULL) {PCB *temp = L;L = L->next;  // 喚醒隊列中的第一個進程printf("進程 %lu 被喚醒。\n", temp->thread);free(temp);  // 釋放喚醒的進程}
}// Swait原語:請求多個資源
void Swait(semaphore *S_1, semaphore *S_2, semaphore *S_3) {if (S_1->value >= 1 && S_2->value >= 1 && S_3->value >= 1) {// 如果所有資源都可用,則將資源的value值減1S_1->value--;S_2->value--;S_3->value--;printf("資源已分配給進程 %lu。\n", pthread_self());} else {// 否則,找到第一個不可用的資源if (S_1->value < 1) {block(S_1->L);  // 阻塞進程} else if (S_2->value < 1) {block(S_2->L);} else if (S_3->value < 1) {block(S_3->L);}}
}// Ssignal原語:釋放多個資源
void Ssignal(semaphore *S_1, semaphore *S_2, semaphore *S_3) {S_1->value++;S_2->value++;S_3->value++;printf("資源已被進程 %lu 釋放。\n", pthread_self());// 喚醒被阻塞的進程wake(S_1->L);wake(S_2->L);wake(S_3->L);
}// 線程函數
void *process(void *param) {printf("進程 %lu 正在嘗試請求資源。\n", pthread_self());Swait(&S1, &S2, &S3);  // 請求資源printf("進程 %lu 已進入臨界區。\n", pthread_self());Ssignal(&S1, &S2, &S3);  // 釋放資源return NULL;
}int main() {pthread_t t1, t2, t3;// 創建三個線程pthread_create(&t1, NULL, process, NULL);pthread_create(&t2, NULL, process, NULL);pthread_create(&t3, NULL, process, NULL);// 等待線程結束pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);return 0;
}
4)信號量集

當一個進程需要申請多種資源,每種資源需要多個單位,并且當資源的可用數量低于設定的下限時,不應進行資源分配。為便于軟件開發,AND型信號量機制進行了擴展,定義了信號量集。

信號量集的資源申請和釋放操作與AND型信號量相似,但參數的構成有所不同。具體來說,Swait操作的參數包括n種資源信號量S_i、每種資源的申請數量d_i以及資源分配的下限t_i的序列。在Swait中,首先判斷每種資源的可用數量(即信號量的value)是否大于或等于對應的下限t_i,如果滿足條件,則將每種資源的信號量value減去相應的d_i,表示分配成功;如果不滿足條件,則檢查所有資源的可用性,直到發現第一個不滿足條件的信號量S_i,然后將當前進程阻塞到該信號量S_i的阻塞隊列S_i.L中。此時,程序的計數器將重新定位到Swait操作的起點,等待資源滿足條件后繼續執行。

偽代碼如下:

// Swait原語:請求多個資源,指定每種資源的分配下限和申請數量
void Swait(semaphore S_1, int t_1, int d_1, ..., semaphore S_n, int t_n, int d_n) {// 判斷所有信號量的value是否都大于等于對應的分配下限if (S_1.value >= t_1 && S_2.value >= t_2 && ... && S_n.value >= t_n) {// 如果所有資源都滿足分配條件,則將資源的value值減去對應的申請數量for (int i = 1; i <= n; i++) {S_i.value = S_i.value - d_i;}} else {// 否則,找到第一個不滿足資源要求的信號量for (int i = 1; i <= n && S_i.value >= t_i; i++);// 將進程阻塞到不滿足條件的信號量的阻塞隊列中block(S_i.L);// 程序計數器重新定位到Swait操作的起點,等待資源可用}
}// Ssignal原語:釋放多個資源,指定每種資源的釋放數量
void Ssignal(semaphore S_1, int d_1, ..., semaphore S_n, int d_n) {// 釋放每個資源并將value加上對應的釋放數量for (int i = 1; i <= n; i++) {S_i.value = S_i.value + d_i;// 喚醒阻塞隊列中的進程if (S_i.value <= 0) {wake(S_i.L);}}
}

示例:

#include <stdio.h>
#include <pthread.h>typedef struct process_control_block {pthread_t thread;  // 阻塞進程的線程IDstruct process_control_block *next;  // 指向下一個進程
} PCB;typedef struct {int value;  // 信號量的值,表示資源的數量PCB *L;     // 阻塞進程隊列的頭指針
} semaphore;semaphore S1 = {5, NULL};  // 資源1,初始值為5
semaphore S2 = {5, NULL};  // 資源2,初始值為5
semaphore S3 = {5, NULL};  // 資源3,初始值為5// 模擬進程被阻塞
void block(PCB *L) {PCB *new_pcb = (PCB *)malloc(sizeof(PCB));new_pcb->thread = pthread_self();  // 獲取當前進程的線程IDnew_pcb->next = NULL;// 將新進程加入到阻塞隊列的尾部if (L == NULL) {L = new_pcb;} else {PCB *temp = L;while (temp->next != NULL) {temp = temp->next;}temp->next = new_pcb;}// 阻塞進程的代碼邏輯printf("進程 %lu 被阻塞。\n", pthread_self());pthread_exit(NULL);  // 當前線程掛起
}// 模擬進程被喚醒
void wake(PCB *L) {if (L != NULL) {PCB *temp = L;L = L->next;  // 喚醒隊列中的第一個進程printf("進程 %lu 被喚醒。\n", temp->thread);free(temp);  // 釋放喚醒的進程}
}// Swait原語:請求多個資源,指定每種資源的分配下限和申請數量
void Swait(semaphore *S_1, int t_1, int d_1, semaphore *S_2, int t_2, int d_2, semaphore *S_3, int t_3, int d_3) {// 判斷所有信號量的value是否都大于等于對應的分配下限if (S_1->value >= t_1 && S_2->value >= t_2 && S_3->value >= t_3) {// 如果所有資源都滿足分配條件,則將資源的value值減去對應的申請數量S_1->value -= d_1;S_2->value -= d_2;S_3->value -= d_3;printf("資源已分配給進程 %lu。\n", pthread_self());} else {// 否則,找到第一個不滿足資源要求的信號量if (S_1->value < t_1) {block(S_1->L);  // 阻塞進程} else if (S_2->value < t_2) {block(S_2->L);} else if (S_3->value < t_3) {block(S_3->L);}}
}// Ssignal原語:釋放多個資源,指定每種資源的釋放數量
void Ssignal(semaphore *S_1, int d_1, semaphore *S_2, int d_2, semaphore *S_3, int d_3) {S_1->value += d_1;S_2->value += d_2;S_3->value += d_3;printf("資源已被進程 %lu 釋放。\n", pthread_self());// 喚醒阻塞隊列中的進程wake(S_1->L);wake(S_2->L);wake(S_3->L);
}// 線程函數
void *process(void *param) {printf("進程 %lu 正在嘗試請求資源。\n", pthread_self());Swait(&S1, 2, 1, &S2, 2, 1, &S3, 2, 1);  // 請求資源printf("進程 %lu 已進入臨界區。\n", pthread_self());Ssignal(&S1, 1, &S2, 1, &S3, 1);  // 釋放資源return NULL;
}int main() {pthread_t t1, t2, t3;// 創建三個線程pthread_create(&t1, NULL, process, NULL);pthread_create(&t2, NULL, process, NULL);pthread_create(&t3, NULL, process, NULL);// 等待線程結束pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);return 0;
}

信號量機制之蘋果-橘子問題-CSDN博客

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/66030.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/66030.shtml
英文地址,請注明出處:http://en.pswp.cn/web/66030.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SOME/IP協議詳解 基礎解讀 涵蓋SOME/IP協議解析 SOME/IP通訊機制 協議特點 錯誤處理機制

車載以太網協議棧總共可劃分為五層&#xff0c;分別為物理層&#xff0c;數據鏈路層&#xff0c;網絡層&#xff0c;傳輸層&#xff0c;應用層&#xff0c;其中今天所要介紹的內容SOME/IP就是一種應用層協議。 SOME/IP協議內容按照AUTOSAR中的描述&#xff0c;我們可以更進一步…

springboot vue uniapp 仿小紅書 1:1 還原 (含源碼演示)

線上預覽: 移動端 http://8.146.211.120:8081/ 管理端 http://8.146.211.120:8088/ 小紅書憑借優秀的產品體驗 和超高人氣 目前成為筆記類產品佼佼者 此項目將詳細介紹如何使用Vue.js和Spring Boot 集合uniapp 開發一個仿小紅書應用&#xff0c;憑借uniapp 可以在h5 小程序 app…

基于celery的任務管理,本文主要是處理自己的算法,暴露API,管理任務并發,多線程

基于celery的任務管理&#xff0c;本文主要是處理自己的算法&#xff0c;暴露API&#xff0c;管理任務并發&#xff0c;多線程 基本需求描述潛在問題主函數配置文件 基本需求描述 暴露API&#xff0c;供其他人調用算法。方便查看任務狀態。因為服務器資源有限&#xff0c;控制…

Java(7)常用的工具類

1.Collections集合工具類 內置了大量對集合操作的靜態方法&#xff0c;可以通過類名直接調用方法。 方法的種類&#xff1a;最大值max、最小值min、sort排序...詳見API幫助文檔 import java.util.ArrayList; import java.util.Collections; import java.util.List;public cl…

【Varnish】:解決 Varnish 7.6 CDN 靜態資源緩存失效問題

項目場景&#xff1a; 在一個使用Varnish作為反向代理的Web應用中&#xff0c;我們依賴CDN&#xff08;內容分發網絡&#xff09;來緩存靜態資源&#xff08;如圖片、CSS、JavaScript文件等&#xff09;&#xff0c;以提高全球用戶的訪問速度并減輕源站服務器的負載。然而&…

理解機器學習中的參數和超參數

在機器學習中&#xff0c;參數和超參數是兩個重要但不同的概念&#xff0c;它們共同影響模型的性能和表現。以下是它們的定義和區別&#xff0c;以及如何通俗地理解它們&#xff1a; 1. 參數 定義 參數是模型在訓練過程中自動學習到的變量&#xff0c;它們直接決定了模型如何…

Win11右鍵菜單實現

主要參考Win11 Context Menu Demo 此工程是vs2022編譯&#xff0c;vs2019先修改下 base.h 方可編譯過 編譯好dll以后 拷貝至SparsePackage目錄下 生成稀疏包msix 就拿他工程里面的改&#xff0c;編輯AppxManifest.xml&#xff0c;配置都要對&#xff0c;一個不對可能都失敗&a…

R.swift庫的詳細用法

R.swift 是一個 Swift 工具庫,它提供了一個自動生成的類 R,使得你可以通過類型安全的方式訪問項目中的資源,例如圖片、字體、顏色、XIB 文件等。通過 R.swift,你可以避免字符串類型的錯誤,提升代碼的可維護性。 以下是 R.swift 庫的詳細用法: 1. 安裝 R.swift 使用 Sw…

像JSONDecodeError: Extra data: line 2 column 1 (char 134)這樣的問題怎么解決

問題介紹 今天處理返回的 JSON 的時候&#xff0c;出現了下面這樣的問題&#xff1a; 處理這種問題的時候&#xff0c;首先你要看一下當前的字符串格式是啥樣的&#xff0c;比如我查看后發現是下面這樣的&#xff1a; 會發現這個字符串中間沒有逗號&#xff0c;也就是此時的J…

what?ngify 比 axios 更好用,更強大?

文章目錄 前言一、什么是ngify&#xff1f;二、npm安裝三、發起請求3.1 獲取 JSON 數據3.2 獲取其他類型的數據3.3 改變服務器狀態3.4 設置 URL 參數3.5 設置請求標頭3.6 與服務器響應事件交互3.7 接收原始進度事件3.8 處理請求失敗3.9 Http Observables 四、更換 HTTP 請求實現…

Linux Kernel 之十 詳解 PREEMPT_RT、Xenomai 的架構、源碼、構建及使用

概述 現在的 RTOS 基本可以分為 Linux 陣營和非 Linux 陣營這兩大陣營。非 Linux 陣營的各大 RTOS 都是獨立發展,使用上也相對獨立;而 Linux 陣營則有多種不同的實現方法來改造 Linux 以實現實時性要求。本文我們重點關注 Linux 陣營的實時內核實現方法! 本文我們重點關注 …

【拒絕算法PUA】3065. 超過閾值的最少操作數 I

系列文章目錄 【拒絕算法PUA】0x00-位運算 【拒絕算法PUA】0x01- 區間比較技巧 【拒絕算法PUA】0x02- 區間合并技巧 【拒絕算法PUA】0x03 - LeetCode 排序類型刷題 【拒絕算法PUA】LeetCode每日一題系列刷題匯總-2025年持續刷新中 C刷題技巧總結&#xff1a; [溫習C/C]0x04 刷…

ClickHouse-CPU、內存參數設置

常見配置 1. CPU資源 1、clickhouse服務端的配置在config.xml文件中 config.xml文件是服務端的配置&#xff0c;在config.xml文件中指向users.xml文件&#xff0c;相關的配置信息實際是在users.xml文件中的。大部分的配置信息在users.xml文件中&#xff0c;如果在users.xml文…

《自動駕駛與機器人中的SLAM技術》ch9:自動駕駛車輛的離線地圖構建

目錄 1 點云建圖的流程 2 前端實現 2.1 前端流程 2.2 前端結果 3 后端位姿圖優化與異常值剔除 3.1 兩階段優化流程 3.2 優化結果 ① 第一階段優化結果 ② 第二階段優化結果 4 回環檢測 4.1 回環檢測流程 ① 遍歷第一階段優化軌跡中的關鍵幀。 ② 并發計算候選回環對…

type 屬性的用途和實現方式(圖標,表單,數據可視化,自定義組件)

1.圖標類型 <uni-icon>組件中&#xff0c;type可以用來指定圖標的不同樣式。 <uni-icons type"circle" size"30" color"#007aff"></uni-icons> //表示圓形 <uni-icons type"square" size"30" co…

網絡基礎知識指南|1-20個

1. IP地址: 即互聯網協議地址&#xff0c;是用于標識互聯網上的每一個設備或節點的唯一地址。IP地址的作用主要是進行網絡設備的定位和路由&#xff0c;確保數據包可以從源設備準確地傳送到目標設備。2. 子網掩碼: 是用于將一個IP地址劃分為網絡地址和主機地址的工具。它通常與…

GPT 系列論文精讀:從 GPT-1 到 GPT-4

學習 & 參考資料 前置文章 Transformer 論文精讀 機器學習 —— 李宏毅老師的 B 站搬運視頻 自監督式學習(四) - GPT的野望[DLHLP 2020] 來自獵人暗黑大陸的模型 GPT-3 論文逐段精讀 —— 沐神的論文精讀合集 GPT&#xff0c;GPT-2&#xff0c;GPT-3 論文精讀【論文精讀】…

lombok在高版本idea中注解不生效的解決

環境&#xff1a; IntelliJ IDEA 2024.3.1.1 Spring Boot Maven 問題描述 使用AllArgsConstructor注解一個用戶類&#xff0c;然后調用全參構造方法創建對象&#xff0c;出現錯誤&#xff1a; java: 無法將類 com.itheima.pojo.User中的構造器 User應用到給定類型; 需要:…

145.《redis原生超詳細使用》

文章目錄 什么是redisredis 安裝啟動redis數據類型redis key操作key 的增key 的查key 的改key 的刪key 是否存在key 查看所有key 「設置」過期時間key 「查看」過期時間key 「移除」過期時間key 「查看」數據類型key 「匹配」符合條件的keykey 「移動」到其他數據庫 redis數據類…

大數據技術Kafka詳解 ⑤ | Kafka中的CAP機制

目錄 1、分布式系統當中的CAP理論 1.1、CAP理論 1.2、Partitiontolerance 1.3、Consistency 1.4、Availability 2、Kafka中的CAP機制 C軟件異常排查從入門到精通系列教程&#xff08;核心精品專欄&#xff0c;訂閱量已達600多個&#xff0c;歡迎訂閱&#xff0c;持續更新…