導航:首頁 > 程序命令 > redisset命令

redisset命令

發布時間:2024-05-25 22:36:19

1. Redis的Setnx命令實現分布式鎖

首先,分布式鎖和我們平常講到的鎖原理基本一樣,目的就是確保在多個線程並發時,只有一個線程在同一刻操作這個業務或者說方法、變數。

在一個進程中,也就是一個jvm或者說應用中,我們很容易去處理控制,在 java.util 並發包中已經為我們提供了這些方法去加鎖,比如 synchronized 關鍵字或者 Lock 鎖,都可以處理。

但是如果在分布式環境下,要保證多個線程同時只有1個能訪問某個資源,就需要用到分布式鎖。這里我們將介紹用Redis的 setnx 命令來實現分布式鎖。

其實目前通常所說的 setnx 命令,並非單指redis的 setnx key value 這條命令,這條命令可能會在後期redis版本中刪除。

一般代指redis中對 set 命令加上 nx 參數進行使用, set 這個命令,目前已經支持這么多參數可選:

從 Redis 2.6.12 版本開始, SET 命令的行為可以通過一系列參數來修改:

注入bean

這里同時啟動5個線程並發往redis中存儲 lock 這個key(key可以自定義,但需要一致),同時設置10秒的過期時間。
setIfAbsent 這個函數實現的功能與 setnx 命令一樣,代表如果沒有這個key則set成功獲取到鎖,否則set失敗沒有獲取到鎖。
獲得鎖後進行資源的操作,最後釋放鎖。

執行效果

可以看到同時只有1個線程能夠獲取到鎖。

使用 setnx 命令方式雖然操作比較簡單方便,但是會有如下問題:

可以在叢肢再次獲取鎖時,如果鎖被佔用就get值,判斷值是否是當前線程存的隨機值,如果是則再次執行 set 命令重新上鎖;當然為了保證原子性這些操作都要用 lua 腳本來執行。

可以使用 while 循環重復執行 setnx 命令,並設置一個超時時間退出循環。

可以盡量把鎖自動過期的時間設的冗餘一些。但也不能絕橡徹底解決。

可以在刪除鎖的時候先get值,判斷值是否是當前線程存的隨機值,只有相同才執行滲宏世刪鎖的操作;當然也要使用 lua 腳本執行來保證原子性。

分布式鎖需要滿足的特性

綜上:使用 setnx 命令來實現分布式鎖並不是一個很嚴謹的方案,如果是Java技術棧,我們可以使用 Redisson 庫來解決以上問題,接下來的文章會介紹如何使用。

Redisson實現分布式鎖
Redlock實現分布式鎖

2. Redis中hash、set、zset的底層數據結構原理

Redis-哈希對象(hash)

Redis-集合對象(set)

其中hashtable的key為set中元素的值,而value為null

inset為可以理解為數組,使用inset數據結構需要滿足下述兩個條件:

intset的底層結構

查詢方式一般採用二分查找法,實際查詢復雜度也就在log(n)
Redis-有序集合對象(zset)
底層實現為 字典(dict) + 跳錶(skiplist),當數據比較少的時候用ziplist編碼結構存儲。

同時滿足以下兩個條件採用ziplist存儲:

ziplist存儲方式

總結

3. Redis --- 八種數據類型(基本命令)

String、Hash、List、Set和Zset。

等同於java中的, Map<String,String> string 是redis裡面的最基本的數據類型,一個key對應一個value。

應用場景 :String是最常用的一種數據類型,普通的key/value存儲都可以歸為此類,如用戶信息,登錄信息和配置信息等;

實現方式 :String在redis內部存儲默認就是一個字元串,被redisObject所引用,當遇到incr、decr等操作(自增自減等原子操作)時會轉成數值型進行計算,此時redisObject的encoding欄位為int。

Redis雖然是用C語言寫的,但卻沒有直接用C語言的字元串,而是自己實現了一套字元串。目的就是為了提升速度,提升性能。 Redis構建了一個叫做簡單動態字元串(Simple Dynamic String),簡稱SDS。

Redis的字元串也會遵守C語言的字元串的實現規則,即 最後一個字元為空字元。然而這個空字元不會被計算在len里頭。

Redis動態擴展步驟:

Redis字元串的性能優勢

常用命令 :set/get/decr/incr/mget等,具體如下;

ps:計數器(字元串的內容為整數的時候可以使用),如 set number 1。

補充:

等同於java中的: Map<String,Map<String,String>> ,redis的hash是一個string類型的field和value的映射表, 特別適合存儲對象。 在redis中,hash因為是一個集合,所以有兩層。第一層是key:hash集合value,第二層是hashkey:string value。所以判斷是否採用hash的時候可以參照有兩層key的設計來做參考。並且注意的是, 設置過期時間只能在第一層的key上面設置。

應用場景 :我們要存儲一個用戶信息對象數據,其中包括用戶ID、用戶姓名、年齡和生日,通過用戶ID我們希望獲取該用戶的姓名或者年齡或者生日;

實現方式 :Redis的Hash實際是內部存儲的Value為一個HashMap,並提供了直接存取這個Map成員的介面。如,Key是用戶ID, value是一個Map。 這個Map的key是成員的屬性名,value是屬性值 。這樣對數據的修改和存取都可以直接通過其內部Map的Key(Redis里稱內部Map的key為field), 也就是通過 key(用戶ID) + field(屬性標簽) 就可以操作對應屬性數據。 當前HashMap的實現有兩種方式 :當HashMap的成員比較少時Redis為了節省內存會採用類似一維數組的方式來緊湊存儲,而不會採用真正的HashMap結構,這時對應的value的redisObject的encoding為zipmap,當成員數量增大時會自動轉成真正的HashMap,此時redisObject的encoding欄位為int。

常用命令 :hget/hset/hgetall等,具體如下:

等同於java中的 Map<String,List<String>> ,list 底層是一個鏈表,在redis中,插入list中的值,只需要找到list的key即可,而不需要像hash一樣插入兩層的key。 list是一種有序的、可重復的集合。

應用場景 :Redis list的應用場景非常多,也是Redis最重要的數據結構之一,比如twitter的關注列表,粉絲列表等都可以用Redis的list結構來實現;

實現方式 :Redis list的實現為一個 雙向鏈表 ,即可以支持反向查找和遍歷,更方便操作,不過帶來了部分額外的內存開銷,Redis內部的很多實現,包括 發送緩沖隊列 等也都是用的這個數據結構。

常用命令 :lpush/rpush/lpop/rpop/lrange等,具體如下:

性能總結 :

它是一個字元串鏈表,left、right都可以插入添加。

等同於java中的 Map<String,Set<String>> ,Set 是一種無序的,不能重復的集合。並且在redis中,只有一個key它的底層由hashTable實現的,天生去重。

應用場景 :Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在於set是可以自動去重的,當你需要存儲一個列表數據,又不希望出現重復數據時,set是一個很好的選擇,並且 set提供了判斷某個成員是否在一個set集合內的重要介面 ,這個也是list所不能提供的;如保存一些標簽的名字。標簽的名字不可以重復,順序是可以無序的。

實現方式 :set 的內部實現是一個 value永遠為null的HashMap,實際就是通過計算hash的方式來快速排重的,這也是set能提供判斷一個成員是否在集合內的原因。

常用命令 :sadd/spop/smembers/sunion等,具體如下:

ZSet(Sorted Set:有序集合) 每個元素都會關聯一個double類型的分數score,分數允許重復,集合元素按照score排序( 當score相同的時候,會按照被插入的鍵的字典順序進行排序 ),還可以通過 score 的范圍來獲取元素的列表。

應用場景 :Redis sorted set的使用場景與set類似,區別是set不是自動有序的,而sorted set可以 通過用戶額外提供一個優先順序(score)的參數來為成員排序,並且是插入有序的,即自動排序。 當你需要一個有序的並且不重復的集合列表,那麼可以選擇sorted set數據結構,比如twitter 的public timeline可以以發表時間作為score來存儲,這樣獲取時就是自動按時間排好序的。

底層實現 : zset 是 Redis 提供的一個非常特別的數據結構,常用作排行榜等功能,以用戶 id 為 value ,關注時間或者分數作為 score 進行排序。實現機制分別是 zipList 和 skipList 。規則如下:

zipList:滿足以下兩個條件

skipList:不滿足以上兩個條件時使用跳錶、組合了hash和skipList

為什麼用skiplist不用平衡樹?

主要從內存佔用、對范圍查找的支持和實現難易程度這三方面總結的原因。

拓展:mysql為什麼不用跳錶?

常用命令 :zadd/zrange/zrem/zcard等;

官網地址: https://redis.io/commands/geoadd

可以用來推算兩地之間的距離,方圓半徑內的人。

關於經度緯度的限制: https://www.redis.net.cn/order/3685.html

一般我們使用Hyperloglog做基數統計。

什麼是基數?就是一個集合中不重復的數的個數。

集合A:{1,3,5,7,9,7}

集合B:{1,3,5,7,9}

AB集合的基數都是5

應用:統計網站的訪問量(一個人訪問網站很多次仍然算作一次)。

優點:佔用的內存是固定的,找2^64次方個數的基數,只需要12KB內存。

缺點:有0.81%的錯誤率,可以忽略不計

概述: bitmap 存儲的是連續的二進制數字(0 和 1),通過 bitmap, 只需要一個 bit 位來表示某個元素對應的值或者狀態,key 就是對應元素本身 。 我們知道 8 個 bit 可以組成一個 byte,所以 bitmap 本身會極大的節省儲存空間。

應用場景: 適合需要保存狀態信息(比如是否簽到、是否登錄...)並需要進一步對這些信息進行分析的場景。比如用戶簽到情況、活躍用戶情況、用戶行為統計(比如是否點贊過某個視頻)。

針對上面提到的一些場景,這里進行進一步說明。

使用場景一:用戶行為分析 很多網站為了分析你的喜好,需要研究你點贊過的內容。

使用場景二:統計活躍用戶

使用時間作為 key,然後用戶 ID 為 offset,如果當日活躍過就設置為 1

那麼我該如果計算某幾天/月/年的活躍用戶呢(暫且約定,統計時間內只有有一天在線就稱為活躍),有請下一個 redis 的命令

使用場景三:用戶在線狀態

對於獲取或者統計用戶在線狀態,使用 bitmap 是一個節約空間效率又高的一種方法。

只需要一個 key,然後用戶 ID 為 offset,如果在線就設置為 1,不在線就設置為 0。

補充

巨人的肩膀:

https://www.cnblogs.com/Small-sunshine/p/11687809.html
https://mp.weixin.qq.com/s/CMu7oXVIKp2s-PXTdMlimA

4. redis 命令執行過程

redis數據淘汰原理
redis過期數據刪除策略
redis server事件模型
redis cluster mget 引發的討論
redis 3.x windows 集群搭建
redis 命令執行過程
redis string底層數據結構
redis list底層數據結構
redis hash底層數據結構好鬧
redis set底層數據結構
redis zset底層數據結構
redis 客戶端管理
redis 主從同步-slave端
redis 主從同步-master端
redis 主從超時檢測
redis aof持久化
redis rdb持久化
redis 數據恢復過程
redis TTL實現原理
redis cluster集群建立
redis cluster集群選主

 這篇文章的目的是為了描述redis server在處理client命令的執行過程,大概包括流程圖、源碼、以及redis的命令格式說明,redis的通信協議參考自redis的則頌 官網


 整個redis的server端命令執行過程就如下面這個流程圖:



 nread = read(fd, c->querybuf+qblen, readlen);負責讀取命令數,通過processInputBuffer進行下一步處理。


 核心在於processInlineBuffer處理內聯命令,processMultibulkBuffer處理批量命令包括get/set等,核心的processCommand用於執行命令。


 執行命令的過程其實主要是尋找命令對應的執行函數,通過lookupCommand查找對應的執行命令,通過call執行命令。


 負責執行命令 c->cmd->proc 並更新統計信息,執行完成後負責同步數據 propagate


 主要是負責同步數據到AOF文件和slave節點,feedAppendOnlyFile負責友盯罩同步到AOF文件,replicationFeedSlaves負責同步


 AOF涉及的緩存有多份,包括


 包含了命令和對應執行函數的映射關系,應該看上去很清晰命令。



協議的一般格式如下,注意前面的*或者$等字元,結尾的 是分隔符。

其中, 回復中的第二個元素為空。


5. redis鏀鎸佹湇鍔$閿佸畾

Redis鏀鎸佹湇鍔$閿佸畾錛岄氳繃浣跨敤SET鍛戒護鏉ヨ劇疆涓涓鍞涓鐨勯敭鍊煎瑰疄鐜扮殑銆

褰撲竴涓瀹㈡埛絝鎯寵佽幏鍙栭攣鏃訛紝瀹冧細浣跨敤SET鍛戒護鏉ヨ劇疆涓涓閿鍊煎癸紝鍏朵腑閿鏄涓涓鍞涓鐨勫瓧絎︿覆錛岃〃紺洪攣鐨勫悕縐幫紝鍊兼槸涓涓鏃墮棿鎴籌紝琛ㄧず瀹㈡埛絝鎯寵佽幏鍙栭攣鐨勬椂闂淬俁edis鏀鎸佹湇鍔$閿佸畾錛岃繖鏄閫氳繃浣跨敤SET鍛戒護鏉ヨ劇疆涓涓鍞涓鐨勯敭鍊煎瑰疄鐜扮殑銆

濡傛灉榪欎釜閿鍊煎瑰凡緇忓瓨鍦錛岄偅涔堝㈡埛絝灝變細絳夊緟鐩村埌閿佽閲婃斁銆傚傛灉瀹㈡埛絝鍦ㄧ瓑寰呮湡闂村彂鐢熶簡瓚呮椂錛岄偅涔堝畠鍙浠ラ夋嫨鏀懼純鑾峰彇閿併傚綋瀹㈡埛絝鎴愬姛鑾峰彇浜嗛攣涔嬪悗錛屽畠鍙浠ヤ嬌鐢‥XPIRE鍛戒護鏉ヨ劇疆閿佺殑榪囨湡鏃墮棿錛屼互闃叉㈠洜涓哄㈡埛絝寮傚父鑰屽艱嚧鐨勬婚攣鎯呭喌銆傚湪Redis涓錛屾湇鍔$閿佹槸涓縐嶄箰瑙傞攣鏈哄埗錛屽畠涓嶄細闃誨炲叾浠栧㈡埛絝鐨勮塊棶錛屽彧浼氫繚璇佸悓涓鏃墮棿鍙鏈変竴涓瀹㈡埛絝鍙浠ヨ幏鍙栧埌閿併

redis鐨勫瓨鍌

redis浣跨敤浜嗕袱縐嶆枃浠舵牸寮忥細鍏ㄩ噺鏁版嵁鍜屽為噺璇鋒眰銆

鍏ㄩ噺鏁版嵁鏍煎紡鏄鎶婂唴瀛樹腑鐨勬暟鎹鍐欏叆紓佺洏錛屼究浜庝笅嬈¤誨彇鏂囦歡榪涜屽姞杞姐

澧為噺璇鋒眰鏂囦歡鍒欐槸鎶婂唴瀛樹腑鐨勬暟鎹搴忓垪鍖栦負鎿嶄綔璇鋒眰錛岀敤浜庤誨彇鏂囦歡榪涜宺eplay寰楀埌鏁版嵁錛屽簭鍒楀寲鐨勬搷浣滃寘鎷琒ET銆丷PUSH銆丼ADD銆乑ADD銆

redis鐨勫瓨鍌ㄥ垎涓哄唴瀛樺瓨鍌ㄣ佺佺洏瀛樺偍鍜宭og鏂囦歡涓夐儴鍒嗭紝閰嶇疆鏂囦歡涓鏈変笁涓鍙傛暟瀵瑰叾榪涜岄厤緗銆

save seconds updates錛宻ave閰嶇疆錛屾寚鍑哄湪澶氶暱鏃墮棿鍐咃紝鏈夊氬皯嬈℃洿鏂版搷浣滐紝灝卞皢鏁版嵁鍚屾ュ埌鏁版嵁鏂囦歡銆傝繖涓鍙浠ュ氫釜鏉′歡閰嶅悎錛屾瘮濡傞粯璁ら厤緗鏂囦歡涓鐨勮劇疆錛屽氨璁劇疆浜嗕笁涓鏉′歡銆

閱讀全文

與redisset命令相關的資料

熱點內容
程序員做競價 瀏覽:694
江蘇中小學編程納入課程 瀏覽:724
單純形法包括動態規劃演算法 瀏覽:951
cpdf百度網盤 瀏覽:671
綜合布線工程中配線架的演算法 瀏覽:925
單片機碩士論文 瀏覽:329
股票預測演算法現狀 瀏覽:430
程序員三高 瀏覽:180
pythonfiddle 瀏覽:215
韓信分油總共有幾種演算法 瀏覽:941
程序員思維方案 瀏覽:970
編譯環境要裝c盤嗎 瀏覽:648
單片機生成pwm 瀏覽:206
線上租車有什麼app 瀏覽:908
php程序修改 瀏覽:684
下列能查找文件或文件夾的操作是 瀏覽:314
遙感科學與技術演算法待遇 瀏覽:136
cad標注半徑命令 瀏覽:367
打卡領購app邀請碼怎麼填 瀏覽:336
編程訪問許可權沖突 瀏覽:152