Redis--字符串(String)


redis中最見到的數據結構,它既可以存儲文字(比如“hello world”),又可以存儲數字(比如整數10086和浮點數3.14),還可以存儲二進制數據(比如10010100)
 
redis為這幾種類型的值分別設置了相應的操作命令,讓用戶可以針對不同的值做不同的處理
 
 
 
 
1.基本操作
 
為字符串鍵設置值
 
SET key value
 
將字符串鍵 key 的值設置為 value ,命令返回 OK 表示設置成功。
 
如果字符串鍵 key 已經存在,那么用新值覆蓋原來的舊值。
復雜度為 O(1) 。
 
redis> SET msg "hello world"
OK
redis> SET msg "goodbye" # 覆蓋原來的值 "hello world"
OK
 
 
SET 命令還支持可選的 NX 選項和 XX 選項:
 
  • 如果給定了 NX 選項,那么命令僅在鍵 key 不存在的情況下,才進行設置操作;如果鍵 key 已經存在,那么 SET ... NX 命令不做動作(不會覆蓋舊值)。
  • 如果給定了 XX 選項,那么命令僅在鍵 key 已經存在的情況下,才進行設置操作;如果鍵 key 不存在,那么 SET ... XX 命令不做動作(一定會覆蓋舊值)。
 
在給定 NX 選項和 XX 選項的情況下,SET 命令在設置成功時返回 OK ,設置失敗時返回 nil 。
redis> SET nx-str "this will fail" XX # 鍵不存在,指定 XX 選項導致設置失敗
(nil)
 
redis> SET nx-str "this will success" NX # 鍵不存在,所以指定 NX 選項是可行的
OK
 
redis> SET nx-str "this will fail" NX # 鍵已經存在,指定 NX 選項導致設置失敗
(nil)
 
redis> SET nx-str "this will success again!" XX # 鍵已經存在,指定 XX 選項是可行的
OK
 
獲取字符串的值
GET key
 
返回字符串鍵 key 儲存的值。
 
復雜度為 O(1) 。
 
redis> SET msg "hello world"
OK
redis> GET msg
hello world
redis> SET number 10086
OK
redis> GET number
10086
 
 
示例:使用 Redis 來進行緩存
我們可以使用 Redis 來緩存一些經常會被用到、或者需要耗 費大量資源的內容,通過將這些內容放到Redis 里面(也即是內存里面),程序可以以極快的速度取得 這些內容。
 
舉個例子,對於一個網站來說,如果某個頁面經常會被訪問到,或者創建頁面時耗費的資源比較多(比
如需要多次訪問數據庫、生成時間比較長,等等),那么我們可以使用 Redis 將這個頁面緩存起來,減
輕網站的負擔,降低網站的延遲值。
@app.route("/")
def index():
    cached_content = cache.get('index')        # 嘗試從緩存里面獲取被緩存的頁面
    if cached_content:                         # 緩存存在,直接返回頁面
        return cached_content
    else:
        content = fetch_and_create_index()     # 頁面沒有被緩存,訪問數據庫並重新生成頁面
        cache.put('index', content)            # 緩存頁面,方便下次取出
        return content                         # 返回頁面
 
 
緩存程序的 API 及其實現
 
API     
效果
實現
Cache(client)
設置緩存程序使用的客戶端。
 
Cache.put(name, content)
把指定的內容放到緩存里面,並使用 name 來 命名它,以便之后取出。
調用 SET 命令。
Cache.get(name)
從緩存中取出以 name 命名的內容。 
調用 GET 命令。
 
緩存程序的具體實現請參考 cache.py 。
 
在之后我們還會實現根據時間自動失效的緩存。
cache.py
# coding: utf-8
 
class Cache:
 
    def __init__(self, client):
        self.client = client
 
    def put(self, name, content):
        self.client.set(name, content)
 
    def get(self, name):
        return self.client.get(name)
 
 
 
僅在鍵不存在的情況下進行設置
 
SETNX key value
 
僅在鍵 key 不存在的情況下,將鍵 key 的值設置為 value ,效果和 SET key value NX 一樣。
NX 的意思為“Not eXists”(不存在)。
 
鍵不存在並且設置成功時,命令返回 1 ;因為鍵已經存在而導致設置失敗時,命令返回 0 。
 
復雜度為 O(1) 。
redis> SETNX new-key "i am a new key!"
1
redis> SETNX new-key "another new key here!" # 鍵已經存在,設置失敗
0
redis> GET new-key # 鍵的值沒有改變
i am a new key!
 
 
同時設置或獲取多個字符串鍵的值
 
 
命令 
效果
復雜度
MSET key value [key value ...]
一次為一個或多個字符串鍵設置 值,效果和同時執行多個 SET 命 令一樣。 命令返回 OK
O(N),N 為要設置的字符串鍵 數量。
MGET key [key ...]
一次返回一個或多個字符串 鍵的 值,效果和同時執行多個 GET 命 令一樣。
O(N),N 為要獲取的字符串鍵 數量。
示例:設置或獲取個人信息
 
很多網站都會給你一個地方,填寫自己的個人信息、聯系信息、個人簡介等等,比如右圖就是某個網站上的個人信息 設置頁面。
 
通過將每項信息儲存在一個字符串鍵里面(比如電子郵件在 huangz::email 鍵、個人網站在 huangz::homepage 鍵、公司在huangz::company 鍵,等等),我們可以通過調用 MSET 來一次性設置多個項,並使用MGET 來一次性獲取多個項的信息。
 
MSET huangz::email " huangz1990@gmail.com" huangz::homepage " http://huangz.
me/" huangz::company "FakeCompany" huangz::position "Programmer" huangz::
location "廣東" huangz::sign "time waits for no one"
 
MGET huangz::email huangz::homepage huangz::company huangz::position ...
 
    
鍵的命名
 
因為 Redis 的數據庫不能出現兩個同名的鍵,所以我們通常會使用 field1::field2::field3 這樣的格式來區分同一類型的多個字符串鍵。
 
舉個例子,像前面儲存個人信息例子,因為網站里面不可能只有 huangz 一個用戶,所以我們不能用email 鍵來直接儲存 huangz 的郵件地址,而是使用 huangz::email ,這樣 huangz 的郵件地址就不會和其他用戶的郵件地址發生沖突 —— 比如用戶名為 peter 的用戶可以將它的郵件地址儲存到peter::email 鍵,而用戶名為 jack 的用戶也可以將它的郵件地址儲存到 jack::email 鍵,大家各不相關,互不影響。
 
一些更為復雜的鍵名例子: user::10086::info ,ID 為 10086 的用戶的信息; news::sport::cache ,新聞網站體育分類的緩存; message::123321::content ,ID 為 123321 的消息的內容。
 
:: 是比較常用的分割符,你也可以 選擇自己喜歡的其他分割符來命名鍵,
 
比如斜線 huangz/email 、豎線 huangz|email 、或者面向對象風格的 huangz.email 。
 
一次設置多個不存在的鍵
 
MSETNX key value [key value ...]
 
只有在所有給定鍵都不存在的情況下, MSETNX 會為所有給定鍵設置值,效果和同時執行多個SETNX 一樣。如果給定的鍵至少有一個是存在的,那么 MSETNX 將不執行任何設置操作。
 
返回 1 表示設置成功,返回 0 表示設置失敗。復雜度為 O(N) , N 為給定的鍵數量。
redis> MSETNX nx-1 "hello" nx-2 "world" nx-3 "good luck"
1
redis> SET ex-key "bad key here"
OK
redis> MSETNX nx-4 "apple" nx-5 "banana" ex-key "cherry" nx-6 "durian"
0
 
因為 ex-key 鍵已經存在,所以第二個 MSETNX 會執行失敗,所有鍵都不會被設置。
 
設置新值並返回舊值
 
GETSET key new-value
 
將字符串鍵的值設置為 new-value ,並返回字符串鍵在設置新值之前儲存的舊值(old value)。
復雜度為 O(1) 。
 
redis> SET getset-str "i'm old value"     # 先給字符串鍵設置一個值
OK
 
redis> GETSET getset-str "i'm new value"  # 更新字符串鍵的值,並返回之前儲存的舊值
i'm old value
 
redis> GET getset-str                     # 確認一下,新值已被設置
i'm new value
 
 
用偽代碼表示 GETSET 的定義
 
def GETSET(key, new-value):
    old-value = GET(key) # 記錄舊值
    SET(key, new-value) # 設置新值
    return old-value # 返回舊值
 
 
追加內容到字符串末尾
 
APPEND key value
 
將值 value 推入到字符串鍵 key 已儲存內容的末尾。
O(N), 其中 N 為被推入值的長度。
 
redis> SET myPhone "nokia"
OK
 
redis> APPEND myPhone "-1110"
(integer) 10
 
redis> GET myPhone
"nokia-1110"
 
 
返回值的長度
 
STRLEN key
 
返回字符串鍵 key 儲存的值的長度。
因為 Redis 會記錄每個字符串值的長度,所以獲取該值的復雜度為 O(1) 。
 
redis> SET msg "hello"
OK
 
redis> STRLEN msg
(integer) 5
 
redis> APPEND msg " world"
(integer) 11
 
redis> STRLEN msg
(integer) 11
 
 
 
 
2.索引和范圍
 
索引
 
字符串的索引(index)以 0 為開始,從字符串的開頭向字符串的結尾依次遞增,字符串第一個字符的索引為 0 ,字符串最后一個字符的索引 為 N-1 ,其中 N 為字符串的長度。
 
除了(正數)索引之外,字符串 還有負數索引:負數索引以 -1 為開始,從字符串的結尾向字符串的開頭依次遞減,字符串的最后一個字符的索引 為 -N ,其中 N 為字符串的長度。
 
 
 
 
 
 
范圍設置
 
SETRANGE key index value
 
從索引 index 開始,用 value 覆寫(overwrite)給定鍵 key 所儲存的字符串值。只接受正數索引。
命令返回覆寫之后,字符串 值的長度。復雜度為 O(N), N 為 value 的長度。
redis> SET msg "hello"
OK
redis> SETRANGE msg 1 "appy"
(integer) 5
redis> GET msg
"happy
 
 
 
范圍取值
 
GETRANGE key start end
 
返回鍵 key 儲存的字符串值中,位於 start 和 end 兩個索引之間的內容(閉區間,start 和 end 會被包括在內)。和 SETRANGE 只接受正數索引不同, GETRANGE 的索引可以是正數或者 負數。
 
復雜度為 O(N) , N 為被選中內容的長度。
redis> SET msg "hello world"
OK
redis> GETRANGE msg 0 4
"hello"
redis> GETRANGE msg -5 -1
"world"
 
3.數字操作
 
 
設置和獲取數字
 
只要儲存在字符串鍵里面的值可以被解釋為 64 位整數,或者 IEEE-754 標准的 64 位浮點數,
那么用戶就可以對這個字符串鍵執行針對數字值的命令。
 
 
能否執行數字值命令?
原因
10086
可以
值可以被解釋為整數
3.14
可以
值可以被解釋為浮點數
+123
可以
值可以被解釋為整數
123456789123456789123456789
不可以
值太大,沒辦法使用 64 位整數來儲存
2.0e7
不可以
Redis 不解釋以科學記數法表示的浮點數
123ABC
不可以
值包含文字
ABC
不可以
值為文字
 
 
增加或者減少數字的值
 
對於一個保存着數字的字符串 鍵 key ,我們可以使用 INCRBY 命令來增加它的值,或者使用 DECRBY命令來減少它的值。
 
INCRBY key increment 
O(1)
DECRBY key decrement 
 
 
命令
效果
復雜度
INCRBY key increment
將 key 所儲存的值加上增量 increment ,命令返回操作執行之后,鍵 key 的當前值。
O(1)
DECRBY key decrement
將 key 所儲存的值減去減量 decrement ,命令返回操作執行之后,鍵 key 的當前值。
O(1)
 
如果執行 INCRBY 或者 DECRBY 時,鍵 key 不存在,那么命令會將 鍵 key 的
值初始化為 0 ,然后再執行增加或者減少操作。
 
INCRBY / DECRBY 示例
redis> INCRBY num 100 # 鍵 num 不存在,命令先將 num 的值初始化為 0 ,
(integer) 100 # 然后再執行加 100 操作
 
redis> INCRBY num 25 # 將值再加上 25
(integer) 125
 
redis> DECRBY num 10 # 將值減少 10
(integer) 115
 
redis> DECRBY num 50 # 將值減少 50
(integer) 65
 
 
增一和減一 
因為針對數字值的增一和減一操作非常常見,所以 Redis 特別為這兩個操作創建了 INCR 命令和 DECR 命令。 
 
命令
效果
 復雜度
 INCR key
 等同於執行 INCRBY key 1
 O(1)
DECR key
等同於執行 DECRBY key 1
O(1) 
   
redis> SET num 10
 OK
redis> INCR num (integer)
 11
redis> DECR num (integer)
 10
 
 
計數器 API 及其實現
 
API
效果
實現
Counter(name, client)
設置計數器的名字以及客戶端。
 
Counter.incr()
將計數器的值增一,然后返回計數器的值。
調用 INCR 命令。
Counter.get()
返回計數器當前的值。
調用 GET 命令。
Counter.reset(n=0)
將計數器的值重置為 n ,默認重置為 0 。
調用 GETSET 命令。 雖然使用 SET 命令也可以達到重置的效果,但 使用 GETSET 可以在重置計數器的同時獲得 計數器之前的值,這有時候會有用。
 
 
c = Counter('page-counter', redis_client) # 創建一個名為 page-counter 的計數器
c.incr() # => 1
c.incr() # => 2
 
計數器實現的完整源碼請查看 counter.py 文件。
 
# encoding: utf-8
 
class Counter:
 
    def __init__(self, key, client):
        self.key = key
        self.client = client
 
    def incr(self, n=1):
        counter = self.client.incr(self.key, n)
        return int(counter)
 
    def decr(self, n=1):
        counter = self.client.decr(self.key, n)
        return int(counter)
 
    def reset(self, n=0):
        counter = self.client.getset(self.key, n)
        if counter is None:
            counter = 0
        return int(counter)
 
    def get(self):
        counter = self.client.get(self.key)
        if counter is None:
 
 
示例:id 生成器
很多網站在創建新條目的時候,都會使用 id 生成器來為條目創建唯一標識符。
 
舉個例子,對於一個論壇來說,每注冊一個新用戶,論壇都會為這個新用戶創建一個用戶 id ,比如12345 ,然后訪問 /user/12345 就可以看到這個用戶的個人頁面。
 
又比如說,當論壇里的用戶創建一個新帖子的時候,論壇都會為這個新帖子創建一個帖子 id ,比如10086 ,然后訪問 /topic/10086 就可以看到這個帖子的內容。
 
被創建的 id 通常都是連續的,比如說,如果最新創建的 id 為 1003 ,那么下一個生成的 id 就會是1004 ,再下一個 id 就是 1005 ,以此類推。
 
id 生成器 API 及其實現
 
API
效果
實現
IdGenerator(name, client)
設置 id 生成器的名字和客戶端。
 
IdGenerator.gen()
生成一個新的自增 id 。
調用 INCR 命令。
IdGenerator.init(n)
保留前 n 個 id ,防止搶注,需要在系統開始運作 前執行,否則會出現重復 id 。 舉個例子,如果要保留前一萬個 id ,那么就需要執 行 IdGenerator.init(10000),這樣生成器創建的 id 就會從 10001 開始。
調用 SET 命令。
 
generator = IdGenerator('user-id', redis_client) # 創建一個用戶 id 生成器
 
generator.init(10000) # 保留前一萬個 id
 
generator.gen() # => 10001
 
generator.gen() # => 10002 id 生成器的源代碼可以在 id_generator.py 找到
 
id_generator.py
# coding: utf-8
 
class IdGenerator:
 
    def __init__(self, key, client):
        self.key = key
        self.client = client
 
    def init(self, n):
        self.client.set(self.key, n)
 
    def gen(self):
        new_id = self.client.incr(self.key)
        return int(new_id)
 
 
浮點數的自增和自減
 
INCRBYFLOAT key increment
 
為字符串鍵 key 儲存的值加上浮點數增量 increment ,命令返回操作執行之后,鍵 key 的值。
 
沒有相應的 DECRBYFLOAT ,但可以通過給定負值來達到 DECRBYFLOAT 的效果。
 
復雜度為 O(1) 。
redis> SET num 10
OK
redis> INCRBYFLOAT num 3.14
"13.14"
redis> INCRBYFLOAT num -2.04 # 通過傳遞負值來達到做減法的效果
"11.1"
 
注意事項
 
即使字符串鍵儲存的是數字值,它也可以執行 APPEND、STRLEN、SETRANGE 和 GETRANGE 。
 
當用戶針對一個數字值執行這些命令的時候,Redis 會先將數字值轉換為字符串,然后再執行命令。
 
redis> SET number 123
OK
redis> STRLEN number # 轉換為 "123" ,然后計算這個字符串的長度
3
redis > APPEND number 456 # 轉換為 "123" ,然后與 "456" 進行拼接
6
redis> GET number
123456
 
 
4.二進制數據操作
 
 
設置和獲取二進制數據
 
SET 、GET 、SETNX、 APPEND 等命令同樣可以用於設置二進制數據。
 
# 因為 Redis 自帶的客戶端 redis-cli 沒辦法方便的設置二進制數據
# 所以這里使用 Python 客戶端來進行
 
>>> import redis
>>> r = redis.Redis()
>>> r.set('bits', 0b10010100) # 將字符串鍵 bits 的值設置為二進制 10010100
True
>>> bin(int(r.get('bits'))) # 獲取字符串鍵 bits 儲存的二進制值(需要進行轉換)
'0b10010100'
>>> r.append('bits', 0b111) # 將 0b111 (也即是十進制的 7)推入到 bits 已有二進制位的末尾
4L
>>> bin(int(r.get('bits'))) # 推入之前的值為 0b10010100 = 148
'0b10111001111' # 推入之后的值為 0b10111001111 = 1487
 
 
二進制位的索引 
 
和儲存文字時一樣,字符串鍵在儲存二進制位時,索引也是從 0 開始的。
 
 但是和儲存文字時,索引從左到右依次遞增不同,當字符串鍵儲存的是二進制位時,二進制位的索引會 從左到右依次遞減。
 
 
設置二進制位的值
 
SETBIT key index value
 
將給定索引上的二進制位的值設置為 value ,命令返回被設置的位原來儲存的舊值。 
 
復雜度為 O(1) 。
 
redis> SETBIT bits 2 1 (integer) 0
 
 
 
獲取二進制位的值
 
GETBIT key index
 
返回給定索引上的二進制位的值。
 
復雜度為 O(1) 。
 
redis> GETBIT bits 7
(integer) 1
redis> GETBIT bits 6
(integer) 0
redis> GETBIT bits 4
(integer) 1
 
 
 
 
 
計算值為 1 的二進制位的數量
 
BITCOUNT key [start] [end]
 
計算並返回字符串鍵儲存的值中,被設置為 1 的二進制位的數量。
 
一般情況下,給定的整個字符串鍵都會進行計數操作,但通過指定額外的 start 或 end 參數,可以讓計數只在特定索引范圍的位上進行。
 
start 和 end 參數的設置和 GETRANGE 命令類似,都可以使用負數值:比如 -1 表示最后一個位,而 -2表示倒數第二個位,以此 類推。
 
復雜度為 O(N) ,其中 N 為被計算二進制位的數量。
 
BITCOUNT 示例
 
 
 
 
帶有 start 和 end 參數的BITCOUNT 示例
 
 
 
redis> BITCOUNT bits 10 3
4
 
 
二進制位運算
 
BITOP operation destkey key [key ...]
 
對一個或多個保存二進制位的字符串鍵執行位元操作,並將結果保存到 destkey 上。
operation 可以是 AND 、 OR 、 NOT 、 XOR 這四種操作中的任意一種:
 
 
命令
效果
BITOP AND destkey key [key ...]
對一個或多個 key 求邏輯並,並將結果保存到 destkey 。
BITOP OR destkey key [key ...]
對一個或多個 key 求邏輯或,並將結果保存到 destkey 。
BITOP XOR destkey key [key ...]
對一個或多個 key 求邏輯或,並將結果保存到 destkey
BITOP NOT destkey key
對一個或多個 key 求邏輯異或,並將結果保存到 destkey 。
 
對給定 key 求邏輯非,並將結果保存到 destkey 。
 
除了 NOT 操作之外,其他操作都可以接受一個或以上數量的 key 作為輸入。
 
復雜度為 O(N) , N 為進行計算的二進制位數量的總和。
 
命令的返回值為計算所得結果的字節長度,相當於對 destkey 執行 STRLEN 。
 
 
BITOP 示例
 
假設現在 b1 鍵儲存了二進制 01001101 ,而 b2 鍵儲存了二進制 10110101 。
 
redis> BITOP AND b1-and-b2 b1 b2 # b1-and-b2 = 00000101
(integer) 1
redis> BITOP OR b1-or-b2 b1 b2 # b1-or-b2 = 11111101
(integer) 1
redis> BITOP XOR b1-xor-b2 b1 b2 # b1-xor-b2 = 11111000
(integer) 1
redis> BITOP NOT not-b1 b1 # not-b1 = 10110010
(integer) 1
 
 
示例:實現在線人數統計
 
一些網站具備了在線人數統計功能,通過這個功能可以看到一段時間以內(比如這個小時,或者這一天),曾經登錄過這個網站的會員人數。
 
某網站的在線人數統計結果,顯示目前有 289 個會員在線。
 
通過使用字符串鍵以及二進制數據處理命令,我們也可以構建一個高效並且 節約內存的在線人數統計實現。
 
 
在用戶 id 和位索引之間進行關聯
 
之前說過,字符串鍵儲存的每個二進制位都有與之對應的索引,比如對於一個 8 位長的二進制值來說,它的各個二進制位的索引值為 0 至 7 。
因為通常網站的每個會員都有一個自己的數字 id ,比如 peter的 id 可能是 3 ,而 jack 的 id 可能是 5 ,所以我們可以在用戶id 和二進制位的索引之間進行關聯:
• 如果 id 為 N 的用戶在線,我們就將索引為 N 的二進制位的值設置為 1 。
• 如果索引為 N 的二進制位的值為 0 ,這表示 id 為 N 用戶不在線。
• 使用 BITCOUNT 可以統計有多少個用戶在線。
• 通過為每段時間分別儲存一個二進制值,我們就可以為每段時間都記錄在線用戶的數量。(每小時創建一個鍵或者每天創建一個鍵,諸如此類。)
 
 
 
 
在線用戶統計的 API 及其實現
 
API
作用
實現
OnlineCount(when, client)
記錄給定時間內的在線用戶數量。
 
OnlineCount.include(user_id)
將給定的用戶記錄為在線。
調用 SETBIT 命令。
OnlineCount.result()
返回給定時間內的在線用戶數量。
調用 BITCOUNT 命令。
 
count = OnlineCount(‘2014-8-3 10a.m.’) # 記錄 2014 年 8 月 3 日上午 10 點的在線用戶數量
count.include(4) # 將 id 為 4 的用戶設置為在線
count.include(5) # 將 id 為 5 的用戶設置為在線
count.include(7) # 將 id 為 7 的用戶設置為在線
count.result() # 返回 3 ,表示有三個用戶在線
在線用戶統計程序的完整實現代碼可以在 online_count.py 查看。
 
# encoding: utf-8
 
class OnlineCount:
 
    def __init__(self, when, client):
        self.when = when
        self.client = client
 
    def include(self, user_id):
        return self.client.setbit(self.when, user_id, 1)
 
    def result(self):
        return self.client.bitcount(self.when)
 
 
關於用戶在線統計的更多信息
 
目前這個實現的優點:
  • 將用戶設置為在線的速度非常快, O(1) 。
  • 即使用戶數量非常大,占用的內存也不多:記錄一百萬用戶僅需一百萬位,也即是 0.125 MB;記錄一千萬用戶僅需一千萬位,也即是 1.25 MB 。
  • 可以在現有程序的基礎上,做進一步的操作。舉個例子,我們可以使用 BITOP AND 命令,將多個在線記錄作為輸入,計算出全勤用戶的數量(全勤指的是,用戶在所有輸入的在線統計記錄中,都顯示為在線)。
 
目前這個實現的缺點:
  • 每次進行統計的復雜度為 O(N) 。
  • 沒辦法輕易地獲取所有在線用戶的名單,只能遍歷整個二進制值,復雜度為 O(N) ,其中 N 為二進制位數量。
 
進一步的優化:
  • 用戶量不大並且需要獲取在線用戶名單的話,可以使用之后介紹的集合數據結構來實現。
  • 不需要獲取在線用戶名單,並且不需要精確的在線統計數量,可以使用之后介紹的 HyperLogLog 來實現。
 
示例:使用 Redis 緩存熱門圖片
 
圖片網站要儲存大量的圖片(通常放在硬盤里面),而少部分熱門的圖片會被經常地訪問到。
 
為了加快網站獲取熱門圖片的速度,我們可以利用 Redis 能夠儲存二進制數據這一特性,使用之前構建的緩存程序來緩存圖片網站中的熱門圖片。
 
cache = Cache(redis_client) # 設置緩存的客戶端
file = open('redis-logo.jpg', 'r') # 打開文件
data = file.read() # 讀取文件數據
file.close() # 關閉文件
cache.put('redis-logo', data) # 以 redis-logo 為名字,將圖片緩存起來
cache.get('redis-logo') # 取出 redis-logo 圖片的數據
 
 
5.儲存中文時的注意事項
 
STRLEN、SETRANGE 和 GETRANGE 不適用於中文
 
注意事項
 
一個英文字符只需要使用 單個字節來儲存,而一個中文字符卻需要使用多個字 節來儲存。
 
STRLEN、SETRANGE 和 GETRANGE 都是為英文設置的,它們只會在字符為單個字節的情況下正常工作,而一旦我們儲存的是類似中文這樣的多字節字符,那么這三個命令就不再適用了。
 
 
STRLEN 示例
$ redis-cli --raw                 # 在 redis-cli 中使用中文時,必須打開 --raw 選項,才能正常顯示中文
redis> SET msg "世界你好"         # 設置四個中文字符
OK
redis> GET msg         # 儲存中文沒有問題
世界你好    
redis> STRLEN msg     # 這里 STRLEN 顯示了“世界你好”的字節長度為 12 字節
12                     # 但我們真正想知道的是 msg 鍵里面包含多少個字符
 
 
 
 
SETRANGE 和 GETRANGE 示例
 
SETRANGE 和 GETRANGE 的情況也是類似的:因為這兩個命令所使用的索引是根據字 節而不是字符來編排的,所以調用 SETRANGE 或者 GETRANGE 來處理中文,得不到我們想要的結果。
 
r
edis> SET msg "世界你好"
OK
redis> GETRANGE msg 2 3 # 試圖獲取 "你好"
redis> SETRANGE msg 2 "歡迎你" # 試圖構建 "世界歡迎你",其中"歡迎你"為 9 字節長
12
redis> GET msg
��歡迎你�
 
 
 
 
結論
不要使用 STRLEN、SETRANGE 和 GETRANGE 來處理中文。
例外情況:如果你想知道被 儲存的中文包含多少個字節,那么可以使用 STRLEN 。
 


免責聲明!

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



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