字符串類型 是 Redis 最基礎的數據結構。字符串類型 的值實際能夠是 字符串(簡單 和 複雜 的字符串,例如 JSON、XML)、數字(整數、浮點數),甚至是 二進制(圖片、音頻、視頻),可是值最大不能超過 512MB。java
set key value [ex seconds] [px milliseconds] [nx|xx]
set 命令有幾個選項:mysql
ex seconds:爲 鍵 設置 秒級過時時間。web
px milliseconds:爲 鍵 設置 毫秒級過時時間。redis
nx:鍵必須 不存在,才能夠設置成功,用於 添加。sql
xx:與 nx 相反,鍵必須 存在,才能夠設置成功,用於 更新。編程
除了 set 選項,Redis 還提供了 setex 和 setnx 兩個命令:後端
setex key seconds value setnx key value
setex:設定鍵的值,並指定此鍵值對應的 有效時間。緩存
127.0.0.1:6379> setex key1 5 value1 OK 127.0.0.1:6379> get key1 "value1" 127.0.0.1:6379> get key1 (nil)
setnx:鍵必須 不存在,才能夠設置成功。若是鍵已經存在,返回 0。安全
127.0.0.1:6379> set key2 value1 OK 127.0.0.1:6379> setnx key2 value2 (integer) 1 127.0.0.1:6379> get key2 "value1"
get key
若是要獲取的 鍵不存在,則返回 nil(空)。服務器
127.0.0.1:6379> get not_exist_key (nil)
mset key value [key value ...]
下面操做經過 mset 命令一次性設置 4 個 鍵值對:
127.0.0.1:6379> mset a 1 b 2 c 3 d 4 OK
mget key [key ...]
經過下面操做 批量獲取 鍵 a、b、c、d 的值:
127.0.0.1:6379> mget a b c d 1) "1" 2) "2" 3) "3" 4) "4"
批量操做 命令,能夠有效提升 開發效率,假如沒有 mget 這樣的命令,要執行 n 次 get 命令的過程和 耗時 以下:
n次get時間 = n次網絡時間 + n次命令時間
使用 mget 命令後,執行 n 次 get 命令的過程和 耗時 以下:
n次get時間 = 1次網絡時間 + n次命令時間
Redis 能夠支撐 每秒數萬 的 讀寫操做,但這指的是 Redis 服務端 的處理能力,對於 客戶端 來講,一次命令除了 命令時間 仍是有 網絡時間。
假設 網絡時間 爲 1 毫秒,命令時間爲 0.1 毫秒(按照每秒處理 1 萬條命令算),那麼執行 1000 次 get 命令和 1 次 mget 命令的區別如表所示:
操做 | 時間 |
---|---|
1000次get操做 | 1000 * 1 + 1000 * 0.1 = 1100ms = 1.1s |
1次mget操做 | 1 * 1 + 1000 * 0.1 = 101ms = 0.101s |
incr key
incr 命令用於對值作 自增操做,返回結果分爲三種狀況:
值不是 整數,返回 錯誤。
值是 整數,返回 自增 後的結果。
鍵不存在,按照值爲 0 自增,返回結果爲 1。
127.0.0.1:6379> exists key (integer) 0 127.0.0.1:6379> incr key (integer) 1 複製代碼
除了 incr 命令,Redis 還提供了 decr(自減)、incrby(自增指定數字)、decrby(自減指定數字)、incrbyfloat(自增浮點數)等命令操做:
decr key
incrby key increment
decrby key decrement
incrbyfloat key increment
不少 存儲系統 和 編程語言 內部使用 CAS 機制實現 計數功能,會有必定的 CPU 開銷。但在 Redis 中徹底不存在這個問題,由於 Redis 是 單線程架構,任何命令到了 Redis 服務端 都要 順序執行。
append key value
append 能夠向 字符串尾部 追加值。
127.0.0.1:6379> get key "redis" 127.0.0.1:6379> append key world (integer) 10 127.0.0.1:6379> get key "redisworld"
strlen key
好比說,當前值爲 redisworld,因此返回值爲 10:
127.0.0.1:6379> get key "redisworld" 127.0.0.1:6379> strlen key (integer) 10
getset key value
getset 和 set 同樣會 設置值,可是不一樣的是,它同時會返回 鍵原來的值,例如:
127.0.0.1:6379> getset hello world (nil) 127.0.0.1:6379> getset hello redis "world"
setrange key offeset value
下面操做將值由 pest 變爲了 best:
127.0.0.1:6379> set redis pest OK 127.0.0.1:6379> setrange redis 0 b (integer) 4 127.0.0.1:6379> get redis "best"
getrange key start end
start 和 end 分別是 開始 和 結束 的 偏移量,偏移量 從 0 開始計算,例如獲取值 best 的 前兩個字符 的命令以下:
127.0.0.1:6379> getrange redis 0 1 "be"
最後給出 字符串 類型命令的 時間複雜度 說明:
字符串 類型的 內部編碼 有 3 種:
int:8 個字節的 長整型。
embstr:小於等於 39 個字節的字符串。
raw:大於 39 個字節的字符串。
Redis 會根據當前值的 類型 和 長度 決定使用哪一種 內部編碼實現。
整數類型
127.0.0.1:6379> set key 8653 OK 127.0.0.1:6379> object encoding key "int"
短字符串
小於等於39個字節的字符串:embstr
127.0.0.1:6379> set key "hello,world" OK 127.0.0.1:6379> object encoding key "embstr"
長字符串
大於39個字節的字符串:raw
127.0.0.1:6379> set key "one string greater than 39 byte........." OK 127.0.0.1:6379> object encoding key "raw" 127.0.0.1:6379> strlen key (integer) 40
下面是一種比較典型的 緩存 使用場景,其中 Redis 做爲 緩存層,MySQL 做爲 存儲層,絕大部分請求的數據都是從 Redis 中獲取。因爲 Redis 具備支撐 高併發 的特性,因此緩存一般能起到 加速讀寫 和 下降後端壓力 的做用。
整個功能的僞代碼以下:
public UserInfo getUserInfo(long id) { String userRedisKey = "user:info:" + id; String value = redis.get(userRedisKey); UserInfo userInfo; if (value != null) { userInfo = deserialize(value); } else { userInfo = mysql.get(id); if (userInfo != null) { redis.setex(userRedisKey, 3600, serialize(userInfo)); } return userInfo; } }
許多應用都會使用 Redis 做爲 計數 的基礎工具,它能夠實現 快速計數、查詢緩存 的功能,同時數據能夠 異步落地 到其餘 數據源。通常來講,視頻播放數系統,就是使用 Redis 做爲 視頻播放數計數 的基礎組件,用戶每播放一次視頻,相應的視頻播放數就會自增 1。
public long incrVideoCounter ( long id){ String key = "video:playCount:" + id; return redis.incr(key); }
實際上,一個真實的 計數系統 要考慮的問題會不少:防做弊、按照 不一樣維度 計數,數據持久化 到 底層數據源等。
一個 分佈式 Web 服務將用戶的 Session 信息(例如 用戶登陸信息)保存在 各自 的服務器中。這樣會形成一個問題,出於 負載均衡 的考慮,分佈式服務 會將用戶的訪問 均衡 到不一樣服務器上,用戶 刷新一次訪問 可能會發現須要 從新登陸,這個問題是用戶沒法容忍的。
爲了解決這個問題,可使用 Redis 將用戶的 Session 進行 集中管理。在這種模式下,只要保證 Redis 是 高可用 和 擴展性的,每次用戶 更新 或者 查詢 登陸信息都直接從 Redis 中集中獲取。
不少應用出於安全的考慮,會在每次進行登陸時,讓用戶輸入 手機驗證碼,從而肯定是不是用戶本人。可是爲了 短信接口 不被 頻繁訪問,會 限制 用戶每分鐘獲取 驗證碼 的頻率。例如一分鐘不能超過 5 次,如圖所示:
此功能可使用 Redis 來實現,僞代碼以下:
String phoneNum = "138xxxxxxxx"; String key = "shortMsg:limit:" + phoneNum; // SET key value EX 60 NX boolean isExists = redis.set(key, 1, "EX 60", "NX"); if (isExists != null || redis.incr(key) <= 5) { // 經過 } else { // 限速 }
上述就是利用 Redis 實現了 限速功能,例如 一些網站 限制一個 IP 地址不能在 一秒鐘以內 訪問超過 n 次也能夠採用 相似 的思路。
本文簡單的介紹了 Redis 的 字符串數據結構 的 基本命令,內部編碼 和 相關應用場景。