Redis入門

Redis之入門教程

博客地址 https://blog.piaoruiqing.com/2019/06/02/redis入門

關鍵詞

  • Redis: Redis是一個開源(BSD許可)內存數據結構存儲. 可用作數據庫, 緩存和消息代理.
  • NoSql: 泛指非關系型的數據庫.
  • Docker: 是一個開源的應用容器引擎. 可以非常方便地部署服務.
  • 緩存: 高速緩存簡稱緩存,原始意義是指訪問速度比一般隨機存取存儲器(RAM)快的一種RAM,通常它不像系統主存那樣使用DRAM技術,而使用昂貴但較快速的SRAM技術. 簡言之, 緩存是在計算機上的一個原始數據的復制集, 讓數據更接近使用者, 有著更快的訪問速度.

前言

本文闡述了Redis的簡單使用, 包括使用Docker啟動redis服務端、redis客戶端的使用、redis常用數據結構及其使用方法和場景.

使用入門

服務端

本文使用Docker啟動redis服務端.
Docker Hub: https://hub.docker.com/_/redis

docker container run \
        --rm \
        --name redis \
        -p 6379:6379 \
        -d \
        redis:5.0
  • --rm: 退出后刪除
  • --name: 指定容器名
  • -p: 映射端口
  • -d: 后臺運行并輸出容器ID

客戶端

redis-cli

原生redis客戶端

在宿主機上執行docker exec -it redis redis-cli即可進入容器內的redis客戶端. 注: 命令中redis為前文中啟動redis時指定的容器名: --name redis(也可用容器id替代).

root@ubuntu:/home/ubuntu/docker/redis$ docker exec -it redis redis-cli
127.0.0.1:6379> 

medis

medis是一個圖形化redis客戶端工具. 支持命令.

Medis

數據結構

Redis不是普通的鍵值對存儲, 它實際上是一個支持不同類型數據結構的服務器. 這意味著Redis與傳統的鍵值存儲不同, 具有更多更復雜的數據結構, 下文將簡要介紹Redis的數據結構及用法.

Binary-safe strings

應用場景:

  • 緩存HTML片段或頁面
  • 緩存某個接口的返回值等.

Redis String類型是與Redis Key關聯的最簡單的值類型.
打開redis-cli執行簡單的string操作. (后文中所有示例都將使用redis-cli)

127.0.0.1:6379> SET mykey myvalue
OK
127.0.0.1:6379> GET mykey
"myvalue"
127.0.0.1:6379> KEYS my*
1) "mykey"
127.0.0.1:6379> EXISTS mykey
(integer) 1
127.0.0.1:6379> DEL mykey
(integer) 1
127.0.0.1:6379> GET mykey
(nil)
  • SET: 設置KEY對應的值.
  • GET: 獲取指定KEY的值.
  • KEYS: 查詢KEY.
  • EXISTS: 查詢KEY是否存在.
  • DEL: 刪除KEY.
  • EXPIRE: 指定KEY的過期時間 (SET命令也可通過參數指定過期時間)

Lists

應用場景:

  • 記錄用戶發布到社交網絡的最近更新.
  • 流程之間的通信, 借助redis列表實現生產者 - 消費者模式.

根據插入順序排序的字符串元素的集合. 其實現基于鏈表, 因此即使數據量極大的情況下, 也能在常量時間內添加元素到列表頭或尾.

127.0.0.1:6379> RPUSH mylist a  # 尾部增加元素a
(integer) 1
127.0.0.1:6379> RPUSH mylist b  # 尾部增加元素b
(integer) 2
127.0.0.1:6379> LPUSH mylist first  # 頭部增加元素first
(integer) 3
127.0.0.1:6379> LRANGE mylist 0 -1  # 獲取mylist全部元素
1) "first"
2) "a"
3) "b"
127.0.0.1:6379> LRANGE mylist 0 -2  # 獲取mylist第一~倒數第二的全部元素
1) "first"
2) "a"
127.0.0.1:6379> RPOP mylist     # 從尾部彈出一個元素
"b"
127.0.0.1:6379> LPOP mylist     # 從頭部彈出一個元素
"first"
127.0.0.1:6379> LRANGE mylist 0 -1
1) "a"
127.0.0.1:6379> RPUSH mylist b c d e f g    # 尾部增加 b c d e f g 元素
(integer) 7
127.0.0.1:6379> LRANGE mylist 0 -1
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
6) "f"
7) "g"
127.0.0.1:6379> LTRIM mylist 0 2    # 截取索引0~2的元素(其余元素丟棄)
OK
127.0.0.1:6379> LRANGE mylist 0 -1
1) "a"
2) "b"
3) "c"
  • RPUSH: 在列表尾部(右側)增加新元素.
  • LPUSH: 在列表頭部(左側)增加新元素.
  • LRANGE: 獲取存儲在列表中指定索引范圍的值, 值得注意的是, startstop從0開始, 支持負值, 負值的意義是從尾部開始偏移, 倒數第一個為-1, 倒數第二個為-2, 依此類推. 故命令LRANGE mylist 0 -1的含義為獲取全部元素(第一個到最后一個).
  • RPOP: POP相信很多人并不陌生, 彈出一個元素(獲取并刪除), RPOP的含義就是從尾部(右側)彈出一個元素.
  • LPOP: 與RPOP類似, 其含義為從列表頭部(左側)彈出一個元素.
  • LTRIM: 截取元素, 指定截取的范圍, 其余丟棄.

Sets

應用場景:

  • 希望存儲一個不重復的數據集合,
  • 獲取兩個人的共同好友

Sets是字符串的無序集合. 使用過Java的讀者應該對HashSet并不陌生, 其特點就是無序且元素不重復, Redis的Set也有這樣的特點.

127.0.0.1:6379> SADD myset a    # 將元素 a 存入 myset
(integer) 1
127.0.0.1:6379> SMEMBERS myset  # 獲取 myset 的元素
1) "a"
127.0.0.1:6379> SADD myset a    # 再次將元素 a 存入 myset, set能保證元素唯一,故此次存入返回0
(integer) 0
127.0.0.1:6379> SMEMBERS myset
1) "a"
127.0.0.1:6379> SADD myset b c  # 將元素 b、c 存入 myset
(integer) 2
127.0.0.1:6379> SMEMBERS myset 
1) "b"
2) "c"
3) "a"
127.0.0.1:6379> SPOP myset  # 隨機彈出一個元素
"c"
127.0.0.1:6379> SMEMBERS myset 
1) "b"
2) "a"
127.0.0.1:6379> SADD myset c    # 將剛剛彈出的c放回去
(integer) 1
127.0.0.1:6379> SPOP myset  # 再次隨機彈出, 這一次彈出的是b
"b"
127.0.0.1:6379> SMEMBERS myset
1) "c"
2) "a"
  • SADD: 向set添加元素.
  • SMEMBERS: 獲取set的元素.
  • SPOP: 隨機彈出一個元素.
  • Sets還可以進行交集、并集、差集計算等操作.

Sorted sets

應用場景:

  • 以某個條件為權重進行排序, 例如排行榜.

有序集合是一種類似于混合了SetHash的數據結構, 由唯一的、 非重復的字符串元素組成. 因此在一定程度上也算是一種集合(Set).

有序集合中的每個元素都與浮點值相關聯, 稱為分數 (score) (這就是為什么說它也類似于散列(hash), 因為每個元素都映射到一個值).

127.0.0.1:6379> ZADD students 99 piaoruiqing    # 向students存入piaoruiqing且指定其score為99
(integer) 1
127.0.0.1:6379> ZADD students 98 zhangsan
(integer) 1
127.0.0.1:6379> ZADD students 85 lisi
(integer) 1
127.0.0.1:6379> ZADD students 90 wangwu
(integer) 1
127.0.0.1:6379> ZRANGE students 0 -1    # 獲取students全部元素
1) "lisi"
2) "wangwu"
3) "zhangsan"
4) "piaoruiqing"
127.0.0.1:6379> ZRANGE students 0 -1 WITHSCORES # 升序獲取students全部元素及其score
1) "lisi"
2) "85"
3) "wangwu"
4) "90"
5) "zhangsan"
6) "98"
7) "piaoruiqing"
8) "99"
127.0.0.1:6379> ZREVRANGE students 0 -1 WITHSCORES  # 降序獲取students全部元素及其score
1) "piaoruiqing"
2) "99"
3) "zhangsan"
4) "98"
5) "wangwu"
6) "90"
7) "lisi"
8) "85"
127.0.0.1:6379> ZADD students 99 wuliu  # 不同元素評分可以相同(piaoruiqing和wuliu都是99)
(integer) 1
127.0.0.1:6379> ZREVRANGE students 0 -1 WITHSCORES
 1) "wuliu"
 2) "99"
 3) "piaoruiqing"
 4) "99"
 5) "zhangsan"
 6) "98"
 7) "wangwu"
 8) "90"
 9) "lisi"
10) "85"

為了更直觀, 讓我們從Medis查看下這條數據:

zset

[版權聲明]
本文發布于樸瑞卿的博客, 非商業用途允許轉載, 但轉載必須保留原作者樸瑞卿 及鏈接:blog.piaoruiqing.com. 如有授權方面的協商或合作, 請聯系郵箱: piaoruiqing@gmail.com.

Hashes

應用場景:

  • 適合存儲對象, 可用緩存用戶信息等

Hashes是一個field-value的映射表, 適合存儲對象.

127.0.0.1:6379> HSET user:9527 user_name piaoruiqing verified 1 user_level 99   # 存
(integer) 1
127.0.0.1:6379> HGET user:9527 user_name    # 獲取 user:9527 的user_name字段的值.
"piaoruiqing"
127.0.0.1:6379> HGET user:9527 user_level
"99"
127.0.0.1:6379> HGETALL user:9527   # 獲取 user:9527 的全部字段和元素
1) "user_name"
2) "piaoruiqing"
3) "birth_year"
4) "1977"
5) "verified"
6) "1"
7) "user_level"
8) "99"

為了更直觀, 讓我們從Medis查看下這條數據:

值得注意的是: 圖中第一欄標題的type是數據類型, name是redis的key, 第二列標題的key, 就是Hashes的field. 請讀者切勿被界面中的文字誤導.

Medis
  • HSET: 向hashs存入元素.

  • HGET: 獲取key某字段對應的元素.

  • HGETALL: 獲取key的全部字段和元素.

  • :: 值得一提的是一般將冒號:作為redis key的分隔符. 冒號在早期的redis版本中是一個存儲命名空間數據的概念, 是一個"遺留下來"的"約定", 冒號并不強制使用, 如果有需要, 你可以選擇_,等任何字符分割你的key, 但推薦使用:, 因為很多客戶端都默認將其作為命名空間進行展示, 比如Redis Desktop Manager就使用冒號將redis的key分割為樹狀結構進行展示, 如圖:

    Redis Desktop Manager

HyperLogLogs

應用場景:

  • 統計網站訪問IP總量.

HyperLogLogs是用來計算唯一事物出現概率的一種數據結構. 它并不存儲元素本身, 僅僅根據元素來計算基數. 即使元素很大它也能占用極小的空間快速計算出基數.

127.0.0.1:6379> PFADD ip 192.168.0.1 192.168.0.2 192.168.0.3 192.168.0.2    # 存入四個IP元素
(integer) 1
127.0.0.1:6379> PFCOUNT ip  # 獲取當前IP總量 (192.168.0.2出現過兩次, 故獲取的值是3而不是4)
(integer) 3

Streams

應用場景:

  • 消息隊列

Stream是Redis 5.0引入的一種新數據類型, 其設計借鑒了Kafka, 以完全不同的方式實現了與Kafka類似的思想: 允許一組客戶端合作消費相同的消息流的不同部分. 彌補了Redis Pub/Sub不能持久化消息的缺陷

127.0.0.1:6379> XADD mystream * sensor_id 9527 temperature 19.9 # 存入
"1559476322048-0"
127.0.0.1:6379> XADD mystream * sensor_id 9528 temperature 19.9
"1559476326813-0"
127.0.0.1:6379> XRANGE mystream - +     # 獲取
1) 1) "1559476322048-0"
   2) 1) "sensor_id"
      2) "9527"
      3) "temperature"
      4) "19.9"
2) 1) "1559476326813-0"
   2) 1) "sensor_id"
      2) "9528"
      3) "temperature"
      4) "19.9"
127.0.0.1:6379> XRANGE mystream - + COUNT 1     # 獲取(升序)
1) 1) "1559476322048-0"
   2) 1) "sensor_id"
      2) "9527"
      3) "temperature"
      4) "19.9"
127.0.0.1:6379> XREVRANGE mystream + - COUNT 1  # 獲取(降序)
1) 1) "1559476326813-0"
   2) 1) "sensor_id"
      2) "9528"
      3) "temperature"
      4) "19.9"
  • XADD: 存入, 命令XADD mystream * sensor_id 9527 temperature 19.9*表示自動生成ID
  • XRANGE: 獲取(升序)
  • XREVRANGE: 獲取(降序)

結語

本文闡述了redis的簡單使用方式及常用數據結構, 需要深入了解的讀者可以訪問redis官網獲取更詳細的文檔.

后續文章將闡述redis在實際開發中的使用方式,如: Java客戶端集成、Lua腳本的使用、實踐案例等, 敬請關注.

參考文獻

歡迎關注公眾號: 代碼如詩


代碼如詩

[版權聲明]
本文發布于樸瑞卿的博客, 非商業用途允許轉載, 但轉載必須保留原作者樸瑞卿 及鏈接:blog.piaoruiqing.com. 如有授權方面的協商或合作, 請聯系郵箱: piaoruiqing@gmail.com.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容