<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 一、Redis 鍵(Key) 構成 ```C typedef struct redisObject { unsigned type:4;//類型 五種對象類型 REDIS_STRING(字符串)、REDIS_LIST (列表)、REDIS_HASH(哈希)、REDIS_SET(集合)、REDIS_ZSET(有序集合)。 unsigned encoding:4; //編碼 4表示位數 void *ptr;//指向底層實現數據結構的指針,指向具體數據 //... int refcount;//引用計數 //... unsigned lru:LRU_BITS; //LRU_BITS為24bit 記錄最后一次被命令程序訪問的時間 ? ? ? ?//高16位存儲一個分鐘數級別的時間戳; 低8位存儲訪問計數; lfu; 最近訪問次數; //... } robj; ``` 1. 查看對象類型 `type key` :-: ![](https://img.kancloud.cn/e2/24/e224a038150723629b35b7ee13966fec_322x70.png) 2. 獲取value具體編碼 `object encoding key` :-: ![](https://img.kancloud.cn/be/72/be726c092b7c2587c02f0a84f854ec63_704x210.png) > 可以看出,value為string類型的,編碼可以有3種:`embstr`,`int`,`raw`;當字符串長度大于44(整個sds總體超過64)時,就用raw存儲。sds結構自身占用19個字節,字符串結尾標識"\\0"占一個字節,所以**64 - 19 -1 = 44** 3. 查看key的結構信息 `debug object key` :-: ![](https://img.kancloud.cn/e0/ce/e0ce3560159b4f3105f486306c1e50d3_831x122.png) ## 二、Redis二進制安全 1. 什么是二進制安全? 二進制安全就是指,在傳輸數據時,保證二進制數據的信息安全,即不被篡改、破譯等。簡單來說,就是只關心二進制化的字符串,不關心具體格式,只會嚴格的按照二進制數據存取,不會妄圖以某種特殊格式解析數據。例如:在C語言中,就以"\\0"來判定字符串的結尾。 2. Redis是如何保證二進制安全的? ~~~c struct sdshdr{ ? ? ? ?int len;//buf數組中已經使用的字節的數量,也就是SDS字符串長度 ? ? ? ?int ?free;//buf數組中未使用的字節的數量 ? ? ? ?char buf[];//字節數組,字符串就保存在這里面 }; ~~~ Redis 通過定義上述結構體的方式,擴展了C語言底層字符串的缺點;不再像C語言那樣,以"\\0"作為字符串的結尾,而是使用了獨立的`len`字段來表示字符串的長度。這樣就避免了如果字符串中出現"\\0"而被截取忽略后面字符串的問題;保證了二進制安全。 > 基于此,Redis的string可以支持各種類型(圖片、視頻、文本等);而C語言的字符串就只能存儲文本格式的數據。 :-: ![](https://img.kancloud.cn/98/c0/98c03487d8feec3f54d5a9dfff2bac87_709x245.png) 3. Redis的簡單動態字符串SDS對比C語言中的字符串char,有什么優勢? * 可以在O(1)的時間復雜度得到字符串的長度 (sds結構中,len字段直接記錄了長度) * 二進制安全 * 可以高效的追加字符串操作 原理:sds會判斷當前字符串空余(free)的長度與需要追加的字符串長度;如果空余大于需要追加,就會直接追加,減少了重新分配內存的操作;如果空余小于需要追加,那么就先對sds進行擴展,然后再追加;只是這里擴展內存是按照一定的機制進行的,擴展后多余的空間不釋放,方便下次追加字符串,會造成一定的內存浪費,但是在頻繁追加操作下,這種機制就很高效。 4. 1. SDS 內存擴展機制 在已經分配的內存低于1M時,每次擴容都是以現有內存2倍的方式擴容;當超過1M時,每次只擴容1M ## 三、5種基本數據類型 ### 1、字符串—string 1). 常見命令 ~~~ set get | mset mget | setrange getrange | getset | append | strlen ? incr decr | incr by decrby | ? setbit getbit | bitcount | bitop | bitpos ~~~ 2). 使用場景 * 計數器。如:文章瀏覽數、帖子點贊數等 ~~~ incr article:100.view # ID為100的文章,每打開一次,瀏覽次數增加1 ~~~ * 分布式鎖。如:秒殺活動中,商品庫存問題 ~~~ set goods:100 1 EX 30 NX # 當key goods:100 不存在時拿到鎖,并設置過期時間為30s ~~~ * 緩存。如果:熱點數據的緩存 ~~~ set hotgoods:100 '{"id":100, "price": 998, "title": "鳥哥筆記"}' # 緩存熱賣書籍基本信息 ~~~ * 活躍用戶數統計 ~~~ # 假如:某東 618 活動,需要為用戶準備禮品;現需要統計最近三天活躍用戶,用于備貨 # 通過bitmap,以日期為key記錄用戶的登錄,然后拿對應日期做與運算,就很容易實現 ? setbit 20210615 10 1 ?# 6月15號,ID為10的用戶登錄 setbit 20210615 8 1 ? # 6月15號,ID為8的用戶登錄 ? setbit 20210616 10 1 ?# 6月16號,ID為10的用戶登錄 setbit 20210616 15 1 ?# 6月16號,ID為15的用戶登錄 setbit 20210616 5 1 ? # 6月16號,ID為5的用戶登錄 ? setbit 20210617 15 1 ?# 6月17號,ID為15的用戶登錄 setbit 20210617 13 1 ?# 6月17號,ID為13的用戶登錄 ? # 可以看出15、16、17號這三天,總共有5位用戶活躍 bitop or mau 20210615 20210616 20210617 # 會將計算結果以mau作為key存儲 bitcount mau # 結果為5 ~~~ :-: ![](https://img.kancloud.cn/ce/ae/ceaee83a946a59a1f204e4a75ea3ce26_734x389.png) * 用戶登錄天數統計 ```bash # 需求:需要統計某個用戶某個時間段的登錄天數 # ID為88的用戶,1月份中有登陸行為的天數;以1月1號為第1天,12月31號為第365天 setbit login:88 0 1 # 第一天有登陸 setbit login:88 8 1 # 第8天有登陸 setbit login:88 12 1 # 第12天有登陸 setbit login:88 13 1 # 第13天有登陸 setbit login:88 20 1 # 第20天有登陸 setbit login:88 25 1 # 第25天有登陸 setbit login:88 27 1 # 第27天有登陸 bitcount login:88 # 結果為:7 ``` ### 2、列表—list > List, 元素可以重復,可以按照添加的先后保證順序 1)、常用命令 ~~~ lpush rpush | lpop rpop | blpop brpop | lrem linsert | llen | lrange | lindex ~~~ 2)、使用場景 * 棧 ~~~ lpush lpop ~~~ * 隊列 ~~~ lpush rpop ~~~ * 阻塞MQ ~~~ lpush brpop ~~~ :-: ![](https://img.kancloud.cn/6e/3e/6e3e5c27a740366ec7737453e423d8ee_463x319.png) ### 3、哈希—hash 1)、常用命令 ~~~ hset hget | hmset | hmget | hstrlen | hgetall | hlen | hincrby | hincrbyfloat | hexists | hdel | hkeys ~~~ 2)、使用場景 * 存儲對象信息 ~~~ # 存儲用戶信息;如姓名,年齡,地址等 hmset uid:101 name zhangsan age 18 addr 北京 ~~~ ### 4、集合—set > 集合中的元素會去重,保證不重復 1)、常用命令 ~~~ sadd srem spop | sinter sdiff sunion| sinterstore sdiffstore sunionstore | smembers | sismember | srandmember | scard ~~~ 2)、使用場景 > 抽獎和關注模型兩大類 * 抽獎程序 ~~~ # 100張購物卡,共30人參與抽獎 # 獎品大于抽獎人 sadd k1 tom xxoo xoox xoxo oxxo ooxx oxox # 將30個參與抽獎的人添加到集合 srandmember k1 -100 # 這里-100,會返回100個元素,隨機重復 ? # 公司年會抽獎,一等獎1 二等獎3 三等獎 5 中獎者會從參與者中剔除,不再參與其他獎項 sadd k1 tom xxoo xoox xoxo oxxo ooxx oxox # 將參與抽獎員工添加到集合 spop k1 1 # 一等獎 spop k1 3 # 二等獎 spop k1 5 # 三等獎 ~~~ * 共同關注 ~~~ # 小王關注了:劉德華、羅大佑、郭富城、黎明 # 小李關注了:黎明、張曼玉、馬龍、張繼科 # 求小王和小李共同關注的人 sadd k1 劉德華 羅大佑 郭富城 黎明 sadd k2 黎明 張曼玉 馬龍 張繼科 sinter k1 k2 # 結果為黎明 ~~~ * 猜你喜歡 ~~~ # 我關注了:劉德華、羅大佑、郭富城、黎明 # 小王關注了:黎明、張曼玉、馬龍、張繼科 # 當我進入小王的主頁后,可以推薦我關注 張曼玉、馬龍、張繼科 sadd k1 劉德華 羅大佑 郭富城 黎明 sadd k2 黎明 張曼玉 馬龍 張繼科 sdiff k2 k1 # 張曼玉 馬龍 張繼科 ~~~ ### 5、有序集合—sort\_set > 集合中數據去重,并可以按照給出的規則(一定的分值)排序 1)、常用命令 ~~~ zadd zrange zrangebyscore zcount | zincrby | zinterstore zunionstore | zrevrange zrevrangebyscore | zremrangebyscore ~~~ 2)、使用場景 * 排行榜 ~~~ # 熱點新聞,每點擊一次,熱搜值加1 zincrby hotnews:20210822 1 汪峰開演唱會 ? # 展示當天排行榜前十的熱搜 zrevrange hotnews:20210822 0 9 withscores ? # 計算最近3日熱搜榜 zunionstore unkey 3 hotnews:20210820 hotnews:20210821 hotnews:20210822 ? # 從上述3日熱搜榜中,展示前3 zrevrange unkey 0 2 withscores ~~~ * 帶有權重的隊列 ## 四、跳表(skip list) 跳表是一個特殊的鏈表,相比一般的鏈表有更高的查找效率;Redis中的有序列表就使用了這種結構 :-: ![](https://img.kancloud.cn/29/60/2960b00b89e5b5ca355f966e311955c8_615x246.png) 1. 查找 (例如:查找40) * 第一步拿目標40跟三級索引第一個節點18比較;由于40 大于 18,則跟18的下一個節點45進行比較,而40小于45 * 通過第一步,可以知道目標40介于三級所以第一個節點和下一個節點之間,所以直接來到三級索引第一個節點18的二級索引 * 此時在二級索引,40大于18的下一個節點36,則移動指針到36;由于40小于36的下一個節點45,所以將指針移動到二級索引36的上級原始鏈表 * 此時發現,原始鏈表36的下一個節點復合條件 2. 插入節點 * 新插入的節點和各級索引節點逐個比較,確定原始鏈表的位置(同上述查找過程) * 把新的數據插入到原始鏈表 * 利用拋硬幣的隨機方式,決定是否將新的節點提升為上一級索引 3. 刪除節點 * 自上而下,查找第一次出現節點的索引,并逐層找到每一層對應的節點 * 刪除每一層找到的節點,如果該層只剩下一個節點,則刪除整個層(原始鏈表除外) ## 五、管道(Pipeline) 當有多個命令(command)需要被及時提交,并且這些命令對相應結果沒有互相依賴、對響應也無需立即獲得;那么就可以使用管道來實現這種批處理。這在一定程度上可以提升性能,原因主要是TCP連接中減少了交互往返時間。假如有三條命令,單個提交就得需要3次往返;而使用管道批處理,只需要一次往返。Redis server 收到Pipeline發送過來的數據后,會以隊列的形式放在內存中后,開始一條條的執行。 :-: ![](https://img.kancloud.cn/20/78/20780b90bee0983ba05a1d7a18678668_692x266.png) 1. 注意事項 * 可以為Pipeline操作新建Client連接,讓其與其他正常操作隔離開在不同的Client連接中(由于Pipeline是獨占連接的,所以在此期間是不可以進行其他操作的) * Pipeline所能容忍的操作數,和socket緩沖區大小有很大的關系,受限于server的物理內存和網絡接口的緩沖能力 * Pipeline只是讓一批命令按順序執行,不能保證原子性 2. 使用場景 將數據庫中的一批數據,一次性批量的存入Redis;可以考慮采用Pipeline實現 ## 六、發布/訂閱 (Pub/Sub) 1. 常用命令 ~~~ publish subscribe unsubscribe | psubscribe punsubscribe ~~~ 2. 使用場景 * 普通的實時聊天、群聊功能 * 網站某一模塊更新后,推送消息給到訂閱者 3. 與Redis通過list結構實現消息隊列的區別: list 消息隊列,再有多個消費者的情況下,一條消息只會有一個消費者獲取消費; 而發布訂閱者,監聽同一發布者同一頻道的消息,多個訂閱者都會收到消息 > 假如,現在需要開發一個聊天軟件,需要實現: > > 1、好友可以接收消息 > > 2、可以查詢聊天信息(考慮3天以內查詢頻次高,3天以外基本不會查詢) > > 請給出架構方案 :-: ![](https://img.kancloud.cn/d6/f0/d6f0e92efdcfdec757250a721fceda57_516x466.png) 上述架構方案,重點關注紅色虛線的部分。Client負責將消息Pub出去,這時候同一個頻道的好友就會收到消息;同時還需負責將數據存入DB和sort\_set以備滿足不同時間的查詢(紅色虛線部分),這種情況下很容易出現當發生網絡錯誤時,DB和sort\_set丟數據。 針對上述問題,可以將保存DB和sort\_set的部分,也以訂閱者身份去監聽Client的消息發布,然后通過監聽的服務負責保存數據。 :-: ![](https://img.kancloud.cn/b5/a2/b5a27c32bafe574cf43ad4c81c4a19a1_693x418.png)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看