国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Redis對(duì)象和五種常用數(shù)據(jù)類型

這篇具有很好參考價(jià)值的文章主要介紹了Redis對(duì)象和五種常用數(shù)據(jù)類型。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

Redisobject 對(duì)象

對(duì)象分為鍵對(duì)象和值對(duì)象

鍵對(duì)象一般是string類型

值對(duì)象可以是string,list,set,zset,hash

q:redisobj的結(jié)構(gòu)

typedef struct redisObject {  
    //類型  
    unsigned type:4;  
    //編碼  
    unsigned encoding:4;  
    //指向底層實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)的指針  
    void *ptr;  
    //引用計(jì)數(shù),垃圾回收的時(shí)候使用
    int refcount;
    //最近被使用的時(shí)間,內(nèi)存淘汰的時(shí)候用
     unsigned lru; 
} robj;

q:數(shù)據(jù)類型,編碼和數(shù)據(jù)結(jié)構(gòu)之間的對(duì)應(yīng) 關(guān)系?

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

Redis對(duì)象和數(shù)據(jù)結(jié)構(gòu)的關(guān)系
Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

鍵總是一個(gè)字符串對(duì)象
而值可以是五種中的一種

type 命令 得到的結(jié)果就是值的類型

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存
Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

可以用object encoding命令查看編碼

list數(shù)據(jù)類型的編碼由linkedlist和ziplist編碼合并成了quicklist編碼

q: 通用數(shù)據(jù)類型命令

keys *  //查看當(dāng)前庫所有key    (匹配:keys *1)

exists key //判斷某個(gè)key是否存在,如果鍵存在則返回1,不存在則返回0:

type key //查看你的key是什么類型

del key  //刪除指定的key數(shù)據(jù),del是一個(gè)通用命令,無論值是什么數(shù)據(jù)結(jié)構(gòu)類型,del命令都可以將其 刪除,返回結(jié)果為成功刪除鍵的個(gè)數(shù),假設(shè)刪除一個(gè)不存在的鍵,就會(huì)返回 0

unlink key   //根據(jù)value選擇非阻塞刪除,僅將keys從keyspace元數(shù)據(jù)中刪除,真正的刪除會(huì)在后續(xù)異步操作。

expire key 10   //10秒鐘:為給定的key設(shè)置過期時(shí)間

ttl key //查看還有多少秒過期,-1表示永不過期,-2表示已過期

select number //命令切換數(shù)據(jù)庫

dbsize //查看當(dāng)前數(shù)據(jù)庫的key的數(shù)量

flushdb //清空當(dāng)前庫

flushall //通殺全部庫

命令在執(zhí)行前都會(huì)判斷 參數(shù)是否是自己可以接收,否則會(huì)返回錯(cuò)誤

數(shù)據(jù)類型

string 字符串

q: 特點(diǎn)

其value是字符串,不過根據(jù)字符串的格式不同,又可以分為3類:

  • string:普通字符串

  • int:整數(shù)類型,可以做自增、自減操作

  • float:浮點(diǎn)類型,可以做自增、自減操作

q: 適用場(chǎng)景?

String 的常見應(yīng)用場(chǎng)景如下:

  • 常規(guī)數(shù)據(jù)(比如 session、token、序列化后的對(duì)象、圖片的路徑)的緩存;
  • 計(jì)數(shù)比如用戶單位時(shí)間的請(qǐng)求數(shù)(簡單限流可以用到)、頁面單位時(shí)間的訪問數(shù);
  • 分布式鎖(利用 SETNX key value 命令可以實(shí)現(xiàn)一個(gè)最簡易的分布式鎖);

q:常用命令?

 set  <key> <value> //添加鍵值對(duì)
                                
 
 *NX:當(dāng)數(shù)據(jù)庫中key不存在時(shí),可以將key-value添加數(shù)據(jù)庫
 
 *XX:當(dāng)數(shù)據(jù)庫中key存在時(shí),可以將key-value添加數(shù)據(jù)庫,與NX參數(shù)互斥
 
 *EX:key的超時(shí)秒數(shù)
 
 *PX:key的超時(shí)毫秒數(shù),與EX互斥
 
 
 get  <key> //查詢對(duì)應(yīng)鍵值
 
 append <key> <value> //將給定的<value> 追加到原值的末尾,返回長度
 
 strlen <key> //獲得值的長度
 
 setnx <key> <value> //只有在 key 不存在時(shí)  設(shè)置 key 的值
 
 incr <key> //將 key 中儲(chǔ)存的數(shù)字值增1  只能對(duì)數(shù)字值操作,如果為空,新增值為1
 
 decr <key> //將 key 中儲(chǔ)存的數(shù)字值減1  只能對(duì)數(shù)字值操作,如果為空,新增值為-1
 
 incrby / decrby <key> <步長> //將 key 中儲(chǔ)存的數(shù)字值增減。自定義步長。
 
 mset <key1><value1><key2><value2> ..... //同時(shí)設(shè)置一個(gè)或多個(gè) key-value對(duì) 
 
 mget <key1><key2><key3> .....  //同時(shí)獲取一個(gè)或多個(gè) value 
 
 msetnx <key1><value1><key2><value2> .....  //同時(shí)設(shè)置一個(gè)或多個(gè) key-value 對(duì),當(dāng)且僅當(dāng)所有給定 key 都不存在。 原子性,有一個(gè)失敗則都失敗
 
 getrange <key><起始位置><結(jié)束位置>  //得值的范圍,類似java中的substring,前包,后包
 
 setrange <key><起始位置><value>  //<value> 覆寫<key>所儲(chǔ)存的字符串值,從<起始位置>開始(索引從0開始)。
 
 setex <key><過期時(shí)間><value>  //設(shè)置鍵值的同時(shí),設(shè)置過期時(shí)間,單位秒。
 
 getset <key><value> //以新?lián)Q舊,設(shè)置了新值同時(shí)獲得舊值。

q:底層編碼方式和數(shù)據(jù)結(jié)構(gòu)?

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

  • 當(dāng)存儲(chǔ)的是long 數(shù)字的時(shí)候,使用int編碼,prt直接存儲(chǔ)數(shù)字

不包括浮點(diǎn)數(shù)

  • 當(dāng)存儲(chǔ)的字符串小于44個(gè)字節(jié)的時(shí)候,使用embstr編碼,字符串和redisobject存儲(chǔ)在一起
  • 當(dāng)存儲(chǔ)的字符串大于44個(gè)字節(jié)的時(shí)候,使用raw編碼,prt存儲(chǔ)的是sds的地址指針

set 集合

q: 特點(diǎn)

  • 無序

  • 元素不可重復(fù)

  • 查找快

  • 支持交集、并集、差集等功能

q: 適用場(chǎng)景?

應(yīng)用場(chǎng)景:

  • 需要存放的數(shù)據(jù)不能重復(fù)的場(chǎng)景
    • 不可重復(fù)下單
    • 點(diǎn)贊
  • 需要獲取多個(gè)數(shù)據(jù)源交集、并集和差集的場(chǎng)景
    • 共同好友(交集)、共同粉絲(交集)、共同關(guān)注(交集)、好友推薦(差集)、音樂推薦(差集)、訂閱號(hào)推薦(差集+交集) 等場(chǎng)景。
  • 需要隨機(jī)獲取數(shù)據(jù)源中的元素的場(chǎng)景
    • 抽獎(jiǎng)系統(tǒng)、隨機(jī)點(diǎn)名等場(chǎng)景。
    • 相關(guān)命令:SPOP(隨機(jī)獲取集合中的元素并移除,適合不允許重復(fù)中獎(jiǎng)的場(chǎng)景)、SRANDMEMBER(隨機(jī)獲取集合中的元素,適合允許重復(fù)中獎(jiǎng)的場(chǎng)景)。

q:常用命令?

sadd <key><value1><value2> .....  //將一個(gè)或多個(gè) member 元素加入到集合 key 中,已經(jīng)存在的 member 元素將被忽略

smembers <key>  //取出該集合的所有值。

sismember <key><value> //判斷集合<key>是否為含有該<value>值,有1,沒有0

scard<key> //返回該集合的元素個(gè)數(shù)。

srem <key><value1><value2> .... //刪除集合中的某個(gè)元素。

spop <key> //隨機(jī)從該集合中吐出一個(gè)值。

srandmember <key><n> //隨機(jī)從該集合中取出n個(gè)值。不會(huì)從集合中刪除 。

smove <source><destination>value //把集合中一個(gè)值從一個(gè)集合移動(dòng)到另一個(gè)集合

sinter <key1><key2> //返回兩個(gè)集合的交集元素。

sunion <key1><key2> //返回兩個(gè)集合的并集元素。

sdiff <key1><key2> //返回兩個(gè)集合的差集元素(key1中的,不包含key2中的)

q:底層編碼方式和數(shù)據(jù)結(jié)構(gòu)?

  • 當(dāng)存儲(chǔ)的所有數(shù)據(jù)都是整數(shù),元素?cái)?shù)量不超過set-max-intset-entries時(shí),Set會(huì)采用IntSet編碼,以節(jié)省內(nèi)存,底層數(shù)據(jù)結(jié)構(gòu)是intset
  • 當(dāng)存儲(chǔ)的所有數(shù)據(jù)不都是整數(shù),或元素?cái)?shù)量超過set-max-intset-entries時(shí),set采用hashtable編碼,底層是Dict中的key用來存儲(chǔ)元素,value統(tǒng)一為null。
    Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

hash 哈希

q: 特點(diǎn)

hash也叫散列, 是一個(gè)鍵值對(duì)集合。

q: 適用場(chǎng)景?

hash特別適合用于存儲(chǔ)對(duì)象。

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

q:常用命令?

hset <key><field><value> <field2><value2>  //<key>集合中的 <field>鍵賦值<value>

hget <key1><field> //<key1>集合<field>取出 value

hmset <key1><field1><value1><field2><value2>... //批量設(shè)置hash的值,hmset被棄用,可以用hset做到

hexists<key1><field> //查看哈希表 key 中,給定域 field 是否存在。

hkeys <key> //列出該hash集合的所有field

hvals <key> //列出該hash集合的所有value

hincrby <key><field><increment> //為哈希表 key 中的域 field 的值加上增量 1  -1

hsetnx <key><field><value> //將哈希表 key 中的域 field 的值設(shè)置為 value ,當(dāng)且僅當(dāng)域 field 不存在 .

q:底層編碼方式和數(shù)據(jù)結(jié)構(gòu)?

  • Hash結(jié)構(gòu)默認(rèn)采用ZipList編碼,用以節(jié)省內(nèi)存。 ZipList中相鄰的兩個(gè)entry 分別保存field和value;底層數(shù)據(jù)結(jié)構(gòu)式ziplist

  • 當(dāng)數(shù)據(jù)量較大時(shí),Hash結(jié)構(gòu)會(huì)轉(zhuǎn)為hashtable編碼,底層數(shù)據(jù)結(jié)構(gòu)是Dict,觸發(fā)條件有兩個(gè):

    • ZipList中的元素?cái)?shù)量超過了hash-max-ziplist-entries(默認(rèn)512)
    • ZipList中的任意entry大小超過了hash-max-ziplist-value(默認(rèn)64字節(jié))

節(jié)點(diǎn)過多,或單個(gè)節(jié)點(diǎn)過大

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

zset/sorted set 有序集合

q: 特點(diǎn)

  • 無重復(fù)
  • 有序

每個(gè)成員都關(guān)聯(lián)了一個(gè)評(píng)分(score),這個(gè)評(píng)分(score)被用來按照從最低分到最高分的方式排序集合中的成員。
集合的成員是唯一的,但是評(píng)分可以是重復(fù)了 。

q: 適用場(chǎng)景?

適合范圍或者排序的應(yīng)用場(chǎng)景:

  • 排行榜

q:常用命令?

zadd <key><score1><value1><score2><value2>//將一個(gè)或多個(gè) member 元素及其 score 值加入到有序集 key 當(dāng)中。

zrange <key><start><stop> [WITHSCORES] //返回有序集 key 中,下標(biāo)在<start><stop>之間的元素,帶WITHSCORES,可以讓分?jǐn)?shù)一起和值返回到結(jié)果集。

zrangebyscore key minmax [withscores] [limit offset count] //返回有序集 key 中,所有 score 值介于 min 和 max 之間(包括等于 min 或 max )的成員。有序集成員按 score 值遞增(從小到大)次序排列。 

zrevrangebyscore key maxmin [withscores] [limit offset count]        //同上,改為從大到小排列。 

zincrby <key><increment><value>  // 為元素的score加上增量

zrem <key><value> //刪除該集合下,指定值的元素 

zcount <key><min><max> //統(tǒng)計(jì)該集合,分?jǐn)?shù)區(qū)間內(nèi)的元素個(gè)數(shù) 

zrank <key><value> //返回該值在集合中的排名,從0開始。

q:底層編碼方式和數(shù)據(jù)結(jié)構(gòu)?

  • 當(dāng)滿足下面條件時(shí),采用ziplist編碼,底層數(shù)據(jù)結(jié)構(gòu)是ziplist
    • 元素?cái)?shù)量小于zset_max_ziplist_entries,默認(rèn)值128
    • 每個(gè)元素都小于zset_max_ziplist_value字節(jié),默認(rèn)值64

ziplist本身沒有排序功能,而且沒有鍵值對(duì)的概念,因此需要有zset通過編碼實(shí)現(xiàn):
- ZipList是連續(xù)內(nèi)存,因此score和element是緊挨在一起的兩個(gè)entry, element在前,score在后
- score越小越接近隊(duì)首,score越大越接近隊(duì)尾,按照score值升序排列
Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

  • 否則采用zset編碼,底層是zset數(shù)據(jù)結(jié)構(gòu),zset的數(shù)據(jù)結(jié)構(gòu)又指向skiplist和dict

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

  • SkipList:可以排序,并且可以同時(shí)存儲(chǔ)score和ele值(member)
  • Dict:可以鍵值存儲(chǔ),并且可以根據(jù)key找value,實(shí)現(xiàn)O(1)的查找

二者實(shí)際上共用對(duì)象,不會(huì)造成內(nèi)存的浪費(fèi)

list 列表

q: 特點(diǎn)

雙向鏈表結(jié)構(gòu)。既可以支持正向檢索和也可以支持反向檢索。

特征也與LinkedList類似:

  • 單鍵多值
  • 有序
  • 元素可以重復(fù)
  • 插入和刪除快
  • 查詢速度一般

q: 適用場(chǎng)景?

應(yīng)用場(chǎng)景:

  • 常用來存儲(chǔ)一個(gè)有序數(shù)據(jù),例如:朋友圈點(diǎn)贊列表,評(píng)論列表等。
  • 可以用來做消息隊(duì)列,只是功能過于簡單且存在很多缺陷,不建議這樣做。

q:常用命令?

lpush/rpush <key><value1><value2><value3>  //.... 從左邊/右邊插入一個(gè)或多個(gè)值。lpush是頭插法

lpop/rpop <key> //從左邊/右邊吐出一個(gè)值。值在鍵在,值光鍵亡。


rpoplpush <key1><key2><key1> //列表右邊吐出一個(gè)值,插到<key2>列表左邊。


lrange <key><start><stop> //按照索引下標(biāo)獲得元素(從左到右)

lrange <key> 0 -1  //0左邊第一個(gè),-1右邊第一個(gè),(0 -1表示獲取所有)

lindex <key><index> //按照索引下標(biāo)獲得元素(從左到右)

llen <key> //獲得列表長度 

linsert <key> before/after <value><newvalue> //<value>的前面、后面插入<newvalue>插入值

lrem <key><n><value> //從左邊刪除n個(gè)value(從左到右)

lset<key><index><value> //將列表key下標(biāo)為index的值替換成value

q:底層編碼方式和數(shù)據(jù)結(jié)構(gòu)?

  • List的編碼方式是quicklist,底層數(shù)據(jù)結(jié)構(gòu)為快速鏈表quickList,quicklist的節(jié)點(diǎn)又指向了ziplist

Redis 3.2 之前,List 底層實(shí)現(xiàn)是 LinkedList 或者 ZipList。 Redis 3.2 之后,引入了 LinkedList 和 ZipList 的結(jié)合 QuickList,List 的底層實(shí)現(xiàn)變?yōu)?QuickList。

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存文章來源地址http://www.zghlxwxcb.cn/news/detail-652164.html

首先在列表元素較少的情況下會(huì)使用一塊連續(xù)的內(nèi)存存儲(chǔ),這個(gè)結(jié)構(gòu)是ziplist,也即是壓縮列表。(它將所有的元素緊挨著一起存儲(chǔ),分配的是一塊連續(xù)的內(nèi)存。)

當(dāng)數(shù)據(jù)量比較多的時(shí)候才會(huì)改成quicklist。

因?yàn)槠胀ǖ逆湵硇枰母郊又羔樋臻g太大,會(huì)比較浪費(fèi)空間。比如這個(gè)列表里存的只是int類型的數(shù)據(jù),結(jié)構(gòu)上還需要兩個(gè)額外的指針prev和next。

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

Redis將鏈表和ziplist結(jié)合起來組成了quicklist。也就是將多個(gè)ziplist使用雙向指針串起來使用。這樣既滿足了快速的插入刪除性能,又不會(huì)出現(xiàn)太大的空間冗余。

數(shù)據(jù)結(jié)構(gòu)

sds 簡單動(dòng)態(tài)字符串

q:sds的結(jié)構(gòu)

sds的結(jié)構(gòu)

struct sdshdr { 
//記錄buf數(shù)組中已使用字節(jié)的數(shù)量 
//等于SDS所保存字符串的長度 
int len; 
//記錄buf數(shù)組中未使用字節(jié)的數(shù)量
int free;
//字節(jié)數(shù)組,用于保存字符串
char buf[];
};

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

q: sds和c字符串的區(qū)別

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

相同點(diǎn):

  • 都是用char數(shù)組來記錄字符,最后都有一個(gè)\0來代表字符串結(jié)束

sds最后也用\0代表結(jié)束,是為了重用c語言字符串的一些函數(shù),例如printf打印,而不用重寫所有的函數(shù)

不同點(diǎn)

肯定是c語言字符串存在一定的缺陷,redis才會(huì)重寫,那么這些既是redis和c語言字符串的不同點(diǎn),也是redis sds的優(yōu)點(diǎn)

  • 常數(shù)級(jí)別獲取字符串長度,sds獲取字符串長度的時(shí)間復(fù)雜度是O(1),c語言是O(n),通過len的冗余存儲(chǔ)來實(shí)現(xiàn)
  • 杜絕緩沖區(qū)溢出,字符串在拼接之前可以做內(nèi)存檢查,確??臻g充足,否則進(jìn)行擴(kuò)充;不會(huì)像c語言一樣造成內(nèi)存溢出
  • 減少修改字符串時(shí)帶來的內(nèi)存重分配次數(shù),預(yù)分配空間free,來減少內(nèi)存重分配的次數(shù),可以提升性能
  • 二進(jìn)制安全,c語言字符串通過\0空字符來標(biāo)志字符串結(jié)束,因此不能包含空字符;而sds通過len來表示字符串結(jié)束,可以包含空字符,可以存儲(chǔ)圖片等二進(jìn)制信息,因此是二進(jìn)制安全的

q: 容量擴(kuò)充機(jī)制?

如圖中所示,內(nèi)部為當(dāng)前字符串實(shí)際分配的空間capacity一般要高于實(shí)際字符串長度len。

  • 當(dāng)字符串長度小于1M時(shí),擴(kuò)容都是加倍現(xiàn)有的空間
  • 如果超過1M,擴(kuò)容時(shí)一次只會(huì)多擴(kuò)1M的空間。需要注意的是字符串最大長度為512M。

intset 正數(shù)集合

q: intset的結(jié)構(gòu)

typedef struct intset {  
    //編碼方式  
    uint32_t encoding;  
    //集合包含的元素?cái)?shù)量  
    uint32_t length;  
    //保存元素的數(shù)組  
    int8_t contents[];  
} intset;
  • 數(shù)組升序排列
  • 沒有重復(fù)
    Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

q: 如何升級(jí)?

當(dāng)新元素很大的時(shí)候,集合要升級(jí)成更大的編碼方式
升級(jí)整數(shù)集合并添加新元素共分為三步進(jìn)行:
1)根據(jù)新元素的類型,擴(kuò)展整數(shù)集合底層數(shù)組的空間大小,并為新元素分配空間。
2)將底層數(shù)組現(xiàn)有的所有元素都轉(zhuǎn)換成與新元素相同的類型,并將類型轉(zhuǎn)換后的元素放置到正確的位上,而且在放置元素的過程中,需要繼續(xù)維持底層數(shù)組的有序性質(zhì)不變。
3)將新元素添加到底層數(shù)組里面。

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存
Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

?升級(jí)操作為整數(shù)集合帶來了操作上的靈活性,并且盡可能地節(jié)約了內(nèi)存。
?整數(shù)集合只支持升級(jí)操作,不支持降級(jí)操作。

dictht 哈希表

typedef struct dictht {  
    //哈希表數(shù)組  
    dictEntry **table;  
    //哈希表大小  
    unsigned long size;  
    //哈希表大小掩碼,用于計(jì)算索引值  
    //總是等于size-1  
    unsigned long sizemask;  
    //該哈希表已有節(jié)點(diǎn)的數(shù)量  
    unsigned long used;  
} dictht;

哈希表結(jié)點(diǎn)

typedef struct dictEntry {  
    //鍵  
    void *key;  
    //值  
    union{  
        void *val;  
        uint64_tu64;  
        int64_ts64;  
    } v;  
    //指向下個(gè)哈希表節(jié)點(diǎn),形成鏈表  
    struct dictEntry *next;  
} dictEntry;

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

q:如何解決哈希沖突?

用拉鏈法的頭插法解決哈希沖突
Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

dict 字典

typedef struct dict {  
    //類型特定函數(shù)  
    dictType *type;  
    //私有數(shù)據(jù)  
    void *privdata;  
    //哈希表  
    dictht ht[2];  
    // rehash索引  
    //當(dāng)rehash不在進(jìn)行時(shí),值為-1  
    in trehashidx; /* rehashing not in progress if rehashidx == -1 */  
} dict;

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

ht有兩個(gè),一般只使用第一個(gè),第二個(gè)哈希表只在rehash的時(shí)候用

插入數(shù)據(jù)的時(shí)候,先計(jì)算哈希值,再計(jì)算索引值,再插入到指定位置

q : 如何rehash?

隨著操作的不斷執(zhí)行,哈希表保存的鍵值對(duì)會(huì)逐漸地增多或者減少,為了讓哈希表的負(fù)載因子(load factor)維持在一個(gè)合理的范圍之內(nèi),當(dāng)哈希表保存的鍵值對(duì)數(shù)量太多或者太少時(shí),程序需要對(duì)哈希表的大小進(jìn)行相應(yīng)的擴(kuò)展或者收縮。

擴(kuò)展和收縮哈希表的工作可以通過執(zhí)行rehash(重新散列)操作來完成,Redis對(duì)字典的哈希表執(zhí)行rehash的步驟如下:

1)為字典的ht[1]哈希表分配空間,這個(gè)哈希表的空間大小取決于要執(zhí)行的操作,以及ht[0]當(dāng)前包含的鍵值對(duì)數(shù)量(也即是ht[0].used屬性的值):
?如果執(zhí)行的是擴(kuò)展操作,那么ht[1]的大小為第一個(gè)大于等于ht[0].used*2的2 n(2的n次方冪);
?如果執(zhí)行的是收縮操作,那么ht[1]的大小為第一個(gè)大于等于ht[0].used的2 n。

2)將保存在ht[0]中的所有鍵值對(duì)rehash到ht[1]上面:rehash指的是重新計(jì)算鍵的哈希值和索引值,然后將鍵值對(duì)放置到ht[1]哈希表的指定位置上。

3)當(dāng)ht[0]包含的所有鍵值對(duì)都遷移到了ht[1]之后(ht[0]變?yōu)榭毡恚尫舎t[0],將ht[1]設(shè)置為ht[0],并在ht[1]新創(chuàng)建一個(gè)空白哈希表,為下一次rehash做準(zhǔn)備。

為ht[1]分配空間,復(fù)制ht[0]的數(shù)據(jù)到ht[1],釋放ht[0],把ht[1]設(shè)為ht[0],ht[1]創(chuàng)建一個(gè)空哈希表
Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存
Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存
Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存
Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

q:什么時(shí)候rehash

哈希表的擴(kuò)展與收縮
哈希表的擴(kuò)展與收縮當(dāng)以下條件中的任意一個(gè)被滿足時(shí),程序會(huì)自動(dòng)開始對(duì)哈希表執(zhí)行擴(kuò)展操作:
1)服務(wù)器目前沒有在執(zhí)行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表的負(fù)載因子大于等于1。
2)服務(wù)器目前正在執(zhí)行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表的負(fù)載因子大于等于5。

為什么rehash是漸進(jìn)式?

如果ht[0]的數(shù)據(jù)非常多,那么把數(shù)據(jù)全部轉(zhuǎn)移到ht[1]將會(huì)非常耗費(fèi)時(shí)間,因此這個(gè)過程是分多次,漸進(jìn)式完成的
rehashidx記錄了正在轉(zhuǎn)移的索引下標(biāo),當(dāng)轉(zhuǎn)移完成,會(huì)置為-1

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存
Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存
Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存
Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存
因?yàn)樵谶M(jìn)行漸進(jìn)式rehash的過程中,字典會(huì)同時(shí)使用ht[0]和ht[1]兩個(gè)哈希表,所以在漸進(jìn)式rehash進(jìn)行期間,字典的刪除(delete)、查找(find)、更新(update)等操作會(huì)在兩個(gè)哈希表上進(jìn)行。例如,要在字典里面查找一個(gè)鍵的話,程序會(huì)先在ht[0]里面進(jìn)行查找,如果沒找到的話,就會(huì)繼續(xù)到ht[1]里面進(jìn)行查找,諸如此類。

另外,在漸進(jìn)式rehash執(zhí)行期間,新添加到字典的鍵值對(duì)一律會(huì)被保存到ht[1]里面,而ht[0]則不再進(jìn)行任何添加操作,這一措施保證了ht[0]包含的鍵值對(duì)數(shù)量會(huì)只減不增,并隨著rehash操作的執(zhí)行而最終變成空表。

ziplist 壓縮列表

q: ziplist的結(jié)構(gòu)?

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存
每個(gè)壓縮列表節(jié)點(diǎn)可以保存一個(gè)字節(jié)數(shù)組或者一個(gè)整數(shù)值

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

q: ziplist過大的時(shí)候有什么缺點(diǎn)?

當(dāng)ziplist變得很?的時(shí)候,它有如下幾個(gè)缺點(diǎn):

  • 每次插?或修改引發(fā)的realloc操作會(huì)有更?的概率造成內(nèi)存拷貝,從而降低性能。
  • ?旦發(fā)生內(nèi)存拷貝,內(nèi)存拷貝的成本也相應(yīng)增加,因?yàn)橐截惛?的?塊數(shù)據(jù)。
  • 當(dāng)ziplist數(shù)據(jù)項(xiàng)過多的時(shí)候,在它上?查找指定的數(shù)據(jù)項(xiàng)就會(huì)性能變得很低,因?yàn)閦iplist上的查找需要進(jìn)行遍歷。

skiplist 跳表

skiplist是多層級(jí)不同跨度的鏈表

q: skiplist的結(jié)構(gòu)?

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

zsikpList

typedef struct zskiplist {  
    //表頭節(jié)點(diǎn)和表尾節(jié)點(diǎn)  
    structz skiplistNode *header, *tail;  
    //表中節(jié)點(diǎn)的數(shù)量  
    unsigned long length;  
    //表中層數(shù)最大的節(jié)點(diǎn)的層數(shù)  
    int level;  
} zskiplist;

zskipListNode

typedef struct zskiplistNode {  
    //層  
    struct zskiplistLevel {  
        //前進(jìn)指針  
        struct zskiplistNode *forward;  
        //跨度  
        unsigned int span;  
    } level[];  
    //后退指針  
    struct zskiplistNode *backward;  
    //分值  
    double score;  
    //成員對(duì)象  
    robj *obj;  
} zskiplistNode;

每個(gè)結(jié)點(diǎn)的成員對(duì)象是唯一的,但是分值可以相同,分值相同就按照成員對(duì)象由小到大排序,整個(gè)鏈表都是按照分值由小到大排序

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

q: skiplist如何遍歷?

遍歷:
首先遍歷高層級(jí)跨度大的指針,如果過大,就遍歷下一層級(jí)

zset

q:zset的結(jié)構(gòu)?

typedef struct zset {  
    zskiplist *zsl;  
    dict *dict;  
} zset;

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

  • SkipList:可以排序,并且可以同時(shí)存儲(chǔ)score和ele值(member)
  • Dict:可以鍵值存儲(chǔ),并且可以根據(jù)key找value,實(shí)現(xiàn)O(1)的查找

二者實(shí)際上共用對(duì)象,不會(huì)造成內(nèi)存的浪費(fèi)

quicklist 快表

q:quicklist的結(jié)構(gòu)

quicklist 實(shí)際上是 zipList 和 linkedList 的混合體,它將 linkedList 按段切分,每一段使用 zipList 來緊湊存儲(chǔ),多個(gè) zipList 之間使用雙向指針串接起來。

Redis對(duì)象和五種常用數(shù)據(jù)類型,Redis,redis,數(shù)據(jù)庫,緩存

typedef struct quicklist {  
    quicklistNode *head;  
    quicklistNode *tail;  
    unsigned long count;        /* total count of all entries in all ziplists */  
    unsigned long len;           
} quicklist;
typedef struct quicklistNode {  
    struct quicklistNode *prev; //上一個(gè)node節(jié)點(diǎn)  
    struct quicklistNode *next; //下一個(gè)node  
    unsigned char *zl;            //保存的數(shù)據(jù) 壓縮前ziplist 壓縮后壓縮的數(shù)據(jù)  
    unsigned int sz;             /* ziplist size in bytes */  
    unsigned int count : 16;     /* count of items in ziplist */  

} quicklistNode;

到了這里,關(guān)于Redis對(duì)象和五種常用數(shù)據(jù)類型的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Redis的五種基本數(shù)據(jù)類型

    簡介:String 是 Redis 最基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)類型,它是二進(jìn)制安全的,可以存儲(chǔ)圖片 或者序列化的對(duì)象,值最大存儲(chǔ)為 512M 簡單使用舉例: set key value、get key等 應(yīng)用場(chǎng)景:共享 session、分布式鎖,計(jì)數(shù)器、限流。 內(nèi)部編碼有 3 種,int(8字節(jié)長整型)/embstr(小于等于 39字節(jié)字符串)

    2024年04月12日
    瀏覽(31)
  • redis 的基本介紹以及 五種 數(shù)據(jù)類型

    redis 的基本介紹以及 五種 數(shù)據(jù)類型

    一句話:redis 是一個(gè)開源的、使用C語言編寫的、支持網(wǎng)絡(luò)交互,基于內(nèi)存也可持久化的 key-value (非關(guān)系型)數(shù)據(jù)庫 redis作者博客,有興趣的小伙伴可以去逛一逛:http://github.com/antirez 關(guān)于key 的命名,不要太長也不要太短,Key太長越占資源,太短可讀性又很差,key 之間的單詞

    2024年02月11日
    瀏覽(24)
  • Redis_五種數(shù)據(jù)類型及操作命令

    5.1.1 簡介 String類型在redis中最常見的一種類型 string類型是二制安全的,可以存放字符串、數(shù)值、json、圖像數(shù)據(jù) value存儲(chǔ)最大數(shù)據(jù)量是512M 5.1.2 常用命令 set key value:添加鍵值對(duì)(下面指令可以再后添加) nx:當(dāng)數(shù)據(jù)庫中key不存在時(shí),可以將key-value添加到數(shù)據(jù)庫 xx: 當(dāng)數(shù)據(jù)庫key存在

    2024年02月13日
    瀏覽(20)
  • Redis精品小案例:Redis支持五種基本數(shù)據(jù)類型及案例解析

    Redis支持五種基本數(shù)據(jù)類型,分別是:string(字符串)、hash(哈希)、list(列表)、set(集合)及zset(sorted set:有序集合)。以下是這些數(shù)據(jù)類型及其用法的簡要說明: String(字符串) : 是Redis最基本的數(shù)據(jù)類型,你可以理解為與Memcached一模一樣的類型,一個(gè)key對(duì)應(yīng)一個(gè)va

    2024年04月08日
    瀏覽(22)
  • 【分享】Redis的五種基本數(shù)據(jù)類型和應(yīng)用場(chǎng)景

    【分享】Redis的五種基本數(shù)據(jù)類型和應(yīng)用場(chǎng)景

    Redis支持五種基本數(shù)據(jù)類型: String(字符串類型):可以是普通字符串,也可以是整數(shù)或浮點(diǎn)數(shù)值??梢栽O(shè)置過期時(shí)間;可以對(duì)字符串進(jìn)行append、get、set、incr、decr等操作。 Hash(哈希類型):類似于一個(gè)數(shù)組,其中每個(gè)元素都是一個(gè)field和value的鍵值對(duì)??梢詫?duì)整個(gè)哈希表或

    2024年02月16日
    瀏覽(16)
  • Redis的五種數(shù)據(jù)類型(string、hash 、list、set、zset)

    Redis的五種數(shù)據(jù)類型(string、hash 、list、set、zset)

    ???????? ????????Redis 提供了豐富的數(shù)據(jù)類型,常見的有五種: String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合) 。 ????????String 是最基本的 key-value 結(jié)構(gòu),key 是唯一標(biāo)識(shí),value 是具體的值,value其實(shí)不僅是字符串, 也可以是數(shù)字(整

    2024年01月25日
    瀏覽(26)
  • Redis五種類型

    Redis五種類型

    應(yīng)用場(chǎng)景 緩存功能:string 最常用的就是緩存功能,會(huì)將一些更新不頻繁但是查詢頻繁的數(shù)據(jù)緩存起來,以此來減輕 DB 的壓力。 底層實(shí)現(xiàn) 如果字符串對(duì)象保存的是一個(gè)字符串值, 并且這個(gè)字符串值的長度大于 44 字節(jié), 那么字符串對(duì)象將使用一個(gè)簡單動(dòng)態(tài)字符串(SDS)來保

    2024年02月11日
    瀏覽(22)
  • Redis常用數(shù)據(jù)類型及常用命令

    Redis常用數(shù)據(jù)類型及常用命令

    服務(wù)端運(yùn)行 配置文件需要輸入完整地址 連接數(shù)據(jù)庫 設(shè)置數(shù)據(jù)庫密碼 編輯 redis.windows.conf 文件 帶端口密碼地址連接數(shù)據(jù)庫 利用可視化工具連接redis 連接前需啟動(dòng)服務(wù)端 地址: https://gitee.com/qishibo/AnotherRedisDesktopManager/releases 字符串操作命令 哈希操作命令 列表操作命令 集合操

    2024年02月11日
    瀏覽(19)
  • Redis常用數(shù)據(jù)類型

    Redis常用數(shù)據(jù)類型

    Redis hash 是一個(gè) string 類型的 field(字段) 和 value(值) 的映射表,hash 特別適合用于存儲(chǔ)對(duì)象。 Redis 中每個(gè) hash 可以存儲(chǔ) 232 - 1 鍵值對(duì)(40多億) 它的value就是一個(gè)hash類型,而hash類型的結(jié)構(gòu)key value形式。一般用于存放對(duì)象數(shù)據(jù)。 Redis列表是簡單的字符串列表,按照插入順序

    2024年02月12日
    瀏覽(19)
  • Redis常用數(shù)據(jù)類型和使用場(chǎng)景

    Redis常用數(shù)據(jù)類型和使用場(chǎng)景

    Redis目前支持5種數(shù)據(jù)類型,分別是: ? ? String(字符串) List(列表) Hash(字典) Set(集合) Sorted Set(有序集合) 下面就分別介紹這五種數(shù)據(jù)類型及其相應(yīng)的操作命令。 ? 1. String(字符串) String是簡單的 key-value 鍵值對(duì),value 不僅可以是 String,也可以是數(shù)字。String在r

    2024年02月16日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包