2.1、預(yù)備

全局命令

  1. 查看所有鍵

    keys *

    下面插入了3對(duì)字符串類型的鍵值對(duì):

    127.0.0.1:6379> set hello world
    OK
    127.0.0.1:6379> set java jedis
    OK
    127.0.0.1:6379> set python redis-py
    OK
    

    key *命令會(huì)將所有的鍵輸出:

    127.0.0.1:6379> key *
    1) "python"
    2) "java"
    3) "hello"
    
  2. 鍵總數(shù)

    dbsize

    下面插入一個(gè)列表類型的鍵值對(duì)(值是多個(gè)元素組成):

    127.0.0.1:6379> rpush mylist a b c d e f g
    (integer) 7
    

    dbsize 命令會(huì)返回當(dāng)前數(shù)據(jù)庫(kù)中鍵的總數(shù)。例如當(dāng)前數(shù)據(jù)庫(kù)有4個(gè)鍵,分別是
    hello、java、python、mylist,所以dbsize的結(jié)果是4:

    127.0.0.1:6379> dbsize
    (integer) 4
    

    dbsize命令在計(jì)算鍵總數(shù)時(shí)不會(huì)遍歷所有的鍵,而是直接獲取Redis內(nèi)置的鍵總
    數(shù)變量,所以dbsize命令的時(shí)間復(fù)雜度是O(1)。而keys命令會(huì)遍歷所有鍵,所
    以它的時(shí)間復(fù)雜度是O(n),當(dāng)Redis保存了大量鍵時(shí),線上環(huán)境禁止使用。

  3. 檢查鍵是否存在

    exists key

    如果鍵存在則返回1,不存在則返回0:

    127.0.0.1:6379> exists java
    (integer) 1
    127.0.0.1:6379> exists not_exists_key
    (integer) 0
    
  4. 刪除鍵

    del key [key ...]

    del是一個(gè)通用命令,無(wú)論值是什么數(shù)據(jù)結(jié)構(gòu)類型,del命令都可以將其刪除,
    例如下面將字符串類型的鍵java和列表類型的鍵mylist分別刪除:

    127.0.0.1:6379> del java
    (integer) 1
    127.0.0.1:6379> exists java
    (integer) 0
    127.0.0.1:6379> del mylist
    (integer) 1
    127.0.0.1:6379> exists mylist
    (integer) 0
    

    返回結(jié)果為成功刪除鍵的個(gè)數(shù),假設(shè)刪除一個(gè)不存在的鍵,就會(huì)返回0:

    127.0.0.1:6379> del not_exists_key
    (integer) 0
    

    同時(shí)del命令可以支持刪除多個(gè)鍵:

    127.0.0.1:6379> set a 1
    OK
    127.0.0.1:6379> set b 2
    OK
    127.0.0.1:6379> set c 3
    OK
    127.0.0.1:6379> del a b c
    (integer) 3
    
  5. 鍵過(guò)期

    expire key seconds

    Redis支持對(duì)鍵添加過(guò)期時(shí)間,當(dāng)超過(guò)過(guò)期時(shí)間后,會(huì)自動(dòng)刪除鍵,例如為鍵
    hello設(shè)置了10秒過(guò)期時(shí)間:

    127.0.0.1:6379> set hello world
    OK
    127.0.0.1:6379> expire hello 10
    (integer) 1
    

    ttl命令返回鍵的生育過(guò)期時(shí)間,它有3中返回值:

    • 大于等于0的整數(shù):鍵剩余的過(guò)期時(shí)間。
    • -1:鍵沒(méi)設(shè)置過(guò)期時(shí)間。
    • -2:鍵不存在

    可以通過(guò)ttl命令觀察鍵hello的剩余過(guò)期時(shí)間:

    # 還剩7秒
    127.0.0.1:6379> ttl hello
    (integer) 7
    ...
    # 還剩1秒
    127.0.0.1:6379> ttl hello
    (integer) 1
    # 返回結(jié)果為-2,說(shuō)明鍵hello已經(jīng)被刪除
    127.0.0.1:6379> ttl hello
    (integer) -2
    127.0.0.1:6379> get hello
    (nil)
    
  6. 鍵的數(shù)據(jù)結(jié)構(gòu)類型

    type key

    例如鍵hello是字符串類型,返回結(jié)果為string。鍵mylist是列表類型,返回
    結(jié)果為list:

    127.0.0.1:6379> set a b
    OK
    127.0.0.1:6379> type a
    string
    127.0.0.1:6379> rpush mylist a b c d e f g
    (integer) 7
    127.0.0.1:6379> type mylist
    list
    

    如果鍵不存在,則返回none:

    127.0.0.1:6379> type not_exists_key
    none
    

數(shù)據(jù)結(jié)構(gòu)和內(nèi)部編碼

  1. 數(shù)據(jù)結(jié)構(gòu)和內(nèi)部編碼

    type命令實(shí)際返回的就是當(dāng)前鍵的數(shù)據(jù)結(jié)構(gòu)類型,他們分別是:string(字符
    串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合),但
    這些只是Redis 對(duì)外的數(shù)據(jù)結(jié)構(gòu)。

    實(shí)際上每種數(shù)據(jù)結(jié)構(gòu)都有自己底層的內(nèi)部編碼實(shí)現(xiàn),而且是多種實(shí)現(xiàn)。

    2019-03-27-23-59-27.png

    可以看到每種數(shù)據(jù)結(jié)構(gòu)都有兩種以上的內(nèi)部編碼實(shí)現(xiàn),可以通過(guò)
    object encoding命令查詢內(nèi)部編碼:

    127.0.0.1:6379> object encoding hello
    "embstr"
    127.0.0.1:6379> object encoding mylist
    "ziplist"
    

    可以看到鍵hello對(duì)應(yīng)值的內(nèi)部編碼是embstr,鍵mylist對(duì)應(yīng)值的內(nèi)部編碼
    是:ziplist。

    Redis這樣設(shè)計(jì)有兩個(gè)有好處:第一,可以改進(jìn)內(nèi)部編碼,而對(duì)外的數(shù)據(jù)結(jié)構(gòu)和
    命令沒(méi)有影響,這樣一旦開(kāi)發(fā)出更優(yōu)秀的內(nèi)部編碼,無(wú)需改動(dòng)外部數(shù)據(jù)結(jié)構(gòu)和
    命令,例如Redis3.2提供了quicklist,結(jié)合了ziplist和linkedlist兩者的
    優(yōu)勢(shì),而列表類型提供了一種更為優(yōu)秀的內(nèi)部編碼實(shí)現(xiàn),而對(duì)外部用戶來(lái)說(shuō)基本
    感知不到。第二,多種內(nèi)部編碼實(shí)現(xiàn)可以在不同場(chǎng)景下發(fā)揮各自優(yōu)勢(shì),例如
    ziplist比較省內(nèi)存,但是在列表元素比較多的情況下,性能會(huì)有所下降,這時(shí)
    候Redis會(huì)根據(jù)配置選項(xiàng)將列表類型的內(nèi)部實(shí)現(xiàn)轉(zhuǎn)換為linkedlist。

單線程架構(gòu)

  1. 引出單線程模型

    現(xiàn)在開(kāi)啟了三個(gè)redis-cli客戶端同事執(zhí)行命令。
    客戶端1設(shè)置一個(gè)字符串鍵值對(duì):

    127.0.0.1:6379> set hello world

    客戶端2對(duì)counter做自增操作:

    127.0.0.1:6379> incr counter

    客戶端3對(duì)counter做自增操作:

    127.0.0.1:6379> incr counter

    Redis每次客戶端調(diào)用都經(jīng)歷了發(fā)送命令、執(zhí)行命令、返回結(jié)果三個(gè)過(guò)程。

    其中第2步是重點(diǎn)研究的,因?yàn)镽edis是單線程來(lái)處理命令的,所以一條命令從
    客戶端達(dá)到服務(wù)端不會(huì)立刻被執(zhí)行,所有命令都會(huì)進(jìn)入一個(gè)隊(duì)列中,然后逐個(gè)
    被執(zhí)行。所以上面3個(gè)客服端命令執(zhí)行順序是不確定的,但是可以確定不會(huì)有
    兩條命令同時(shí)被執(zhí)行,所以兩條incr命令無(wú)論怎么執(zhí)行最終結(jié)果都是2,不會(huì)產(chǎn)
    生并發(fā)問(wèn)題,這就是Redis單線程的基礎(chǔ)模型。但是像發(fā)送命令、返回結(jié)果、命
    令排隊(duì)肯定不像描述的這么簡(jiǎn)單,Redis使用I/O多路復(fù)用技術(shù)解決I/O問(wèn)題。

  2. 為什么單線程還能這么快

    通常來(lái)講,單線程處理能力要比多線程差,Redis使用單線程模型會(huì)達(dá)到每秒萬(wàn)
    級(jí)別的處理能力原因有三點(diǎn):

    1. 純內(nèi)存訪問(wèn),Redis將所有數(shù)據(jù)放在內(nèi)存中,內(nèi)存的響應(yīng)時(shí)長(zhǎng)大約為100納
      秒,這是Redis達(dá)到每秒萬(wàn)級(jí)別訪問(wèn)的重要基礎(chǔ)。

    2. 非阻塞I/O,Redis使用epoll作為I/O多路復(fù)用技術(shù)的實(shí)現(xiàn),再加上Redis
      自身的事件處理模型將epoll中的連接、讀寫(xiě)、關(guān)閉都轉(zhuǎn)換為時(shí)間,不在網(wǎng)絡(luò)
      I/O上浪費(fèi)過(guò)多的時(shí)間。

    3. 單線程避免了線程切換和競(jìng)態(tài)產(chǎn)生的消耗。既然采用單線程就能達(dá)到如此高
      的性能,那么也不失為一種不錯(cuò)的選擇,因?yàn)閱尉€程能帶來(lái)幾個(gè)好處:第一,單
      線程可以簡(jiǎn)化數(shù)據(jù)結(jié)構(gòu)和算法的實(shí)現(xiàn)。如果對(duì)高級(jí)編程語(yǔ)言熟悉的讀者應(yīng)該了解
      并發(fā)數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)不但困難而且開(kāi)發(fā)測(cè)試比較麻煩。第二,單線程避免了線程切
      換和競(jìng)態(tài)產(chǎn)生的消耗,對(duì)于服務(wù)端開(kāi)發(fā)來(lái)說(shuō),鎖和線程切換通常是性能殺手。

    但是單線程會(huì)有一個(gè)問(wèn)題:對(duì)于每個(gè)命令的執(zhí)行時(shí)間是有要求的。如果某個(gè)命令
    時(shí)間執(zhí)行過(guò)長(zhǎng),會(huì)造成其他命令的阻塞,對(duì)于Redis這種高性能的服務(wù)來(lái)說(shuō)是致
    命的,所以Redis是面向快速執(zhí)行場(chǎng)景的數(shù)據(jù)庫(kù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • redis是一個(gè)以key-value存儲(chǔ)的非關(guān)系型數(shù)據(jù)庫(kù)。有五種數(shù)據(jù)類型,string、hashes、list、s...
    林ze宏閱讀 1,111評(píng)論 0 0
  • 前言 Redis的作者antirez(Salvatore Sanfilippo)曾經(jīng)發(fā)表了一篇名為Redis宣言(...
    OzanShareing閱讀 1,596評(píng)論 0 20
  • 重點(diǎn)參考鏈接: http://www.cnblogs.com/wangyuyu/p/3786236.html Re...
    Kevin_Junbaozi閱讀 2,266評(píng)論 0 21
  • 1 Redis介紹1.1 什么是NoSql為了解決高并發(fā)、高可擴(kuò)展、高可用、大數(shù)據(jù)存儲(chǔ)問(wèn)題而產(chǎn)生的數(shù)據(jù)庫(kù)解決方...
    克魯?shù)吕?/span>閱讀 5,726評(píng)論 0 36
  • 很久以前,我習(xí)慣了喜歡一個(gè)人就愛(ài)到骨子里去。 后來(lái)一個(gè)人走了很長(zhǎng)的路,見(jiàn)過(guò)一些人,他們告訴我,喜歡是沒(méi)道理的。 自...
    李迢閱讀 104評(píng)論 0 1

友情鏈接更多精彩內(nèi)容