Redis入門使用


redis簡介

Redis 是一個高性能的key-value數據庫。

  • Redis可基於內存亦可持久化。
  • Redis 支持存儲的value類型豐富,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)
  • Redis性能極高,讀的速度可高達110000次/s,寫的速度可高達81000次/s 。
  • Redis的所有操作都是原子性的,Redis還支持幾個操作合並后的原子性執行。

Redis 下載安裝

Redis官方並不支持Windows。 但是,微軟針對Win64自己開發了一個windows版的redis並共享到github上。

點擊https://github.com/MSOpenTech/redis/releases下載。

選擇你喜歡的安裝方式,這里我選擇壓縮版。
下載redis

安裝/解壓縮后到redis目錄找到redis-server.exe和redis-cli.exe
redis目錄

雙擊redis-server.exe啟動redis服務
redis服務

雙擊redis-cli.exe啟動客戶端,用來訪問redis服務。
redis客戶端

測試一下,設置x的值為1並獲取x。
redis測試

使用redis

redis使用key-value來存儲數據。

set & get

使用set命令設置值,並用get命令獲取值。

> set name "tenny"
OK
> get name
"tenny"

場景舉例

一般,我們存user是用id做key,user實體(或json格式化)做value。set 1 user1

但是,如果對user中某個字段經常要修改,可以采取另一種格式存儲user信息

  1. 使用mset命令批量設置屬性,假設id為1的用戶名為zhangsan,其余額為1688。mset user:1:name zhangsan user:1:balance 1688
  2. 如果該用戶頻繁購物,余額經常變動,我們修改其余額很簡單,直接設置其余額值即可。set user:1:banlance 1000
  3. 而如果是之前放入整個user實體作為value的情況,就需要不斷重復幾個步驟:get 1 => user1,反序列化user1,user.banlance = 1000,序列化user1,set 1 user1

del

del刪除一個key

> del name
(integer) 1
> get name
(nil)

incr

incr遞增一個值,如果key不存在則創造它並初始化值為1

> set connections 10
OK
> incr connections
(integer) 11
> incr connections
(integer) 12

> del connections
(integer) 1
> incr connections    //connections不存在,初始化為1
(integer) 1

場景舉例

分庫分表后,數據庫自己不生成id

  1. 由redis統一生成主鍵id。incr orderId
  2. 如果並發請求大,可以批量生成id以提升性能,用完一批后再找redis要。incrby orderId 1000

setnx

setnx(set-if-not-exists),如果key不存在才改變值。

> set name "panda"
OK
> get name
"panda"
> setnx name "tenny"    //因為name存在所以不會改變值
(integer) 0
> get name
"panda"

> get age
(nil)
> setnx age 22    //age不存在,賦值為22
(integer) 1
> get age
"22"

場景舉例

利用該操作的原子性,實現分布式鎖。

expire & ttl

expire設置生存時間,ttl查看剩余時間。

> set name "tenny"
OK
> expire name 120   //設置name生存時間為120秒
(integer) 1
> ttl name
(integer) 80    //剩余80秒
> ttl name      //2分鍾后
(integer) -2    //-2表示name這個key已經不存在了。
> get name
(nil)

> set name "tenny"
OK
> ttl name
(integer) -1    //默認-1表示永久存在
> expire name 120
(integer) 1
> ttl name
(integer) 118
> get name
"tenny"
> set name "panda"    //設置值會重置存在時間
OK
> ttl name
(integer) -1

list操作:rpush & lpush & llen & lrange & lpop & rpop

  • rpush在list末尾添加元素
> rpush color "blue"    //[bule]
(integer) 1
> rpush color "red"   //[bule, red]
(integer) 2
  • lpush在list開頭添加元素
> lpush color "yellow"    //[yellow, bule, red]
(integer) 3
  • llen查看list長度
> llen color
(integer) 3
  • lrange查看list內容,接受兩個參數,開始index和結尾index,如果結尾index為-1,表示直到list末尾。
> lrange color 0 2
1) "yellow"
2) "blue"
3) "red"
> lrange color 0 1
1) "yellow"
2) "blue"
> lrange color 1 2
1) "blue"
2) "red"
> lrange color 1 2
1) "blue"
2) "red"
  • lpop移除list第一個元素並返回它
> lpop color
"yellow"
> llen color
(integer) 2
> lrange color 0 -1
1) "blue"
2) "red"
  • rpop移除list最后一個元素並返回它
> rpop color
"red"
> llen color
(integer) 1
> lrange color 0 -1
1) "blue"

場景舉例

1 實現數據結構

  1. 棧FILO lpush + lpop
  2. 隊列FIFO lpush + rpop
  3. 阻塞隊列 lpush + brpop。brpop其中的b表示block, 阻塞。可選參數timeout,默認0表示一直等待

2 公眾號消息列表
假設張三(userId=001)關注了兩個公眾號(V1和V2)

  1. V1發消息(消息ID=1001),往張三的消息隊列里放入消息1001。lpush msg:001 1001
  2. V2發消息(消息ID=2001),往張三的消息隊列里放入消息2001。lpush msg:001 2001
  3. 其他消息依次放入...
  4. 張三查看所關注的最新消息,從張三的消息隊列里取出前5條(5條只是舉例,隨便幾條都可以)。lrange msg:001 0 4
  5. 實現消息翻頁功能,只需要往后再取5條即可,lrange msg:001 5 9

set操作:sadd & srem & sismember & smembers & sunion

set類似list,但是元素沒有順序且只能出現一次。

  • sadd添加一個元素到set
> sadd superpowers "flight"   //["flight"]
(integer) 1
> sadd superpowers "x-ray vision"   //["flight", "x-ray vision"]
(integer) 1
> sadd superpowers "reflexes"   //["flight", "x-ray vision", "reflexes"]
(integer) 1
> SADD superpowers "flight"   //重復添加無效
(integer) 0
  • srem從set中移除一個元素
> srem superpowers "reflexes"   //["flight", "x-ray vision"]
1
  • sismember測試一個元素是否存在於set,存在返回1,不存在返回0
> sismember superpowers "flight"
(integer) 1
> sismember superpowers "reflexes"
(integer) 0
  • smembers查看set所有元素
> sismember superpowers
1) "x-ray vision"
2) "flight"
  • sunion聯合多個set並返回它們的合集
> sadd birdpowers "pecking"
(integer) 1
> sadd birdpowers "flight"
(integer) 1
> smembers birdpowers
1) "pecking"
2) "flight"
> smembers superpowers
1) "x-ray vision"
2) "flight"
> sunion superpowers birdpowers   //無序的 sunion birdpowers superpowers結果一樣
1) "pecking"
2) "flight"
3) "x-ray vision"

場景舉例

1 抽獎活動

設抽獎集合名為luckdraw

  1. 將抽獎用戶放進set里。sadd luckdraw 001
  2. 查看所有參與用戶。smembers luckdraw
  3. 抽取3名中獎者。srandmember luckdraw 3
  4. 有時,需同時將中獎者移除(如中了二等獎的用戶不能再參與一等獎)。spop luckdraw 3

2 微博共同關注

設set1 set2 分別是兩個人a, b的關注集合

  1. 兩個人的共同關注,sinter set1 set2
  2. a是否關注了某個人c,sismember set1 c
  3. set1和set2的差集,即b可能認識的人,sdiff set1 set2

sorted set操作:zadd zrange

有序集合(sorted set)類似集合,不過它每個元素有一個關聯值,通過這個關聯值對元素進行排序。

  • zadd為一個有序集合添加元素
> zadd hackers 1940 "Alan Kay"
(integer) 1
> zadd hackers 1906 "Grace Hopper"
(integer) 1
> zadd hackers 1953 "Richard Stallman"
(integer) 1
> zadd hackers 1965 "Yukihiro Matsumoto"
(integer) 1
> zadd hackers 1916 "Claude Shannon"
(integer) 1
> zadd hackers 1969 "Linus Torvalds"
(integer) 1
> zadd hackers 1957 "Sophie Wilson"
(integer) 1
> zadd hackers 1912 "Alan Turing"
(integer) 1
  • zrange類似於lrange,查看sorted set元素。接受兩個參數,開始index和結尾index,如果結尾index為-1,表示直到末尾
> zrange hackers 0 -1
1) "Grace Hopper"
2) "Alan Turing"
3) "Claude Shannon"
4) "Alan Kay"
5) "Richard Stallman"
6) "Sophie Wilson"
7) "Yukihiro Matsumoto"
8) "Linus Torvalds"

可以看到元素以年份遞增排序。

> ZRANGE hackers 2 4
1) "Claude Shannon"
2) "Alan Kay"
3) "Richard Stallman"

場景舉例

熱點新聞

假設20190918這天有 xx事件,yy事件,zz事件等熱點事件。

  1. 對於某一個事件,每被點擊(或搜索)一次熱度加1。zincrby hotNews:20190918 1 xx事件
  2. 當日熱點前10,按分值倒序排序后取前10(翻頁的話往后再取10個即可)。zrevrange hotNews:20190918 0 9 withscores
  3. 七日熱點榜單,求hotNews:20190912 hotNews:20190913 ... hotNews:20190918的並集,同樣的條目會合並加分(比如20190912有yy事件,20199013也有yy事件,最終集合里會將所有yy事件的分值求和)。zunionstore hotNews:20190912-20190918 7 hotNews:20190912 hotNews:20190912 hotNews:20190913 ... hotNews:20190918
  4. 七日熱點前10,對上一步的並集按分值倒序排序后取前10。zrevrange hotNews:20190912-20190918 0 9 withscores

hash操作:hset & hget & hgetall & hmset & hincrby & hdel

hash 是一個string類型的field和value的映射表,hash特別適合用於存儲對象。

  • hset添加值
> hset user name "tenny"
(integer) 1
> hset user email "tenny@example.com"
(integer) 1
> hset user password "cutepanda"
(integer) 1
  • hget獲取值
> hget user name
"tenny"
  • hgetall獲取所有值
> hgetall user
1) "name"
2) "tenny"
3) "email"
4) "tenny@example.com"
5) "password"
6) "cutepanda"
  • hmset一次性設置多個值
> hmset user1 name "tenny1" password "cutepanda1" email "tenny1@example.com"
OK
> hgetall user1
1) "name"
2) "tenny1"
3) "password"
4) "cutepanda1"
5) "email"
6) "tenny1@example.com"

可以使用hset繼續添加或修改

> hset user1 age 22
(integer) 1
> hgetall user1
1) "name"
2) "tenny1"
3) "password"
4) "cutepanda1"
5) "email"
6) "tenny1@example.com"
7) "age"
8) "22"
> hset user1 age 24   //已存在的值重復設定返回0,新值返回1
(integer) 0
> hgetall user1
1) "name"
2) "tenny1"
3) "password"
4) "cutepanda1"
5) "email"
6) "tenny1@example.com"
7) "age"
8) "24"
  • hincrby增加數值型域的值
> hset user visits 10
(integer) 1
> hincrby user visits 1
(integer) 11
> hincrby user visits 1
(integer) 12
  • hdel刪除指定的域
> hdel user visits
(integer) 1
> hdel user age   //刪除不存在的域返回0
(integer) 0
> hdel user visits
(integer) 0
> hincrby user visits 20    //字段不存在則默認設置為0后再執行此增加操作
(integer) 20

場景舉例

1 分組儲存用戶

假設我們有存儲用戶信息:hmset user 1:name zhangsan 1:banlance 1688

當用戶很多(假設有10000個)時,一次性獲取全部用戶將耗時很久。這里便可以采取分組的策略

  1. 將10000個用戶分為10組,每組1000個用戶,則用戶所在組編號=userId/1000 + 1。即會有user01, user02, ... user10 共10個組,而不是原來的只有user一個大組
  2. 獲取用戶id是500的余額。先計算其所在分組編號 500/1000 + 1 = 01 ,然后執行hmget user01 500:banlance
  3. 設置用戶id是1200的余額為8000。先計算其所在分組編號 1200/1000 + 1 = 02,然后執行hmset user02 1200:balance 8000

2 購物車

假如以cart前綴+用戶id做key,商品id做field,商品數量做value。即cart:userId productId count

  1. 添加商品,往用戶1001的購物車里添加商品id為10088的商品。hset cart:1001 10088 1
  2. 增加商品數量,用戶1001又添加了一個10088商品。hincrby cart:1001 10088 1
  3. 刪除商品,用戶刪除了10088這個商品。hdel cart:1001 10088
  4. 查看商品總數,統計用戶1001的購物車里所有商品的總數。hlen cart:1001
  5. 獲取所有商品,獲取用戶1001的購物車里所有商品id及其count。hgetall cart:1001

以上介紹了redis的一些簡單命令,可以訪問redis中文官方網站了解更多。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM