Redis IO多路復用

0、前言

本文所有代碼可見 => 【gitee code demo】
本文涉及的主題:

1、BIO、NIO的業務實踐和缺陷

2、Redis IO多路復用:redis快的主要原因

3、epoll 架構

部分圖片 via 【epoll 原理分析】

1、BIO單線程版

1.1 業務代碼

client client代碼相同 啟動多個即可

public class RedisClient1 {public static void main(String[] args) throws IOException {SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");Socket socket = new Socket("127.0.0.1", 6300);log("{} {}> 嘗試連接服務 {}", sdf.format(new Date()) ,socket.getLocalPort(), socket.getPort());OutputStream outputStream = socket.getOutputStream();while (true) {Scanner scanner = new Scanner(System.in);log("{} {}> ", sdf.format(new Date()) ,socket.getLocalPort());String string = scanner.nextLine();if (string.equalsIgnoreCase("quit")) {break;}socket.getOutputStream().write(string.getBytes());log("{} {}> 發送數據:{}", sdf.format(new Date()) ,socket.getLocalPort(), string);}outputStream.close();socket.close();}}

server

public class RedisServerBIO {public static void main(String[] args) throws IOException {SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");ServerSocket serverSocket = new ServerSocket(6300);while (true) {log("{} {}> ", sdf.format(new Date()), serverSocket.getLocalPort());Socket socket = serverSocket.accept();//阻塞1 ,等待客戶端連接log("{} {}> {} 連接到服務", sdf.format(new Date()), socket.getLocalPort(), socket.getPort());InputStream inputStream = socket.getInputStream();int length = -1;byte[] bytes = new byte[1024];log("{} {}> ", sdf.format(new Date()), serverSocket.getLocalPort());while ((length = inputStream.read(bytes)) != -1)//阻塞2 ,等待客戶端發送數據{log("{} {}> 收到 {} 的消息:{}", sdf.format(new Date()), serverSocket.getLocalPort(), socket.getPort(), new String(bytes, 0, length));}inputStream.close();socket.close();}}
}

1.2 結果演示

現象:

1、client1 連接到server,client2嘗試連接被阻塞

2、client2 先發送的消息未被server接受,client1后發送的repeat消息被server接受

結論:

BIO會一直阻塞,單線程下只能處理一個socket連接

存在的問題:

多 client 訪問時效率低

在這里插入圖片描述

2、BIO多線程版

2.1 業務代碼

public class RedisServerBIOMultiThread {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket(6300);SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");log("{} {}> ", sdf.format(new Date()), serverSocket.getLocalPort());while (true) {Socket socket = serverSocket.accept();//阻塞1 ,等待客戶端連接log("{} {}> {} 連接到服務", sdf.format(new Date()), socket.getLocalPort(), socket.getPort());new Thread(() -> {try {InputStream inputStream = socket.getInputStream();int length = -1;byte[] bytes = new byte[1024];while ((length = inputStream.read(bytes)) != -1)//阻塞2 ,等待客戶端發送數據{log("{} {}> 收到 {} 的消息:{}", sdf.format(new Date()), serverSocket.getLocalPort(), socket.getPort(), new String(bytes, 0, length));}inputStream.close();socket.close();} catch (IOException e) {e.printStackTrace();}}, Thread.currentThread().getName()).start();System.out.println(Thread.currentThread().getName());}}
}

2.1 結果演示

現象:

client1 、client2 都能正常連接到 server且正常發送、接受消息

結論:

BIO多線程提高處理能力,可以同時處理多個socket連接

存在的問題:

每個線程只能處理一個socket,當client數量大時,需要消耗大量線程資源

在這里插入圖片描述

3、NIO

3.1 業務代碼

當一個客戶端與服務端進行連接,這個socket就會加入到一個容器中,隔一段時間遍歷一次,看這個socket的read()方法能否讀到數據,這樣一個線程就能處理多個客戶端的連接和讀取了

public class RedisServerNIO {static ArrayList<SocketChannel> socketList = new ArrayList<>();static ByteBuffer byteBuffer = ByteBuffer.allocate(1024);public static void main(String[] args) throws IOException {ServerSocketChannel serverSocket = ServerSocketChannel.open();SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");serverSocket.bind(new InetSocketAddress("127.0.0.1", 6300));serverSocket.configureBlocking(false);//設置為非阻塞模式while (true) {for (SocketChannel element : socketList) {int read = element.read(byteBuffer);if (read > 0) {byteBuffer.flip();byte[] bytes = new byte[read];byteBuffer.get(bytes);//System.out.println(JSONUtil.toJsonStr(element));log("{} {}> 收到 {} 的消息:{}", sdf.format(new Date()), element.socket().getLocalPort(), element.socket().getPort(), new String(bytes, 0, read));byteBuffer.clear(); }}SocketChannel socketChannel = serverSocket.accept();if (socketChannel != null) {log("{} {}> {} 連接到服務", sdf.format(new Date()), socketChannel.socket().getLocalPort(), socketChannel.socket().getPort());socketChannel.configureBlocking(false);//設置為非阻塞模式socketList.add(socketChannel);log("{} {}> socket 數量: {} ", sdf.format(new Date()), socketChannel.socket().getLocalPort(), socketList.size());}}}
}

3.2 結果演示

現象:

1、client1 、client2 都能正常連接到 server且正常發送、接受消息

2、server 沒有創建額外線程

結論:

NIO 可以實現一個線程處理多個 socket 連接

存在的問題:

1、每次遍歷所有socket,有很多無用功

2、遍歷過程在用戶態,還需要將數據從內核態讀取到用戶態

在這里插入圖片描述

4、IO多路復用

1、使用 epoll() 實現,多個網絡連接 socket 復用同一個線程

2、基于事件驅動機制,socket 中有數據會主動通知內核,并加入到就緒鏈表中,不需要遍歷所有 socket

3、減少了內核態和用戶態的切換

Redis IO多路復用實現

在這里插入圖片描述

4.1 epoll_create()

創建內核中的fd容器

4.2 epoll_ctl()

epoll_ctl函數用于增加,刪除,修改epoll事件,epoll事件會存儲于內核epoll結構體紅黑樹中

4.3 epoll_wait

用于監聽套接字事件,可以通過設置超時時間timeout來控制監聽的行為為阻塞模式還是超時模式

4.4 epoll 軟件架構

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

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

相關文章

Mongodb索引使用限制

學習mongodb&#xff0c;體會mongodb的每一個使用細節&#xff0c;歡迎閱讀威贊的文章。這是威贊發布的第85篇mongodb技術文章&#xff0c;歡迎瀏覽本專欄威贊發布的其他文章。如果您認為我的文章對您有幫助或者解決您的問題&#xff0c;歡迎在文章下面點個贊&#xff0c;或者關…

Sahi+Yolov10

一、前言 了解到Sahi&#xff0c;是通過切圖&#xff0c;實現提高小目標的檢測效果。sahi 目前支持yolo5\yolo8\mmdet\detection2 等等算法&#xff0c;本篇主要通過實驗onnx加載模型的方式使sahi支持yolov10。 二、代碼 &#xff08;1&#xff09;轉換模型 首先使用 conda創…

大數的排列組合公式C代碼

我們知道&#xff0c;計算排列A(n,m)和組合C(n,m)可以用先求階乘的方式實現&#xff0c;但是當數很大時求階乘很容易溢出&#xff0c;所以這里給出非階乘的方式求排列組合 求排列 分母和分子可以抵消&#xff0c;最后代碼如下 unsigned long long A(int n, int m) {unsigned…

華為機試HJ34圖片整理

華為機試HJ34圖片整理 題目&#xff1a; 想法&#xff1a; 將輸入的字符串中每個字符都轉為ASCII碼&#xff0c;再通過快速排序進行排序并輸出 input_str input() input_list [int(ord(l)) for l in input_str]def partition(arr, low, high):i low - 1pivot arr[high]f…

RPC與REST

RPC與REST 訪問遠程服務1遠程服務調用&#xff08;Remote Procedure Call&#xff0c;RPC&#xff09;&#xff1a;RPC 解決什么問題&#xff1f;如何解決的&#xff1f;為什么要那樣解決&#xff1f;1.1 先解決兩個進程間如何交換數據的問題&#xff0c;也就是進程間通信&…

最新扣子(Coze)實戰案例:使用擴圖功能,讓你的圖任意變換,完全免費教程

&#x1f9d9;?♂? 大家好&#xff0c;我是斜杠君&#xff0c;手把手教你搭建扣子AI應用。 &#x1f4dc; 本教程是《AI應用開發系列教程之扣子(Coze)實戰教程》&#xff0c;完全免費學習。 &#x1f440; 微信關注公從號&#xff1a;斜杠君&#xff0c;可獲取完整版教程。&a…

如何快速搭建python項目的虛擬環境

itopen組織1、提供OpenHarmony優雅實用的小工具2、手把手適配riscv qemu linux的三方庫移植3、未來計劃riscv qemu ohos的三方庫移植 小程序開發4、一切擁抱開源&#xff0c;擁抱國產化 你在開發python工具的時候還一直使用系統默認的環境嗎&#xff1f;是否有遇到有時候…

2024年【北京市安全員-B證】報名考試及北京市安全員-B證最新解析

題庫來源&#xff1a;安全生產模擬考試一點通公眾號小程序 2024年北京市安全員-B證報名考試為正在備考北京市安全員-B證操作證的學員準備的理論考試專題&#xff0c;每個月更新的北京市安全員-B證最新解析祝您順利通過北京市安全員-B證考試。 1、【多選題】《中華人民共和國安…

android輪播圖入門2——觸摸停止與指示器

前言 這次要在上一篇輪播圖的基礎上做改造&#xff0c;增加兩個功能&#xff1a; 用戶觸摸到輪播圖時&#xff0c;停止輪播在輪播圖上展示一個小指示器&#xff0c;指示當前輪播組件的位置 觸摸停播 觸摸停播的設計思路是&#xff1a;監聽實現輪播圖的觸摸事件&#xff0c;…

手把手教你從零開始構建 AI 視頻生成模型

在 GitHub 上發現一篇教程&#xff0c;作者詳細介紹了如何使用 Python 語言&#xff0c;從零開始構建一個文本到視頻生成模型。 涵蓋了從理解理論概念到架構編碼&#xff0c;最終實現輸入文本提示即可生成視頻的全過程。 相關鏈接 GitHub&#xff1a;github.com/FareedKhan-…

python-redis-lock是如何實現鎖自動續期的

python-redis-lock簡介 python-redis-lock是一個python的第三方庫&#xff0c;基于Redis&#xff0c;封裝了分布式鎖的邏輯&#xff0c;提供了更高級的API來簡化鎖的獲取、保持和釋放過程。包括自動續期、鎖超時、重入鎖等功能。 相比于直接使用redis的setnx&#xff0c;避免了…

倒退型自閉癥與輕度自閉癥有什么區別?

作為星貝育園自閉癥兒童康復中心的一名專業教師&#xff0c;我深知家長們在面對自閉癥譜系障礙&#xff08;ASD&#xff09;時的種種疑問與挑戰&#xff0c;尤其是關于倒退型自閉癥與輕度自閉癥之間的區別。今天&#xff0c;我將從專業視角出發&#xff0c;深入淺出地解析這兩種…

精通Vim編輯器:Linux系統下的強大文本編輯工具

精通Vim編輯器&#xff1a;Linux系統下的強大文本編輯工具 引言 在Linux世界中&#xff0c;Vim是一個功能強大、高度可定制的文本編輯器&#xff0c;它繼承自經典的vi編輯器并提供了一系列增強功能。無論是系統管理員、開發人員還是普通用戶&#xff0c;掌握Vim的使用都能大幅…

游戲AI的創造思路-技術基礎-強化學習(2)

上一篇中引出了深度強化學習這個大坑&#xff0c;本篇淺淺填一下~~~~ 目錄 6. 深度強化學習概述 6.1. 基本概念 6.2. 發展歷史 6.3. 基本公式 6.4. Python實現 6.5. 運行原理 6.5.1. 核心要素 6.5.2. 運行原理 6.5.3. 典型算法 6.5.4. Python實現代碼 6.6. 優缺點 …

Segmentation fault (core dumped)

錯誤簡介 出現 “Segmentation fault (core dumped)” 錯誤通常意味著程序訪問了未分配的內存或者越界訪問了已分配內存之外的區域。 段錯誤通常發生在以下情況&#xff1a; 空指針解引用&#xff1a;嘗試對空指針進行操作。內存越界&#xff1a;訪問了超出分配內存邊界的區…

大廠面試官贊不絕口的后端技術亮點【后端項目亮點合集(2)】

本文將持續更新~~ hello hello~ &#xff0c;這里是絕命Coding——老白~&#x1f496;&#x1f496; &#xff0c;歡迎大家點贊&#x1f973;&#x1f973;關注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;個人主頁&#xff1a;絕命C…

提高論文發表機會:Nature Communications 最新研究教你如何巧妙回復審稿意見

我是娜姐 迪娜學姐 &#xff0c;一個SCI醫學期刊編輯&#xff0c;探索用AI工具提效論文寫作和發表。 對于科研搬磚人來說&#xff0c;在論文投稿過程中&#xff0c;如何有效回復審稿意見才能得到審稿人的認可&#xff0c;一直是一個讓人困惑又帶點玄學的問題。 但是&#xff0c…

vue3 按鈕復制粘貼功能

1.html <div click"copy(item.envelopePassword)" > 復制口令 </div> 2.utils 創建copy.js export const copy (val: string): void > {let { isSuccessRef } useCopyToClipboard(val) as anyif (isSuccessRef) {// 輕提示showNotify("復制…

【強化學習的數學原理】課程筆記--3(蒙特卡洛方法)

目錄 蒙特卡洛方法MC Basic算法sparse reward MC Greedy 算法樣本使用效率MC ? \epsilon ?-Greedy 算法一些例子 蒙特卡洛方法 第二節 推導貝爾曼最優公式中的&#xff1a; q π k ( s , a ) ∑ r P ( r ∣ s , a ) r γ ∑ s ′ P ( s ′ ∣ s , a ) v π k ( s ′ ) q…

vue3 ~ pinia學習

先看兩個圖 一個vuex 一個pinia 根據圖看出來 pinia更簡單了 那么具體怎么操作呢 我們來看下~ 第一步 下載 yarn add pinia # 或者使用 npm npm install pinia 第二步 注冊 創建一個 pinia 實例 (根 store) 并將其傳遞給應用&#xff1a; import { createApp } from v…