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 微服務框架,幫助我們輕鬆構建和管理微服務應用。 本框架不僅支持 Consul 服務註 ...
  • 先看一下效果吧: 如果不會寫動畫或者懶得寫動畫,就直接交給Blend來做吧; 其實Blend操作起來很簡單,有點類似於在操作PS,我們只需要設置關鍵幀,滑鼠點來點去就可以了,Blend會自動幫我們生成我們想要的動畫效果. 第一步:要創建一個空的WPF項目 第二步:右鍵我們的項目,在最下方有一個,在B ...
  • Prism:框架介紹與安裝 什麼是Prism? Prism是一個用於在 WPF、Xamarin Form、Uno 平臺和 WinUI 中構建鬆散耦合、可維護和可測試的 XAML 應用程式框架 Github https://github.com/PrismLibrary/Prism NuGet htt ...
  • 在WPF中,屏幕上的所有內容,都是通過畫筆(Brush)畫上去的。如按鈕的背景色,邊框,文本框的前景和形狀填充。藉助畫筆,可以繪製頁面上的所有UI對象。不同畫筆具有不同類型的輸出( 如:某些畫筆使用純色繪製區域,其他畫筆使用漸變、圖案、圖像或繪圖)。 ...
  • 前言 嗨,大家好!推薦一個基於 .NET 8 的高併發微服務電商系統,涵蓋了商品、訂單、會員、服務、財務等50多種實用功能。 項目不僅使用了 .NET 8 的最新特性,還集成了AutoFac、DotLiquid、HangFire、Nlog、Jwt、LayUIAdmin、SqlSugar、MySQL、 ...
  • 本文主要介紹攝像頭(相機)如何採集數據,用於類似攝像頭本地顯示軟體,以及流媒體數據傳輸場景如傳屏、視訊會議等。 攝像頭採集有多種方案,如AForge.NET、WPFMediaKit、OpenCvSharp、EmguCv、DirectShow.NET、MediaCaptre(UWP),網上一些文章以及 ...
  • 前言 Seal-Report 是一款.NET 開源報表工具,擁有 1.4K Star。它提供了一個完整的框架,使用 C# 編寫,最新的版本採用的是 .NET 8.0 。 它能夠高效地從各種資料庫或 NoSQL 數據源生成日常報表,並支持執行複雜的報表任務。 其簡單易用的安裝過程和直觀的設計界面,我們 ...
  • 背景需求: 系統需要對接到XXX官方的API,但因此官方對接以及管理都十分嚴格。而本人部門的系統中包含諸多子系統,系統間為了穩定,程式間多數固定Token+特殊驗證進行調用,且後期還要提供給其他兄弟部門系統共同調用。 原則上:每套系統都必須單獨接入到官方,但官方的接入複雜,還要官方指定機構認證的證書 ...
  • 本文介紹下電腦設備關機的情況下如何通過網路喚醒設備,之前電源S狀態 電腦Power電源狀態- 唐宋元明清2188 - 博客園 (cnblogs.com) 有介紹過遠程喚醒設備,後面這倆天瞭解多了點所以單獨加個隨筆 設備關機的情況下,使用網路喚醒的前提條件: 1. 被喚醒設備需要支持這WakeOnL ...
  • 前言 大家好,推薦一個.NET 8.0 為核心,結合前端 Vue 框架,實現了前後端完全分離的設計理念。它不僅提供了強大的基礎功能支持,如許可權管理、代碼生成器等,還通過採用主流技術和最佳實踐,顯著降低了開發難度,加快了項目交付速度。 如果你需要一個高效的開發解決方案,本框架能幫助大家輕鬆應對挑戰,實 ...