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 。
 

转载于:https://www.cnblogs.com/ykyk1229/p/9674587.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值