1. 讓 Command Line 指令列顯示目前處在哪一個 Git Branch 分支,最早是在 RGBA 看到這一招,非常方便。另外我最近看到一個點子是顯示從上一次 commit 之後過了多久時間,這可以提醒你是不是該 commit 了 XD
請修改家目錄的 ~/.bash_profile 檔案 (我是用 Bash)。
1234567891011121314151617 |
|
結果如下,各位可以看到目前處在 master 分支,並且這個專案已經過了 1821 個小時沒有 commit 了…. :p
2. 安裝 Git 的 Bash autocompletion,這樣按 tab 就會有自動完成的效果,它甚至包括 git checkout 時都可以抓到你的 branch 名稱。這裡我用 Homebrew 來安裝 bash-completion,這套件其實包括很多 autocompletion script,你可以去 /usr/local/etc/bash_completion.d 這個目錄找找看。
brew install bash-completion cp /usr/local/etc/bash_completion.d/git-completion.bash ~/.git-bash-completion.sh
編輯 ~/.bash_profile 加入
[ -f ~/.git-bash-completion.sh ] && . ~/.git-bash-completion.sh
3. 打開 Git 的 color 顏色設定,這樣 Git 指令的輸出結果才會加上顏色,像是 git status 等:
git config --global color.ui true
4. 設定你偏好的文字編輯器和 diff 工具
git config --global core.editor git config --global merge.tool opendiff
5. 最後,我個人喜歡以下的 alias:
git config --global alias.co checkout git config --global alias.ci commit git config --global alias.st status git config --global alias.br branch
這樣只要輸入 git st 就是 git status 了。
FYI,以上 git 設定檔的位置在 ~/.gitconfig,你也可以直接修改這個檔案。
- git在windows上配置ssh公鑰一 .設置git的user name和email:$ git config --global user.name "lxyz"$ git config --global user.email "1129103472@qq.com"二 生成密鑰ssh-keygen -t rsa -C “1129103472@qq.com”按3個回車,密碼為空。(不要輸密碼)然后到.ssh下面將id_rsa.pub里的內容復制出來粘貼到github個人中心的賬戶設置的ssh key里面git for windows下載地址:http://code.google.com/p/msysgit/downloads/list
現象是:
Windows下Eclipse可以連接Device里能顯示設備名稱,但是在Mac OS X下的Eclipse Device始終不能顯示連接。
解決方法:
1.把Android手機開啟調試模式,然后連接在我們的Mac OS上。
2.選擇Mac的 關于本機->更多信息-> 系統報告->找到usb選項,右邊會出現一系列和usb相關的設備我們找到自己的Android設備并選中。
3.選中后找到 供應商ID或叫廠商ID,我的MX4手機顯示的供應商ID是:0x2a45
4.打開Mac終端 輸入: echo 0x2a45 >> ~/.android/adb_usb.ini
然后重啟adb(我是重啟Mac系統)后再打開eclipse 你會發現Android手機的設備顯示了。這樣的辦法還可以解決Mac上其他android設備不顯示的問題。
感謝魅族的冤家對手小米論壇提供了解決方法,原文:點擊打開鏈接
一、概述:
在Redis中,我們可以將Set類型看作為沒有排序的字符集合,和List類型一樣,我們也可以在該類型的數據值上執行添加、刪除或判斷某一元素是否存在等操作。需要說明的是,這些操作的時間復雜度為O(1),即常量時間內完成次操作。Set可包含的最大元素數量是4294967295。
和List類型不同的是,Set集合中不允許出現重復的元素,這一點和C++標準庫中的set容器是完全相同的。換句話說,如果多次添加相同元素,Set中將僅保留該元素的一份拷貝。和List類型相比,Set類型在功能上還存在著一個非常重要的特性,即在服務器端完成多個Sets之間的聚合計算操作,如unions、intersections和differences。由于這些操作均在服務端完成,因此效率極高,而且也節省了大量的網絡IO開銷。
二、相關命令列表:
命令原型 | 時間復雜度 | 命令描述 | 返回值 |
SADD key member [member ...] | O(N) | 時間復雜度中的N表示操作的成員數量。如果在插入的過程用,參數中有的成員在Set中已經存在,該成員將被忽略,而其它成員仍將會被正常插入。如果執行該命令之前,該Key并不存在,該命令將會創建一個新的Set,此后再將參數中的成員陸續插入。如果該Key的Value不是Set類型,該命令將返回相關的錯誤信息。 | 本次操作實際插入的成員數量。 |
SCARD key | O(1) | 獲取Set中成員的數量。 | 返回Set中成員的數量,如果該Key并不存在,返回0。 |
SISMEMBERkey member | O(1) | 判斷參數中指定成員是否已經存在于與Key相關聯的Set集合中。 | 1表示已經存在,0表示不存在,或該Key本身并不存在。 |
SMEMBERS key | O(N) | 時間復雜度中的N表示Set中已經存在的成員數量。獲取與該Key關聯的Set中所有的成員。 | 返回Set中所有的成員。 |
SPOP key | O(1) | 隨機的移除并返回Set中的某一成員。 由于Set中元素的布局不受外部控制,因此無法像List那樣確定哪個元素位于Set的頭部或者尾部。 | 返回移除的成員,如果該Key并不存在,則返回nil。 |
SREM key member [member ...] | O(N) | 時間復雜度中的N表示被刪除的成員數量。從與Key關聯的Set中刪除參數中指定的成員,不存在的參數成員將被忽略,如果該Key并不存在,將視為空Set處理。 | 從Set中實際移除的成員數量,如果沒有則返回0。 |
SRANDMEMBERkey | O(1) | 和SPOP一樣,隨機的返回Set中的一個成員,不同的是該命令并不會刪除返回的成員。 | 返回隨機位置的成員,如果Key不存在則返回nil。 |
SMOVE source destination member | O(1) | 原子性的將參數中的成員從source鍵移入到destination鍵所關聯的Set中。因此在某一時刻,該成員或者出現在source中,或者出現在destination中。如果該成員在source中并不存在,該命令將不會再執行任何操作并返回0,否則,該成員將從source移入到destination。如果此時該成員已經在destination中存在,那么該命令僅是將該成員從source中移出。如果和Key關聯的Value不是Set,將返回相關的錯誤信息。 | 1表示正常移動,0表示source中并不包含參數成員。 |
SDIFF key [key ...] | O(N) | 時間復雜度中的N表示所有Sets中成員的總數量。返回參數中第一個Key所關聯的Set和其后所有Keys所關聯的Sets中成員的差異。如果Key不存在,則視為空Set。 | 差異結果成員的集合。 |
SDIFFSTOREdestination key [key ...] | O(N) | 該命令和SDIFF命令在功能上完全相同,兩者之間唯一的差別是SDIFF返回差異的結果成員,而該命令將差異成員存儲在destination關聯的Set中。如果destination鍵已經存在,該操作將覆蓋它的成員。 | 返回差異成員的數量。 |
SINTER key [key ...] | O(N*M) | 時間復雜度中的N表示最小Set中元素的數量,M則表示參數中Sets的數量。該命令將返回參數中所有Keys關聯的Sets中成員的交集。因此如果參數中任何一個Key關聯的Set為空,或某一Key不存在,那么該命令的結果將為空集。 | 交集結果成員的集合。 |
SINTERSTOREdestination key [key ...] | O(N*M) | 該命令和SINTER命令在功能上完全相同,兩者之間唯一的差別是SINTER返回交集的結果成員,而該命令將交集成員存儲在destination關聯的Set中。如果destination鍵已經存在,該操作將覆蓋它的成員。 | 返回交集成員的數量。 |
SUNION key [key ...] | O(N) | 時間復雜度中的N表示所有Sets中成員的總數量。該命令將返回參數中所有Keys關聯的Sets中成員的并集。 | 并集結果成員的集合。 |
SUNIONSTOREdestination key [key ...] | O(N) | 該命令和SUNION命令在功能上完全相同,兩者之間唯一的差別是SUNION返回并集的結果成員,而該命令將并集成員存儲在destination關聯的Set中。如果destination鍵已經存在,該操作將覆蓋它的成員。 | 返回并集成員的數量。 |
三、命令示例:
1. SADD/SMEMBERS/SCARD/SISMEMBER:
#在Shell命令行下啟動Redis的客戶端程序。
/> redis-cli
#插入測試數據,由于該鍵myset之前并不存在,因此參數中的三個成員都被正常插入。
redis 127.0.0.1:6379> sadd myset a b c
(integer) 3
#由于參數中的a在myset中已經存在,因此本次操作僅僅插入了d和e兩個新成員。
redis 127.0.0.1:6379> sadd myset a d e
(integer) 2
#判斷a是否已經存在,返回值為1表示存在。
redis 127.0.0.1:6379> sismember myset a
(integer) 1
#判斷f是否已經存在,返回值為0表示不存在。
redis 127.0.0.1:6379> sismember myset f
(integer) 0
#通過smembers命令查看插入的結果,從結果可以,輸出的順序和插入順序無關。
redis 127.0.0.1:6379> smembers myset
1) "c"
2) "d"
3) "a"
4) "b"
5) "e"
#獲取Set集合中元素的數量。
redis 127.0.0.1:6379> scard myset
(integer) 5
2. SPOP/SREM/SRANDMEMBER/SMOVE:
#刪除該鍵,便于后面的測試。
redis 127.0.0.1:6379> del myset
(integer) 1
#為后面的示例準備測試數據。
redis 127.0.0.1:6379> sadd myset a b c d
(integer) 4
#查看Set中成員的位置。
redis 127.0.0.1:6379> smembers myset
1) "c"
2) "d"
3) "a"
4) "b"
#從結果可以看出,該命令確實是隨機的返回了某一成員。
redis 127.0.0.1:6379> srandmember myset
"c"
#Set中尾部的成員b被移出并返回,事實上b并不是之前插入的第一個或最后一個成員。
redis 127.0.0.1:6379> spop myset
"b"
#查看移出后Set的成員信息。
redis 127.0.0.1:6379> smembers myset
1) "c"
2) "d"
3) "a"
#從Set中移出a、d和f三個成員,其中f并不存在,因此只有a和d兩個成員被移出,返回為2。
redis 127.0.0.1:6379> srem myset a d f
(integer) 2
#查看移出后的輸出結果。
redis 127.0.0.1:6379> smembers myset
1) "c"
#為后面的smove命令準備數據。
redis 127.0.0.1:6379> sadd myset a b
(integer) 2
redis 127.0.0.1:6379> sadd myset2 c d
(integer) 2
#將a從myset移到myset2,從結果可以看出移動成功。
redis 127.0.0.1:6379> smove myset myset2 a
(integer) 1
#再次將a從myset移到myset2,由于此時a已經不是myset的成員了,因此移動失敗并返回0。
redis 127.0.0.1:6379> smove myset myset2 a
(integer) 0
#分別查看myset和myset2的成員,確認移動是否真的成功。
redis 127.0.0.1:6379> smembers myset
1) "b"
redis 127.0.0.1:6379> smembers myset2
1) "c"
2) "d"
3) "a"
3. SDIFF/SDIFFSTORE/SINTER/SINTERSTORE:
#為后面的命令準備測試數據。
redis 127.0.0.1:6379> sadd myset a b c d
(integer) 4
redis 127.0.0.1:6379> sadd myset2 c
(integer) 1
redis 127.0.0.1:6379> sadd myset3 a c e
(integer) 3
#myset和myset2相比,a、b和d三個成員是兩者之間的差異成員。再用這個結果繼續和myset3進行差異比較,b和d是myset3不存在的成員。
redis 127.0.0.1:6379> sdiff myset myset2 myset3
1) "d"
2) "b"
#將3個集合的差異成員存在在diffkey關聯的Set中,并返回插入的成員數量。
redis 127.0.0.1:6379> sdiffstore diffkey myset myset2 myset3
(integer) 2
#查看一下sdiffstore的操作結果。
redis 127.0.0.1:6379> smembers diffkey
1) "d"
2) "b"
#從之前準備的數據就可以看出,這三個Set的成員交集只有c。
redis 127.0.0.1:6379> sinter myset myset2 myset3
1) "c"
#將3個集合中的交集成員存儲到與interkey關聯的Set中,并返回交集成員的數量。
redis 127.0.0.1:6379> sinterstore interkey myset myset2 myset3
(integer) 1
#查看一下sinterstore的操作結果。
redis 127.0.0.1:6379> smembers interkey
1) "c"
#獲取3個集合中的成員的并集。
redis 127.0.0.1:6379> sunion myset myset2 myset3
1) "b"
2) "c"
3) "d"
4) "e"
5) "a"
#將3個集合中成員的并集存儲到unionkey關聯的set中,并返回并集成員的數量。
redis 127.0.0.1:6379> sunionstore unionkey myset myset2 myset3
(integer) 5
#查看一下suiionstore的操作結果。
redis 127.0.0.1:6379> smembers unionkey
1) "b"
2) "c"
3) "d"
4) "e"
5) "a"
四、應用范圍:
1). 可以使用Redis的Set數據類型跟蹤一些唯一性數據,比如訪問某一博客的唯一IP地址信息。對于此場景,我們僅需在每次訪問該博客時將訪問者的IP存入Redis中,Set數據類型會自動保證IP地址的唯一性。
2). 充分利用Set類型的服務端聚合操作方便、高效的特性,可以用于維護數據對象之間的關聯關系。比如所有購買某一電子設備的客戶ID被存儲在一個指定的Set中,而購買另外一種電子產品的客戶ID被存儲在另外一個Set中,如果此時我們想獲取有哪些客戶同時購買了這兩種商品時,Set的intersections命令就可以充分發揮它的方便和效率的優勢了。
一、概述:
我們可以將Redis中的Hashes類型看成具有String Key和String Value的map容器。所以該類型非常適合于存儲值對象的信息。如Username、Password和Age等。如果Hash中包含很少的字段,那么該類型的數據也將僅占用很少的磁盤空間。每一個Hash可以存儲4294967295個鍵值對。
二、相關命令列表:
命令原型 | 時間復雜度 | 命令描述 | 返回值 |
HSET key field value | O(1) | 為指定的Key設定Field/Value對,如果Key不存在,該命令將創建新Key以參數中的Field/Value對,如果參數中的Field在該Key中已經存在,則用新值覆蓋其原有值。 | 1表示新的Field被設置了新值,0表示Field已經存在,用新值覆蓋原有值。 |
HGET key field | O(1) | 返回指定Key中指定Field的關聯值。 | 返回參數中Field的關聯值,如果參數中的Key或Field不存,返回nil。 |
HEXISTSkey field | O(1) | 判斷指定Key中的指定Field是否存在。 | 1表示存在,0表示參數中的Field或Key不存在。 |
HLEN key | O(1) | 獲取該Key所包含的Field的數量。 | 返回Key包含的Field數量,如果Key不存在,返回0。 |
HDEL key field [field ...] | O(N) | 時間復雜度中的N表示參數中待刪除的字段數量。從指定Key的Hashes Value中刪除參數中指定的多個字段,如果不存在的字段將被忽略。如果Key不存在,則將其視為空Hashes,并返回0. | 實際刪除的Field數量。 |
HSETNXkey field value | O(1) | 只有當參數中的Key或Field不存在的情況下,為指定的Key設定Field/Value對,否則該命令不會進行任何操作。 | 1表示新的Field被設置了新值,0表示Key或Field已經存在,該命令沒有進行任何操作。 |
HINCRBYkey field increment | O(1) | 增加指定Key中指定Field關聯的Value的值。如果Key或Field不存在,該命令將會創建一個新Key或新Field,并將其關聯的Value初始化為0,之后再指定數字增加的操作。該命令支持的數字是64位有符號整型,即increment可以負數。 | 返回運算后的值。 |
HGETALLkey | O(N) | 時間復雜度中的N表示Key包含的Field數量。獲取該鍵包含的所有Field/Value。其返回格式為一個Field、一個Value,并以此類推。 | Field/Value的列表。 |
HKEYSkey | O(N) | 時間復雜度中的N表示Key包含的Field數量。返回指定Key的所有Fields名。 | Field的列表。 |
HVALSkey | O(N) | 時間復雜度中的N表示Key包含的Field數量。返回指定Key的所有Values名。 | Value的列表。 |
HMGETkey field [field ...] | O(N) | 時間復雜度中的N表示請求的Field數量。獲取和參數中指定Fields關聯的一組Values。如果請求的Field不存在,其值返回nil。如果Key不存在,該命令將其視為空Hash,因此返回一組nil。 | 返回和請求Fields關聯的一組Values,其返回順序等同于Fields的請求順序。 |
HMSET key field value [field value ...] | O(N) | 時間復雜度中的N表示被設置的Field數量。逐對依次設置參數中給出的Field/Value對。如果其中某個Field已經存在,則用新值覆蓋原有值。如果Key不存在,則創建新Key,同時設定參數中的Field/Value。 |
三、命令示例:
1. HSET/HGET/HDEL/HEXISTS/HLEN/HSETNX:
#在Shell命令行啟動Redis客戶端程序
/> redis-cli
#給鍵值為myhash的鍵設置字段為field1,值為stephen。
redis 127.0.0.1:6379> hset myhash field1 "stephen"
(integer) 1
#獲取鍵值為myhash,字段為field1的值。
redis 127.0.0.1:6379> hget myhash field1
"stephen"
#myhash鍵中不存在field2字段,因此返回nil。
redis 127.0.0.1:6379> hget myhash field2
(nil)
#給myhash關聯的Hashes值添加一個新的字段field2,其值為liu。
redis 127.0.0.1:6379> hset myhash field2 "liu"
(integer) 1
#獲取myhash鍵的字段數量。
redis 127.0.0.1:6379> hlen myhash
(integer) 2
#判斷myhash鍵中是否存在字段名為field1的字段,由于存在,返回值為1。
redis 127.0.0.1:6379> hexists myhash field1
(integer) 1
#刪除myhash鍵中字段名為field1的字段,刪除成功返回1。
redis 127.0.0.1:6379> hdel myhash field1
(integer) 1
#再次刪除myhash鍵中字段名為field1的字段,由于上一條命令已經將其刪除,因為沒有刪除,返回0。
redis 127.0.0.1:6379> hdel myhash field1
(integer) 0
#判斷myhash鍵中是否存在field1字段,由于上一條命令已經將其刪除,因為返回0。
redis 127.0.0.1:6379> hexists myhash field1
(integer) 0
#通過hsetnx命令給myhash添加新字段field1,其值為stephen,因為該字段已經被刪除,所以該命令添加成功并返回1。
redis 127.0.0.1:6379> hsetnx myhash field1 stephen
(integer) 1
#由于myhash的field1字段已經通過上一條命令添加成功,因為本條命令不做任何操作后返回0。
redis 127.0.0.1:6379> hsetnx myhash field1 stephen
(integer) 0
2. HINCRBY:
#刪除該鍵,便于后面示例的測試。
redis 127.0.0.1:6379> del myhash
(integer) 1
#準備測試數據,該myhash的field字段設定值1。
redis 127.0.0.1:6379> hset myhash field 5
(integer) 1
#給myhash的field字段的值加1,返回加后的結果。
redis 127.0.0.1:6379> hincrby myhash field 1
(integer) 6
#給myhash的field字段的值加-1,返回加后的結果。
redis 127.0.0.1:6379> hincrby myhash field -1
(integer) 5
#給myhash的field字段的值加-10,返回加后的結果。
redis 127.0.0.1:6379> hincrby myhash field -10
(integer) -5
3. HGETALL/HKEYS/HVALS/HMGET/HMSET:
#刪除該鍵,便于后面示例測試。
redis 127.0.0.1:6379> del myhash
(integer) 1
#為該鍵myhash,一次性設置多個字段,分別是field1 = "hello", field2 = "world"。
redis 127.0.0.1:6379> hmset myhash field1 "hello" field2 "world"
OK
#獲取myhash鍵的多個字段,其中field3并不存在,因為在返回結果中與該字段對應的值為nil。
redis 127.0.0.1:6379> hmget myhash field1 field2 field3
1) "hello"
2) "world"
3) (nil)
#返回myhash鍵的所有字段及其值,從結果中可以看出,他們是逐對列出的。
redis 127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
3) "field2"
4) "world"
#僅獲取myhash鍵中所有字段的名字。
redis 127.0.0.1:6379> hkeys myhash
1) "field1"
2) "field2"
#僅獲取myhash鍵中所有字段的值。
redis 127.0.0.1:6379> hvals myhash
1) "hello"
2) "world"
一、概述:
在Redis中,List類型是按照插入順序排序的字符串鏈表。和數據結構中的普通鏈表一樣,我們可以在其頭部(left)和尾部(right)添加新的元素。在插入時,如果該鍵并不存在,Redis將為該鍵創建一個新的鏈表。與此相反,如果鏈表中所有的元素均被移除,那么該鍵也將會被從數據庫中刪除。List中可以包含的最大元素數量是4294967295。
從元素插入和刪除的效率視角來看,如果我們是在鏈表的兩頭插入或刪除元素,這將會是非常高效的操作,即使鏈表中已經存儲了百萬條記錄,該操作也可以在常量時間內完成。然而需要說明的是,如果元素插入或刪除操作是作用于鏈表中間,那將會是非常低效的。相信對于有良好數據結構基礎的開發者而言,這一點并不難理解。
二、相關命令列表:
命令原型 | 時間復雜度 | 命令描述 | 返回值 |
LPUSH key value [value ...] | O(1) | 在指定Key所關聯的List Value的頭部插入參數中給出的所有Values。如果該Key不存在,該命令將在插入之前創建一個與該Key關聯的空鏈表,之后再將數據從鏈表的頭部插入。如果該鍵的Value不是鏈表類型,該命令將返回相關的錯誤信息。 | 插入后鏈表中元素的數量。 |
LPUSHX key value | O(1) | 僅有當參數中指定的Key存在時,該命令才會在其所關聯的List Value的頭部插入參數中給出的Value,否則將不會有任何操作發生。 | 插入后鏈表中元素的數量。 |
LRANGE key start stop | O(S+N) | 時間復雜度中的S為start參數表示的偏移量,N表示元素的數量。該命令的參數start和end都是0-based。即0表示鏈表頭部(leftmost)的第一個元素。其中start的值也可以為負值,-1將表示鏈表中的最后一個元素,即尾部元素,-2表示倒數第二個并以此類推。該命令在獲取元素時,start和end位置上的元素也會被取出。如果start的值大于鏈表中元素的數量,空鏈表將會被返回。如果end的值大于元素的數量,該命令則獲取從start(包括start)開始,鏈表中剩余的所有元素。 | 返回指定范圍內元素的列表。 |
LPOP key | O(1) | 返回并彈出指定Key關聯的鏈表中的第一個元素,即頭部元素,。如果該Key不存,返回nil。 | 鏈表頭部的元素。 |
LLEN key | O(1) | 返回指定Key關聯的鏈表中元素的數量,如果該Key不存在,則返回0。如果與該Key關聯的Value的類型不是鏈表,則返回相關的錯誤信息。 | 鏈表中元素的數量。 |
LREM key count value | O(N) | 時間復雜度中N表示鏈表中元素的數量。在指定Key關聯的鏈表中,刪除前count個值等于value的元素。如果count大于0,從頭向尾遍歷并刪除,如果count小于0,則從尾向頭遍歷并刪除。如果count等于0,則刪除鏈表中所有等于value的元素。如果指定的Key不存在,則直接返回0。 | 返回被刪除的元素數量。 |
LSET key index value | O(N) | 時間復雜度中N表示鏈表中元素的數量。但是設定頭部或尾部的元素時,其時間復雜度為O(1)。設定鏈表中指定位置的值為新值,其中0表示第一個元素,即頭部元素,-1表示尾部元素。如果索引值Index超出了鏈表中元素的數量范圍,該命令將返回相關的錯誤信息。 | |
LINDEX key index | O(N) | 時間復雜度中N表示在找到該元素時需要遍歷的元素數量。對于頭部或尾部元素,其時間復雜度為O(1)。該命令將返回鏈表中指定位置(index)的元素,index是0-based,表示頭部元素,如果index為-1,表示尾部元素。如果與該Key關聯的不是鏈表,該命令將返回相關的錯誤信息。 | 返回請求的元素,如果index超出范圍,則返回nil。 |
LTRIM key start stop | O(N) | N表示被刪除的元素數量。該命令將僅保留指定范圍內的元素,從而保證鏈接中的元素數量相對恒定。start和stop參數都是0-based,0表示頭部元素。和其他命令一樣,start和stop也可以為負值,-1表示尾部元素。如果start大于鏈表的尾部,或start大于stop,該命令不錯報錯,而是返回一個空的鏈表,與此同時該Key也將被刪除。如果stop大于元素的數量,則保留從start開始剩余的所有元素。 | |
LINSERT key BEFORE|AFTER pivot value | O(N) | 時間復雜度中N表示在找到該元素pivot之前需要遍歷的元素數量。這樣意味著如果pivot位于鏈表的頭部或尾部時,該命令的時間復雜度為O(1)。該命令的功能是在pivot元素的前面或后面插入參數中的元素value。如果Key不存在,該命令將不執行任何操作。如果與Key關聯的Value類型不是鏈表,相關的錯誤信息將被返回。 | 成功插入后鏈表中元素的數量,如果沒有找到pivot,返回-1,如果key不存在,返回0。 |
RPUSH key value [value ...] | O(1) | 在指定Key所關聯的List Value的尾部插入參數中給出的所有Values。如果該Key不存在,該命令將在插入之前創建一個與該Key關聯的空鏈表,之后再將數據從鏈表的尾部插入。如果該鍵的Value不是鏈表類型,該命令將返回相關的錯誤信息。 | 插入后鏈表中元素的數量。 |
RPUSHX key value | O(1) | 僅有當參數中指定的Key存在時,該命令才會在其所關聯的List Value的尾部插入參數中給出的Value,否則將不會有任何操作發生。 | 插入后鏈表中元素的數量。 |
RPOP key | O(1) | 返回并彈出指定Key關聯的鏈表中的最后一個元素,即尾部元素,。如果該Key不存,返回nil。 | 鏈表尾部的元素。 |
RPOPLPUSHsource destination | O(1) | 原子性的從與source鍵關聯的鏈表尾部彈出一個元素,同時再將彈出的元素插入到與destination鍵關聯的鏈表的頭部。如果source鍵不存在,該命令將返回nil,同時不再做任何其它的操作了。如果source和destination是同一個鍵,則相當于原子性的將其關聯鏈表中的尾部元素移到該鏈表的頭部。 | 返回彈出和插入的元素。 |
三、命令示例:
1. LPUSH/LPUSHX/LRANGE:
/> redis-cli #在Shell提示符下啟動redis客戶端工具。
redis 127.0.0.1:6379> del mykey
(integer) 1
#mykey鍵并不存在,該命令會創建該鍵及與其關聯的List,之后在將參數中的values從左到右依次插入。
redis 127.0.0.1:6379> lpush mykey a b c d
(integer) 4
#取從位置0開始到位置2結束的3個元素。
redis 127.0.0.1:6379> lrange mykey 0 2
1) "d"
2) "c"
3) "b"
#取鏈表中的全部元素,其中0表示第一個元素,-1表示最后一個元素。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
#mykey2鍵此時并不存在,因此該命令將不會進行任何操作,其返回值為0。
redis 127.0.0.1:6379> lpushx mykey2 e
(integer) 0
#可以看到mykey2沒有關聯任何List Value。
redis 127.0.0.1:6379> lrange mykey2 0 -1
(empty list or set)
#mykey鍵此時已經存在,所以該命令插入成功,并返回鏈表中當前元素的數量。
redis 127.0.0.1:6379> lpushx mykey e
(integer) 5
#獲取該鍵的List Value的頭部元素。
redis 127.0.0.1:6379> lrange mykey 0 0
1) "e"
2. LPOP/LLEN:
redis 127.0.0.1:6379> lpush mykey a b c d
(integer) 4
redis 127.0.0.1:6379> lpop mykey
"d"
redis 127.0.0.1:6379> lpop mykey
"c"
#在執行lpop命令兩次后,鏈表頭部的兩個元素已經被彈出,此時鏈表中元素的數量是2
redis 127.0.0.1:6379> llen mykey
(integer) 2
3. LREM/LSET/LINDEX/LTRIM:
#為后面的示例準備測試數據。
redis 127.0.0.1:6379> lpush mykey a b c d a c
(integer) 6
#從頭部(left)向尾部(right)變量鏈表,刪除2個值等于a的元素,返回值為實際刪除的數量。
redis 127.0.0.1:6379> lrem mykey 2 a
(integer) 2
#看出刪除后鏈表中的全部元素。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "c"
2) "d"
3) "c"
4) "b"
#獲取索引值為1(頭部的第二個元素)的元素值。
redis 127.0.0.1:6379> lindex mykey 1
"d"
#將索引值為1(頭部的第二個元素)的元素值設置為新值e。
redis 127.0.0.1:6379> lset mykey 1 e
OK
#查看是否設置成功。
redis 127.0.0.1:6379> lindex mykey 1
"e"
#索引值6超過了鏈表中元素的數量,該命令返回nil。
redis 127.0.0.1:6379> lindex mykey 6
(nil)
#設置的索引值6超過了鏈表中元素的數量,設置失敗,該命令返回錯誤信息。
redis 127.0.0.1:6379> lset mykey 6 hh
(error) ERR index out of range
#僅保留索引值0到2之間的3個元素,注意第0個和第2個元素均被保留。
redis 127.0.0.1:6379> ltrim mykey 0 2
OK
#查看trim后的結果。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "c"
2) "e"
3) "c"
4. LINSERT:
#刪除該鍵便于后面的測試。
redis 127.0.0.1:6379> del mykey
(integer) 1
#為后面的示例準備測試數據。
redis 127.0.0.1:6379> lpush mykey a b c d e
(integer) 5
#在a的前面插入新元素a1。
redis 127.0.0.1:6379> linsert mykey before a a1
(integer) 6
#查看是否插入成功,從結果看已經插入。注意lindex的index值是0-based。
redis 127.0.0.1:6379> lindex mykey 0
"e"
#在e的后面插入新元素e2,從返回結果看已經插入成功。
redis 127.0.0.1:6379> linsert mykey after e e2
(integer) 7
#再次查看是否插入成功。
redis 127.0.0.1:6379> lindex mykey 1
"e2"
#在不存在的元素之前或之后插入新元素,該命令操作失敗,并返回-1。
redis 127.0.0.1:6379> linsert mykey after k a
(integer) -1
#為不存在的Key插入新元素,該命令操作失敗,返回0。
redis 127.0.0.1:6379> linsert mykey1 after a a2
(integer) 0
5. RPUSH/RPUSHX/RPOP/RPOPLPUSH:
#刪除該鍵,以便于后面的測試。
redis 127.0.0.1:6379> del mykey
(integer) 1
#從鏈表的尾部插入參數中給出的values,插入順序是從左到右依次插入。
redis 127.0.0.1:6379> rpush mykey a b c d
(integer) 4
#通過lrange的可以獲悉rpush在插入多值時的插入順序。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
#該鍵已經存在并且包含4個元素,rpushx命令將執行成功,并將元素e插入到鏈表的尾部。
redis 127.0.0.1:6379> rpushx mykey e
(integer) 5
#通過lindex命令可以看出之前的rpushx命令確實執行成功,因為索引值為4的元素已經是新元素了。
redis 127.0.0.1:6379> lindex mykey 4
"e"
#由于mykey2鍵并不存在,因此該命令不會插入數據,其返回值為0。
redis 127.0.0.1:6379> rpushx mykey2 e
(integer) 0
#在執行rpoplpush命令前,先看一下mykey中鏈表的元素有哪些,注意他們的位置關系。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
#將mykey的尾部元素e彈出,同時再插入到mykey2的頭部(原子性的完成這兩步操作)。
redis 127.0.0.1:6379> rpoplpush mykey mykey2
"e"
#通過lrange命令查看mykey在彈出尾部元素后的結果。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
#通過lrange命令查看mykey2在插入元素后的結果。
redis 127.0.0.1:6379> lrange mykey2 0 -1
1) "e"
#將source和destination設為同一鍵,將mykey中的尾部元素移到其頭部。
redis 127.0.0.1:6379> rpoplpush mykey mykey
"d"
#查看移動結果。
redis 127.0.0.1:6379> lrange mykey 0 -1
1) "d"
2) "a"
3) "b"
4) "c"
四、鏈表結構的小技巧:
針對鏈表結構的Value,Redis在其官方文檔中給出了一些實用技巧,如RPOPLPUSH命令,下面給出具體的解釋。
Redis鏈表經常會被用于消息隊列的服務,以完成多程序之間的消息交換。假設一個應用程序正在執行LPUSH操作向鏈表中添加新的元素,我們通常將這樣的程序稱之為"生產者(Producer)",而另外一個應用程序正在執行RPOP操作從鏈表中取出元素,我們稱這樣的程序為"消費者(Consumer)"。如果此時,消費者程序在取出消息元素后立刻崩潰,由于該消息已經被取出且沒有被正常處理,那么我們就可以認為該消息已經丟失,由此可能會導致業務數據丟失,或業務狀態的不一致等現象的發生。然而通過使用RPOPLPUSH命令,消費者程序在從主消息隊列中取出消息之后再將其插入到備份隊列中,直到消費者程序完成正常的處理邏輯后再將該消息從備份隊列中刪除。同時我們還可以提供一個守護進程,當發現備份隊列中的消息過期時,可以重新將其再放回到主消息隊列中,以便其它的消費者程序繼續處理。