文章目錄
- 簡介
- 概述
- 常用資料型別
- String型別操作實踐
- incr/incrby
- decr/decrby
- append
- strlen
- mset/mget
- 小節面試分析
- Hash型別應用實踐
- 概述
- hset/hget
- hincrby
- hmset/hmget
- hexists
- hdel
- hkeys/hvals
- 小節面試分析
- List型別應用實踐
- 問題
- lpush
- rpush
- 查看list
- linsert
- lset
- lrem
- ltrim
- lpop
- rpop
- llen
- index
- rpoplpush
- 小節面試分析
- Set型別應用實踐
- sadd
- smembers
- spop
- scard
- smove
- sunion
- 小節面試分析
- 總結(Summary)
簡介
概述
Redis作為一種key/value結構的資料存盤系統,為了便于對資料進行進行管理,提供了多種資料型別,然后,基于指定型別存盤我們專案中產生的資料,例如用戶的登陸資訊,購物車資訊,商品詳情資訊等等,
常用資料型別
Reids中基礎資料結構包含字串、散列,串列,集合,有序集合,作業中具體使用哪種型別要結合具體場景,
String型別操作實踐
字串型別是redis中最簡單的資料型別,它存盤的值可以是字串,其最大字串長度支持到512M,基于此型別,可以實作博客的字數統計,將日志不斷追加到指定key,實作一個分布式自增iid,實作一個博客的的點贊操作等
incr/incrby
當存盤的字串是整數時,redis提供了一個實用的命令INCR,其作用是讓當前鍵值遞增,并回傳遞增后的值,
語法:INCR key
127.0.0.1:6379> set num 1
(integer) 1
127.0.0.1:6379> incr num
(integer) 2
127.0.0.1:6379> keys *
1) "num"
127.0.0.1:6379> incr num
127.0.0.1:6379>
說明,如果num不存在,則自動會創建,如果存在自動+1,
指定增長系數
語法:INCRBY key increment
127.0.0.1:6379> incrby num 2
(integer) 5
127.0.0.1:6379> incrby num 2
(integer) 7
127.0.0.1:6379> incrby num 2
(integer) 9
127.0.0.1:6379>
decr/decrby
減少指定的整數
DECR key 按照默認步長(默認為1)進行遞減
DECRBY key decrement 按照指定步長進行遞減
127.0.0.1:6379> incr num
(integer) 10
127.0.0.1:6379> decr num
(integer) 9
127.0.0.1:6379> decrby num 3
append
向尾部追加值,如果鍵不存在則創建該鍵,其值為寫的value,即相當于SET key value,回傳值是追加后字串的總長度,
語法:APPEND key value
127.0.0.1:6379> keys *
1) "num"
2) "test1"
3) "test"
127.0.0.1:6379> get test
"123"
127.0.0.1:6379> append test "abc"
(integer) 6
127.0.0.1:6379> get test
"123abc"
127.0.0.1:6379>
strlen
字串長度,回傳資料的長度,如果鍵不存在則回傳0,注意,如果鍵值為空串,回傳也是0,
語法:STRLEN key
127.0.0.1:6379> get test
"123abc"
127.0.0.1:6379> strlen test
(integer) 6
127.0.0.1:6379> strlen tnt
(integer) 0
127.0.0.1:6379> set tnt ""
OK
127.0.0.1:6379> strlen tnt
(integer) 0
127.0.0.1:6379> exists tnt
(integer) 1
127.0.0.1:6379>
mset/mget
同時設定/獲取多個鍵值
語法:MSET key value [key value …]
MGET key [key …]
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> mset a 1 b 2 c 3
OK
127.0.0.1:6379> mget a b c
1) "1"
2) "2"
3) "3"
127.0.0.1:6379>
小節面試分析
- 博客的字數統計如何實作?(strlen)
- 如何將審計日志不斷追加到指定key?(append)
- 你如何實作一個分布式自增id?(incr-雪花演算法)
- 如何實作一個博客的的點贊操作?(incr,decr)
Hash型別應用實踐
概述
Redis散列型別是redis中一種常見的資料型別,存盤了欄位(field)和欄位值的映射,一個散列型別可以包含最多232-1個欄位,
hset/hget
語法結構
HSET key field value
HGET key field
HMSET key field value [field value…]
HMGET key field [field]
HGETALL key
HSET和HGET賦值和取值
127.0.0.1:6379> hset user username chenchen
(integer) 1
127.0.0.1:6379> hget user username
"chenchen"
127.0.0.1:6379> hset user username chen
(integer) 0
127.0.0.1:6379> keys user
1) "user"
127.0.0.1:6379> hgetall user
1) "username"
2) "chen"
127.0.0.1:6379>
127.0.0.1:6379> hset user age 18
(integer) 1
127.0.0.1:6379> hset user address "xi'an"
(integer) 1
127.0.0.1:6379> hgetall user
1) "username"
2) "chen"
3) "age"
4) "18"
3) "address"
4) "xi'an"
127.0.0.1:6379>
HSET命令不區分插入和更新操作,當執行插入操作時HSET命令回傳1,當執行更新操作時回傳0,
hincrby
127.0.0.1:6379> hdecrby article total 1 #執行會出錯
127.0.0.1:6379> hincrby article total -1 #沒有hdecrby自減命令
(integer) 1
127.0.0.1:6379> hget article total #獲取值
hmset/hmget
HMSET和HMGET設定和獲取物件屬性
127.0.0.1:6379> hmset person username tony age 18
OK
127.0.0.1:6379> hmget person age username
1) "18"
2) "tony"
127.0.0.1:6379> hgetall person
1) "username"
2) "tony"
3) "age"
4) "18"
127.0.0.1:6379>
注意:上面HMGET欄位順序可以自行定義
hexists
屬性是否存在
127.0.0.1:6379> hexists killer
(error) ERR wrong number of arguments for 'hexists' command
127.0.0.1:6379> hexists killer a
(integer) 0
127.0.0.1:6379> hexists user username
(integer) 1
127.0.0.1:6379> hexists person age
(integer) 1
127.0.0.1:6379>
hdel
洗掉屬性
127.0.0.1:6379> hdel user age
(integer) 1
127.0.0.1:6379> hgetall user
1) "username"
2) "chen"
127.0.0.1:6379> hgetall person
1) "username"
2) "tony"
3) "age"
4) "18"
127.0.0.1:6379>
hkeys/hvals
只獲取欄位名HKEYS或欄位值HVALS
127.0.0.1:6379> hkeys person
1) "username"
2) "age"
127.0.0.1:6379> hvals person
1) "tony"
2) "18"
2.3.8 hlen
元素個數
127.0.0.1:6379> hlen user
(integer) 1
127.0.0.1:6379> hlen person
(integer) 2
127.0.0.1:6379>
小節面試分析
- 發布一篇博客需要寫記憶體嗎?(需要,hmset)
- 瀏覽博客內容會怎么做?(hmget)
- 如何判定一篇博客是否存在?(hexists)
- 洗掉一篇博客如何實作?(hdel)
- 分布式系統中你登錄成功以后是如何存盤用戶資訊的?(hmset)
List型別應用實踐
一個串列最多可以包含232-1個元素(4294967295,每個表超過近43億個元素)
問題
Redis的list型別其實就是一個每個子元素都是string型別的雙向鏈表,可以通過push,pop操作從鏈表的頭部或者尾部添加洗掉元素,這使得list既可以用作堆疊,也可以用作佇列,
有意思的是list的pop操作還有阻塞版本的,當我們[lr]pop一個list物件時,如果list是空,或者不存在,會立即回傳nil,但是阻塞版本的b[lr]pop可以則可以阻塞,當然可以加超時時間,超時后也會回傳nil,為什么要阻塞版本的pop呢,主要是為了避免輪詢,舉個簡單的例子如果我們用list來實作一個作業佇列,執行任務的thread可以呼叫阻塞版本的pop去獲取任務這樣就可以避免輪詢去檢查是否有任務存在,當任務來時候作業執行緒可以立即回傳,也可以避免輪詢帶來的延遲,
lpush
在key對應list的頭部添加字串元素
redis 127.0.0.1:6379> lpush mylist "world"
(integer) 1
redis 127.0.0.1:6379> lpush mylist "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379>
其中,Redis Lrange 回傳串列中指定區間內的元素,區間以偏移量 START 和 END 指定, 其中 0 表示串列的第一個元素, 1 表示串列的第二個元素,以此類推, 你也可以使用負數下標,以 -1 表示串列的最后一個元素, -2 表示串列的倒數第二個元素,以此類推
rpush
在key對應list的尾部添加字串元素
redis 127.0.0.1:6379> rpush mylist2 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist2 "world"
(integer) 2
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379>
查看list
redis 127.0.0.1:6379> lrange mylist3 0 -1
2.4.5 del
redis 127.0.0.1:6379> del mylist
linsert
在key對應list的特定位置之前或之后添加字串元素
redis 127.0.0.1:6379> rpush mylist3 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist3 "world"
(integer) 2
redis 127.0.0.1:6379> linsert mylist3 before "world" "there"
(integer) 3
redis 127.0.0.1:6379> lrange mylist3 0 -1
1) "hello"
2) "there"
3) "world"
redis 127.0.0.1:6379>
lset
設定list中指定下標的元素值(一般用于修改操作)
redis 127.0.0.1:6379> rpush mylist4 "one"
(integer) 1
redis 127.0.0.1:6379> rpush mylist4 "two"
(integer) 2
redis 127.0.0.1:6379> rpush mylist4 "three"
(integer) 3
redis 127.0.0.1:6379> lset mylist4 0 "four"
OK
redis 127.0.0.1:6379> lset mylist4 -2 "five"
OK
redis 127.0.0.1:6379> lrange mylist4 0 -1
1) "four"
2) "five"
3) "three"
redis 127.0.0.1:6379>
lrem
從key對應list中洗掉count個和value相同的元素,count>0時,按從頭到尾的順序洗掉
redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 2
redis 127.0.0.1:6379> rpush mylist5 "foo"
(integer) 3
redis 127.0.0.1:6379> rpush mylist5 "hello"
(integer) 4
redis 127.0.0.1:6379> lrem mylist5 2 "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) "foo"
2) "hello"
redis 127.0.0.1:6379>
count<0時,按從尾到頭的順序洗掉
redis 127.0.0.1:6379> rpush mylist6 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist6 "hello"
(integer) 2
redis 127.0.0.1:6379> rpush mylist6 "foo"
(integer) 3
redis 127.0.0.1:6379> rpush mylist6 "hello"
(integer) 4
redis 127.0.0.1:6379> lrem mylist6 -2 "hello"
(integer) 2
redis 127.0.0.1:6379> lrange mylist6 0 -1
1) "hello"
2) "foo"
redis 127.0.0.1:6379>
count=0時,洗掉全部
redis 127.0.0.1:6379> rpush mylist7 "hello"
(integer) 1
redis 127.0.0.1:6379> rpush mylist7 "hello"
(integer) 2
redis 127.0.0.1:6379> rpush mylist7 "foo"
(integer) 3
redis 127.0.0.1:6379> rpush mylist7 "hello"
(integer) 4
redis 127.0.0.1:6379> lrem mylist7 0 "hello"
(integer) 3
redis 127.0.0.1:6379> lrange mylist7 0 -1
1) "foo"
redis 127.0.0.1:6379>
ltrim
保留指定key 的值范圍內的資料
redis 127.0.0.1:6379> rpush mylist8 "one"
(integer) 1
redis 127.0.0.1:6379> rpush mylist8 "two"
(integer) 2
redis 127.0.0.1:6379> rpush mylist8 "three"
(integer) 3
redis 127.0.0.1:6379> rpush mylist8 "four"
(integer) 4
redis 127.0.0.1:6379> ltrim mylist8 1 -1
OK
redis 127.0.0.1:6379> lrange mylist8 0 -1
1) "two"
2) "three"
3) "four"
redis 127.0.0.1:6379>
lpop
從list的頭部洗掉元素,并回傳洗掉元素
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379> lpop mylist
"hello"
redis 127.0.0.1:6379> lrange mylist 0 -1
1) "world"
redis 127.0.0.1:6379>
rpop
從list的尾部洗掉元素,并回傳洗掉元素:
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) "hello"
2) "world"
redis 127.0.0.1:6379> rpop mylist2
"world"
redis 127.0.0.1:6379> lrange mylist2 0 -1
1) "hello"
redis 127.0.0.1:6379>
llen
回傳key對應list的長度:
redis 127.0.0.1:6379> llen mylist5
(integer) 2
redis 127.0.0.1:6379>
index
回傳名稱為key的list中index位置的元素:
redis 127.0.0.1:6379> lrange mylist5 0 -1
1) "three"
2) "foo"
redis 127.0.0.1:6379> lindex mylist5 0
"three"
redis 127.0.0.1:6379> lindex mylist5 1
"foo"
redis 127.0.0.1:6379>
rpoplpush
從第一個list的尾部移除元素并添加到第二個list的頭部,最后回傳被移除的元素值,整個操作是原子的.如果第一個list是慷訓者不存在回傳nil:
rpoplpush lst1 lst1
rpoplpush lst1 lst2
小節面試分析
- 如何基于redis實作一個佇列結構?(lpush/rpop)
- 如何基于redis實作一個堆疊結構?(lpush/lpop)
- 如何基于redis實作一個阻塞式佇列?(lpush/brpop)
- 如何實作秒殺活動的公平性?(先進先出-FIFO)
- 通過list結構實作一個訊息佇列(順序)嗎?(可以,FIFO->lpush,rpop)
- 用戶注冊時的郵件發送功能如何提高其效率?(郵件發送是要呼叫三方服務,底層通過佇列優化其效率,佇列一般是list結構)
- 如何動態更新商品的銷量串列?(賣的好的排名靠前一些,linsert)
- 商家的粉絲串列使用什么結構實作呢?(list結構)
Set型別應用實踐
Redis的Set是string型別的無序集合,集合成員是唯一的,這就意味著集合中不能出現重復的資料,Redis中Set集合是通過哈希表實作的,所以添加,洗掉,查找的復雜度都是O(1),集合中最大的成員數為232 - 1 (4294967295每個集合可存盤40多億個成員),
sadd
添加元素,重復元素添加失敗,回傳0
127.0.0.1:6379> sadd name tony
(integer) 1
127.0.0.1:6379> sadd name hellen
(integer) 1
127.0.0.1:6379> sadd name rose
(integer) 1
127.0.0.1:6379> sadd name rose
(integer) 0
smembers
獲取內容
127.0.0.1:6379> smembers name
- “hellen”
- “rose”
- “tony”
spop
移除并回傳集合中的一個隨機元素
127.0.0.1:6379> smembers internet
1) "amoeba"
2) "redis"
3) "rabbitmq"
4) "nginx"
127.0.0.1:6379> spop internet
"rabbitmq"
127.0.0.1:6379> spop internet
"nginx"
127.0.0.1:6379> smembers internet
1) "amoeba"
2) "redis"
scard
獲取成員個數
127.0.0.1:6379> scard name
(integer) 3
smove
移動一個元素到另外一個集合
127.0.0.1:6379> sadd internet amoeba nginx redis
(integer) 3
127.0.0.1:6379> sadd bigdata hadopp spark rabbitmq
(integer) 3
127.0.0.1:6379> smembers internet
1) "amoeba"
2) "redis"
3) "nginx"
127.0.0.1:6379> smembers bigdata
1) "hadopp"
2) "spark"
3) "rabbitmq"
127.0.0.1:6379> smove bigdata internet rabbitmq
(integer) 1
127.0.0.1:6379> smembers internet
1) "amoeba"
2) "redis"
3) "rabbitmq"
4) "nginx"
127.0.0.1:6379> smembers bigdata
1) "hadopp"
2) "spark"
127.0.0.1:6379>
sunion
并集
127.0.0.1:6379> sunion internet bigdata
1) "redis"
2) "nginx"
3) "rabbitmq"
4) "amoeba"
5) "hadopp"
6) "spark"
小節面試分析
- 朋友圈的點贊功能你如何實作?(sadd,srem,smembers,scard)
- 如何實作一個網站投票統計程式?
- 你知道微博中的關注如何實作嗎?
總結(Summary)
本章節主要是對redis中的常用資料型別存盤結構,基本操作進行了分析和實踐,結合指令特性理解其應用場景,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/292420.html
標籤:其他
下一篇:19-Redis 資料持久化實踐
