【中間件開發】Redis基礎命令詳解及概念介紹

文章目錄

  • 前言
  • 一、Redis相關命令詳解及原理
    • 1.1 string、set、zset、list、hash
      • 1.1.1 string
      • 1.1.2 list
      • 1.1.3 hash
      • 1.1.4 set
      • 1.1.5 zset
    • 1.2 分布式鎖的實現
    • 1.3 lua腳本解決ACID原子性
    • 1.4 Redis事務的ACID性質分析
  • 二、Redis協議與異步方式
    • 2.1 Redis協議解析
      • 2.1.1 redis pipeline
      • 2.1.2 Redis協議圖
    • 2.2 特殊協議操作-訂閱發布
    • 2.3 異步redis協議
      • 2.3.1 hiredis + libevent
  • 總結


前言

本文介紹了Redis相關命令以及Redis當中的一些概念(協議)。


一、Redis相關命令詳解及原理

內存是稀缺資源,所以:

  1. 當數據量少時,存儲效率高為主
  2. 當數據量多時,運行速度快為主

1.1 string、set、zset、list、hash

  1. string 是一個安全的二進制字符串(兼容’\0’作為分隔符,安全指按長度);
  2. 雙端隊列 (鏈表) list :有序(插入有序);
  3. 散列表 hash:對順序不關注,field 是唯一的;
  4. 無序集合 set:對順序不關注,里面的值都是唯一的;
  5. 有序集合 zset :對順序是關注的,里面的值是唯一的;根據 member 來確定唯一;根據 score 來 確定有序;

1.1.1 string

set key_test 1000get key_test# 原子減一
decr key_test
decrby key_test decrement(一個數字)# 原子加一
incr key_test
incrby key_test increment# set Not exist,當key_test存在時,什么也不做,否則等同于set
setnx key_test value
del key_test----------
# 
setbit key_test offset value
# 第offset位設置為value
getbit key_test offset
# 統計字符串被設置為1的bit數
bitcount key_test
----------

image.png

image.png
image.png

應用

  1. 對象存儲:set,get
  2. 累加器:incr
  3. 分布式鎖:setnx
  4. 位運算:setbit,getbit,bitcount

1.1.2 list

雙向鏈表,首尾操作時間復雜度O(1);中間元素操作O(n)

  1. list.size < 48 不壓縮
  2. 元素壓縮前后長度差不超過8,不壓縮

為什么壓縮?如何壓縮的?

# 從隊列左側入隊
lpush key value ...
lpop key# 從隊列右側入隊
rpush key value ...
rpop key # 尾索引
lrange key start end# 從存于 key 的列表里移除前 count 次出現的值為 value 的元素
lrem key count value# rpop的阻塞版本
brpop key timeout

image.png

應用

  1. 棧:lpush + lpop
  2. 隊列:lpush + rpop
  3. 阻塞隊列:lpush + brpop
  4. 異步消息隊列
    1. 操作和隊列一樣,但是在不同系統間;生產者和消費者;
  5. 獲取固定窗口記錄
    1. ltrim key 0 4 保留最近5條記錄

1.1.3 hash

散列表;C++ unordered_map

(節點數量 > 512 || 所有字符串長度 > 64) 采用dict
(節點數量 <= 512 || 所有字符串長度 < 64) 采用ziplist

hget key field
hgetallhset key field value
# 設置多個鍵值對
hmset key field1 value1 field2 value2 field3 value3 ... fieldn valuenhmget key field1 field2 ...hincrby key field increment
# 獲取有多少個鍵值對
hlen keyhdel key field

image.png

應用

  1. 存儲對象
  2. 購物車:商品列表用list,其中屬性用hash

1.1.4 set

無序集合

(元素都為整數 && 節點數量 <= 512) 采用整數數組存儲
(元素不全為整數 || 節點數量 > 512) 采用字典存儲

# 添加一個或多個
sadd key member ...
# 計算集合元素個數
scard keysmembers key
# 返回成員member是否為key的成員
sismember key member
# 隨機返回key集合中的一個或多個元素
srandmember key [count]
# 移除一個隨機元素
spop key [count]
# 返回差集
sdiff key [key...]
# 返回交集
sinter key [key...]
# 返回并集
sunion key [key...]

image.png

應用

  1. 抽獎:srandmember
  2. 共同關注:sdiff ; sinter; sunion

1.1.5 zset

有序集合;實現排行榜;有序唯一


zadd key 
# 從key中刪除member的鍵值對
zrem key member [member...]
# 返回有序集key中member的score值
zscore key member
# 成員member的score值加上增量
zincrby key increment member
# 返回個數
zcard key
# 返回排名
zrank key member
# 返回指定范圍的元素
zrange key start stop
# 返回指定范圍的元素(逆序)
zrevrange key start stop

image.png

應用

  1. 百度熱榜
  2. 延時隊列
  3. 分布式定時器
  4. 時間窗口限流

1.2 分布式鎖的實現

釋放鎖操作:事務操作

鎖:誰持有,誰釋放

get dislock
-- 釋放鎖
local uuid = redis.call("get", KEYS[1])
if uuid == KEYS[2] thenredis.call("del", KEYS[1])
end

1.3 lua腳本解決ACID原子性

# 開啟事務
multi# 提交事務
exec# 取消事務
discard# 檢測key的變動
watch實際中是使用lua腳本
  • redis 中加載了一個 lua 虛擬機;用來執行 redis lua 腳本;
  • redis lua 腳本的執行是原子性的;
  • 當某個腳本正在執行的時候,不會有其他命令或者腳本被執行;
  • lua 腳本當中的命令會直接修改數據狀態;
  • lua 腳本 mysql 存儲區別:MySQL存儲過程不具備事務性,所以也不具備原子性;

注意:如果項目中使用了 lua 腳本,不需要使用上面的事務命令
image.png

1.4 Redis事務的ACID性質分析

  • A 原子性;事務是一個不可分割的工作單位,事務中的操作要么全部成功,要么全部失敗;redis 不支持回滾;即使事務隊列中的某個命令在執行期間出現了錯誤,整個事務也會繼續執行下去,直 到將事務隊列中的所有命令都執行完畢為止。

  • C 一致性;事務的前后,所有的數據都保持一個一致的狀態,不能違反數據的一致性檢測;這里 的一致性是指預期的一致性而不是異常后的一致性;所以 redis 也不滿足;這個爭議很大:redis 能 確保事務執行前后的數據的完整約束;但是并不滿足業務功能上的一致性;比如轉賬功能,一個扣 錢一個加錢;可能出現扣錢執行錯誤,加錢執行正確,那么最終還是會加錢成功;系統憑空多了 錢;

set zhang 1000
lpush zhang 1 3 4 #error
get mark
  • I 隔離性;各個事務之間互相影響的程度;redis 是單線程執行,天然具備隔離性;

  • D 持久性;redis 只有在 aof 持久化策略的時候,并且需要在 appendfsync=always 才具備持久性;實際項目中幾乎不會使用 redis.conf 中 aof 持久化策略;

  • 面試時候回答:lua 腳本滿足原子性和隔離性;一致性和持久性不滿足;

get zhang ==>100set zhang 200

如果這兩個命令沒有作為一個整體,那么可以會有另一條連接set。這將導致數據不一致。

什么時候探討事務?多條并發連接
什么時候探討原子操作?多核

二、Redis協議與異步方式

2.1 Redis協議解析

2.1.1 redis pipeline

redis pipeline 是一個客戶端提供的機制,而不是服務端提供的;

注意:pipeline 不具備事務性;

目的:節約網絡傳輸時間;

通過一次發送多次請求命令,從而減少網絡傳輸的時間。

image.png

2.1.2 Redis協議圖

image.png

上圖描述了如何界定數據包:

  1. 長度 + 二進制流
  2. 二進制流 + 特殊分割符

2.2 特殊協議操作-訂閱發布

為了支持消息的多播機制,redis引入了發布訂閱:發送者發送消息,訂閱者接收消息。

# 訂閱頻道
subscribe `channel`
# 訂閱模式頻道
psubscribe `channel`
# 取消訂閱頻道
unsubscribe `channel`
# 發布具體頻道或模式頻道的內容
publish `channel` `message`
# 客戶端接收具體頻道內容
message `specificChannel` `message`
# 客戶端接收模式頻道內容
pmessage

應用

  1. 發布訂閱可以收到redis主動推送的內容
  2. 項目中支持發布訂閱,需要另開一條連接

缺點

  1. 生產者傳遞來一條消息,redis找到相應的消費者并傳遞過去,如果沒有消費者,消息丟棄;
  2. 如果有兩個消費者,此時其中一個消費者掛掉了,重連上來將不會接收到該消息;
  3. redis停機重啟,發布訂閱的消息不會持久化。

2.3 異步redis協議

同步連接方案采用阻塞IO來實現
優點:代碼書寫是同步的,業務邏輯不割裂
缺點:阻塞當前線程,直到返回結果,通常需要多個線程來實現線程池來解決效率問題。

異步連接方案采用非阻塞IO來實現
優點:不阻塞當前線程,redis沒有返回,可以繼續向redis發送命令
缺點:代碼書寫是異步的,業務邏輯割裂,可以通過協程解決(skynet,openresty)

2.3.1 hiredis + libevent

我們需要做的事情:
適配

  1. 事件對象
  2. 事件操作函數

hiredis需要做:

  1. 協議解析
  2. 讀寫事件
  3. 緩沖區操作
  4. 協議加密等

適配事件對象和函數。

static int redisAttach(reactor_t *r, redisAsyncContext *ac) {redisContext *c = &(ac->c);redis_event_t *re;/* Nothing should be attached when something is already attached */if (ac->ev.data != NULL)return REDIS_ERR;/* Create container for ctx and r/w events */re = (redis_event_t*)hi_malloc(sizeof(*re));if (re == NULL)return REDIS_ERR;re->ctx = ac;re->e.fd = c->fd;re->e.r = r;// dont use event buffer, using hiredis's bufferre->e.in = NULL;re->e.out = NULL;re->mask = 0;ac->ev.addRead = redisAddRead;ac->ev.delRead = redisDelRead;ac->ev.addWrite = redisAddWrite;ac->ev.delWrite = redisDelWrite;ac->ev.cleanup = redisCleanup;ac->ev.data = re;return REDIS_OK;
}

總結

本文介紹了Redis的基本命令以及Redis協議中的部分內容。Redis是內存型數據庫,圍繞著內存的特性,Redis結合了lua腳本,分布式鎖(最快的),異步連接等一系列特性。

參考鏈接:
https://github.com/0voice

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

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

相關文章

力扣每日一題 - 999. 可以被一步捕獲的棋子數

題目 還需要你前往力扣官網查看詳細的題目要求 地址 1.給定一個 8 x 8 的棋盤&#xff0c;只有一個 白色的車&#xff0c;用字符 R 表示。棋盤上還可能存在白色的象 B 以及黑色的卒 p。空方塊用字符 . 表示。2.車可以按水平或豎直方向&#xff08;上&#xff0c;下&#xff0c;…

[UVM]在UVM環境中加入C++內存模塊

摘要&#xff1a;要在UVM環境中實現一個內存模塊并存入數據&#xff0c;您可以遵循以下步驟。這里會涉及C的內存建模和UVM的SystemVerilog部分的接口。在高層次上&#xff0c;我們將描述如何在C中實現內存模型并通過UVM的DPI接口訪問它。 一、C內存模型 首先&#xff0c;在C中…

學習記錄,正則表達式, 隱式轉換

正則表達式 \\&#xff1a;表示正則表達式 W: 表示一個非字&#xff08;不是一個字&#xff0c;例如&#xff1a;空格&#xff0c;逗號&#xff0c;句號&#xff09; W: 多個非字 基本組成部分 1.字符字面量&#xff1a; 普通字符&#xff1a;在正則表達式中&#xff0c;大…

Selenium是廣泛使用的模擬瀏覽器運行的庫

簡介 Selenium是廣泛使用的模擬瀏覽器運行的庫&#xff0c;它是一個用于Web應用程序測試的工具。 Selenium測試直接運行在瀏覽器中&#xff0c;就像真正的用戶在操作一樣&#xff0c;并且支持大多數現代 Web 瀏覽器。 環境 安裝 pip install selenium下載Chrome驅動 系統環境…

網絡練級寶典-> UDP傳輸層協議

目錄 傳輸層 端口號 端口號和進程的關系 UDP協議 UDP協議格式 UDP數據封裝&#xff1a; UDP數據分用&#xff1a; 面向數據報 UDP的緩沖區 UDP的缺點 基于UDP的應用層協議 傳輸層 端口號 我們知道端口號對應的其實就是一個進程的pid&#xff0c;在操作系統中二者的…

Redis原理—1.Redis數據結構

大綱 1.Redis的數據結構 2.Redis的SDS 3.Redis的鏈表 4.Redis的字典 5.Redis的跳躍表 6.Redis的整數集合 7.Redis的壓縮列表 8.Redis的對象 9.Redis對象的幾個關鍵屬性 10.Redis的單線程為什么這么快 11.Redis的典型應用場景和說明 12.Redis的相關命令說明 1.Redis…

【Vue3中Router使用】

Vue3中Router使用 1. 安裝vue-router組件2. 建兩個測試頁面2.1 測試頁面Home.vue2.2 測試頁面Category.vue 3. 創建路由對象4. 在入口main.js中引入router把App.vue改成路由頁面5. 測試5.1 關閉檢查解決ESlint報錯5.2 改文件名解決ESlint檢查報錯測試WebHashHistory 和WebHisto…

python拆分Excel文件

按Sheet拆分Excel 或 按照某一列的不同值拆分Excel。文檔樣式如下&#xff1a; 結果&#xff1a;紅色是按照Sheet名拆出的&#xff0c;藍色和橙色是某個Sheet按照某列的不同值拆分的。 代碼&#xff1a; # -*- coding: utf-8 -*- """ 拆分excel文件——按照…

交易所 Level-2 歷史行情數據自動化導入攻略

用戶部署完 DolphinDB 后&#xff0c;需要將歷史股票數據批量導入數據庫&#xff0c;再進行數據查詢、計算和分析等操作。DolphinDB 開發了 ExchData 模塊&#xff0c;主要用于滬深交易所 Level-2 行情原始數據的自動化導入&#xff0c;目前已支持的數據源包括&#xff1a; 滬…

開源ISP介紹(2)————嵌入式Vitis搭建

Vivado搭建參考前一節Vivado基于IP核的視頻處理框架搭建&#xff1a; 開源ISP介紹&#xff08;1&#xff09;——開源ISP的Vivado框架搭建-CSDN博客 導出Hardware 在vivado中導出Hardware文件&#xff0c;成功綜合—實現—生成比特流后導出硬件.xsa文件。&#xff08;注意導…

Node.js JWT認證教程

Node.js JWT認證教程 1. 項目介紹 JSON Web Token (JWT) 是一種安全的跨域身份驗證解決方案&#xff0c;在現代Web應用中廣泛使用。本教程將詳細講解如何在Node.js中實現JWT認證。 2. 項目準備 2.1 初始化項目 # 創建項目目錄 mkdir nodejs-jwt-auth cd nodejs-jwt-auth# …

109.【C語言】數據結構之二叉樹層序遍歷

目錄 1.知識回顧 2.代碼實現 準備工作 LevelOrder函數 代碼框架 關鍵代碼 3.執行結果 1.知識回顧 層序遍歷參見106.【C語言】數據結構之二叉樹的三種遞歸遍歷方式文章 截取的部分內容 定義:按層的方式遍歷(,設n為樹的深度,h1-->h2-->h3-->...-->hn) 以下面…

Ruby On Rails 筆記2——表的基本知識

Active Record Basics — Ruby on Rails Guides Active Record Migrations — Ruby on Rails Guides 原文鏈接自取 1.Active Record是什么&#xff1f; Active Record是MVC模式中M的一部分&#xff0c;是負責展示數據和業務邏輯的一層&#xff0c;可以幫助你創建和使用Ruby…

安裝部署PowerDNS--實現內網DNS解析

PDNS是PowerDNS的縮寫&#xff0c;是一個開源的DNS服務器軟件。PowerDNS具有高性能、靈活性和可擴展性&#xff0c;可用于搭建各種規模的DNS解析服務。它支持多種后端數據庫&#xff08;如MySQL、PostgreSQL等&#xff09;&#xff0c;提供高度定制化的配置選項&#xff0c;并具…

13.在 Vue 3 中使用OpenLayers加載鷹眼控件示例教程

在 WebGIS 開發中&#xff0c;鷹眼控件 是一個常用的功能&#xff0c;它可以為用戶提供當前地圖位置的概覽&#xff0c;幫助更好地定位和導航。在本文中&#xff0c;我們將基于 Vue 3 的 Composition API 和 OpenLayers&#xff0c;創建一個簡單的鷹眼控件示例。 效果預覽 在最…

Elasticsearch 單節點安全配置與用戶認證

Elasticsearch 單節點安全配置與用戶認證 安全掃描時發現了一個高危漏洞&#xff1a;Elasticsearch 未授權訪問 。在使用 Elasticsearch 構建搜索引擎或處理大規模數據時&#xff0c;需要啟用基本的安全功能來防止未經授權的訪問。本文將通過簡單的配置步驟&#xff0c;為單節…

使用C#基于ADO.NET編寫MySQL的程序

MySQL 是一個領先的開源數據庫管理系統。它是一個多用戶、多線程的數據庫管理系統。MySQL 在網絡上特別流行。MySQL 數據庫可在大多數重要的操作系統平臺上使用。它可在 BSD Unix、Linux、Windows 或 Mac OS 上運行。MySQL 有兩個版本&#xff1a;MySQL 服務器系統和 MySQL 嵌入…

計算機視覺與各個學科融合:探索新方向

目錄 引言計算機視覺與其他學科的結合 與醫學的結合與機械工程的結合與土木工程的結合與藝術與人文的結合發文的好處博雅知航的輔導服務 引言 計算機視覺作為人工智能領域的重要分支&#xff0c;正迅速發展并滲透到多個學科。通過與其他領域的結合&#xff0c;計算機視覺不僅…

SpringBoot期末知識點大全

一、學什么 IoC AOP&#xff1a;面向切面編程。 事物處理 整合MyBatis Spring框架思想&#xff01; 二、核心概念 問題&#xff1a;類之間互相調用/實現&#xff0c;導致代碼耦合度高。 解決&#xff1a;使用對象時&#xff0c;程序中不主動new對象&#xff0c;轉換為由外部提…

QT模型/視圖:自定義代理類型

簡介 在模型/視圖結構中&#xff0c;代理的作用就是在視圖組件進入編輯狀態編輯某個項時&#xff0c;提供一個臨時的編輯器用于數據編輯&#xff0c;編輯完成后再把數據提交給數據模型。例如&#xff0c;在 QTableView 組件上雙擊一個單元格時&#xff0c;代理會提供一個臨時的…