Redis網路模型

来源:https://www.cnblogs.com/fanglikuai/p/18189324
-Advertisement-
Play Games

theme: condensed-night-purple highlight: androidstudio 主從複製原理 建立連接 從節點在配置了 replicaof 配置了主節點的ip和port 從庫執行replicaof 併發送psync命令 同步數據到從庫 主庫bgsave生成RDB文件,並 ...


主從複製原理

  1. 建立連接

    1. 從節點在配置了 replicaof 配置了主節點的ip和port
    2. 從庫執行replicaof 併發送psync命令
  2. 同步數據到從庫

    1. 主庫bgsave生成RDB文件,併發送給從庫,同時為每一個slave開闢一塊 replication buffer 緩衝區記錄從生成rdb文件開始收到的所有寫命令。
    2. 從庫清空數據並載入rdb
  3. 發送新寫的命令給從庫

    1. 從節點載入 RDB 完成後,主節點將 replication buffer 緩衝區的數據(增量寫命令)發送到從節點,slave 接收並執行,從節點同步至主節點相同的狀態。
  4. 基於長連接傳播

    1. 方便後續命令傳輸,除了寫命令,還維持著心跳機制

網路模型

  • 阻塞IO

  • 非阻塞IO

    • 沒啥用,還是需要等待數據準備就緒
  • IO多路復用

  • 信號驅動IO

  • 非同步IO

IO多路復用

文件描述符:簡稱FD

select

流程:

  1. 創建fd_set rfds

    1. 假設要監聽的fd為1,2,5
  2. 執行select(5+1,null,null,3)

    1. 第一個參數為最大長度+1,後面是等待時間
  3. 內核遍歷fd

    1. 沒有數據,休眠

      1. 等待數據就緒或者超時
  4. 遍歷fd_set 找到就緒的數據

存在的問題

  • 需要將整個fd_set從用戶空間拷貝到內核空間,select結束後還要拷貝回用戶空間
  • 需要遍歷一次
  • 最大為監聽1024

poll

將數據改為了鏈表,還是需要遍歷

epoll

  1. epoll_create 創建epoll實例
  2. epoll_ctl 添加需要監聽的fd,關聯callback
  3. epoll_wait 等待fd就緒

epoll_wait有兩種通知模式

  • levelTriggered 簡稱LT 當FD有數據可讀的時候,會重覆通知多次,直到數據處理完成。是epoll的預設模式
  • EdgeTriggered 簡稱ET 。當FD有數據可讀的時候只會被通知一次,不管數據是否處理完成

ET模式避免了LT的驚群效應。

ET模式最好結合非阻塞IO。

淘汰策略

分類:全體,ttl

LRU

抽樣LRU 不是嚴格的

LFU

RedisObject中使用邏輯訪問次數

訪問頻率越高,增加的越小,還會衰減(16位記錄時間,8位記錄邏輯訪問次數)

總結

image.png

附帶的tcp連接redis客戶端 使用go編寫的

package main

import (
    "bufio"
    "errors"
    "fmt"
    "io"
    "net"
    "strconv"
)

// RedisClient 封裝用於連接
type RedisClient struct {
    conn net.Conn
    //包裝一層 方便讀寫
    writer *bufio.Writer
    reader *bufio.Reader
}

func main() {
    //連接redis
    conn, err := net.Dial("tcp", "127.0.0.1:6379")
    if err != nil {
       fmt.Println("連接redis失敗", err)
    }
    client := RedisClient{conn: conn, writer: bufio.NewWriter(conn), reader: bufio.NewReader(conn)}
    defer client.conn.Close()
    //發送命令
    client.sendRequest([]string{"set", "name", "方塊"})
    //zrange boards:2024-4 0 -1
    //client.sendRequest([]string{"zrange", "boards:2024-4", "0", "-1"})
    //LRANGE tlist 0 -1
    client.sendRequest([]string{"LRANGE", "tlist", "0", "-1"})

}

func (client *RedisClient) sendRequest(args []string) interface{} {

    length := len(args)
    firstCommand := fmt.Sprintf("%s%d", "*", length)
    client.writeCommand(firstCommand)
    for _, s := range args {
       n := len(s)
       client.writeCommand("$" + strconv.Itoa(n))
       client.writeCommand(s)
       println(n, s)
    }
    response := client.handleResponse()
    //fmt.Printf("%v", response)
    return response

}

// 寫命令
func (client *RedisClient) writeCommand(s string) {
    client.conn.Write([]byte(s + "\r\n"))

}

// 解析返回結果
func (client *RedisClient) handleResponse() interface{} {

    //先讀取第一個字元
    r, _, _ := client.reader.ReadRune()
    flag := string(r)
    fmt.Println("第一個操作數:" + flag)
    switch flag {
    case "+":
       //一行字元串
       return client.ReadLine()
    case "-":
       //異常
       return client.ReadLine()
    case ":":
       //數字
       line := client.ReadLine()
       res, _ := strconv.Atoi(line)
       return res
    case "$":
       // 多行字元串
       //readRune, _, _ := client.reader.ReadRune()
       //去掉換行
       readRune := client.ReadLine()
       length := string(readRune)
       if length == "-1" {
          return nil
       } else if length == "0" {
          return ""
       }
       lll, _ := strconv.Atoi(length)
       //+2是跳過\r\n
       bytes := make([]byte, lll+2)
       n, _ := client.reader.Read(bytes)
       return string(bytes[:n])
    case "*":
       //多行字元串 遞歸獲取
       return client.readBulkString()
    default:
       return errors.New("錯誤")
    }
}

// 讀一行
func (client *RedisClient) ReadLine() string {
    bytes, _, _ := client.reader.ReadLine()
    return string(bytes)
}

// 讀到末尾 估計有點問題
func (client *RedisClient) ReadToEnd() string {

    var size = 1024
    bytes := make([]byte, size)
    var temp = ""
    for {
       n, err := client.reader.Read(bytes)
       temp += string(bytes[:n])
       //n, err := client.conn.Read(bytes)
       if err == io.EOF || n == 0 || n < size {
          break
       }

    }

    return temp
}
func (client *RedisClient) readBulkString() interface{} {

    counts, _ := strconv.Atoi(client.ReadLine())
    if counts <= 0 {
       return nil
    }
    //var resList = list.List{}
    var lists []interface{}
    for i := 0; i < counts; i++ {
       res := client.handleResponse()
       lists = append(lists, res)
       //fmt.Println("多行結果:" + fmt.Sprintf("%v", res))
    }

    return lists

}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • X-Frame-Options 是一個HTTP響應頭,用於控制網頁是否可以嵌套在 <frame>, <iframe>, <embed> 或者 <applet> 中。通過設置 X-Frame-Options 頭部,網站管理員可以防止網頁被嵌套到其他網站的框架中,從而有效防範點擊劫持等安全風險。下麵是關 ...
  • nginx 系列 Nginx-01-聊一聊 nginx Nginx-01-Nginx 是什麼 Nginx-02-為什麼使用 Nginx Nginx-02-Nginx Ubuntu 安裝 + windows10 + WSL ubuntu 安裝 nginx 實戰筆記 Nginx-02-基本使用 Ngin ...
  • JPEG庫的移植(arm平臺) 目錄JPEG庫的移植(arm平臺)介紹頭文件及全局變數1、圖片顯示2、其他圖片壓縮到jpg圖片3、主函數及驗證程式輸出結果 介紹 圖解 頭文件及全局變數 #include <stdio.h> #include <stdlib.h> #include <sys/type ...
  • 寫在前面 這部分真的感覺超級難,其實也不能說難,主要是真的想不到這個思路應該這麼做,或者說他好厲害,他怎麼知道該這麼設計實現。 說下難點吧,我覺得後天邏輯還好,主要是前端部分真的需要點花點時間來思考,比如佈局、交互設計的實現等等。 文檔頁面功能開發 1、任務拆解 增加文檔頁面,首頁點擊電子書時,跳轉 ...
  • NumPy 數組的複製與視圖 NumPy 數組的複製和視圖是兩種不同的方式來創建新數組,它們之間存在著重要的區別。 複製 複製 會創建一個包含原始數組相同元素的新數組,但這兩個數組擁有獨立的記憶體空間。這意味著對複製進行的任何更改都不會影響原始數組,反之亦然。 創建副本可以使用以下方法: arr.co ...
  • title: Django 安全性與防禦性編程:如何保護 Django Web 應用 date: 2024/5/13 20:26:58 updated: 2024/5/13 20:26:58 categories: 後端開發 tags: CSRF XSS SQL Upload HTTPOnly Pa ...
  • 正文 感覺自己這兩天摸魚有些嚴重(笑。 前兩天有件事忘了寫了。周六晚去吃飯和拍照的時候,看見有個女生坐在路邊,紅著眼睛跟誰打電話,語氣裡帶一股哭腔。身上穿著校服,我想應該是高中生。身邊沒有人。我不知道什麼事情能讓人發火又哭泣,覺得有些奇怪,也不知道怎麼寬慰這個陌生人。想了想,跑去小賣部買了瓶怡寶,放 ...
  • 在將紙質文檔掃描成PDF電子文檔時,有時可能會出現頁面方向翻轉或者頁面順序混亂的情況。為了確保更好地瀏覽和查看PDF文件,本文將分享一個使用Python來旋轉PDF頁面或者調整PDF頁面順序的解決方案。 要實現Python對PDF頁面進行設置,我們需要用到第三方庫 Spire.PDF for Pyt ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...