一
Redis 中最简单的数据结构,它既可以储存文字(比如 "hello world"),又可以储存数字(比如整数10086 和浮点数 3.14),还可以储存二进制数据(比如 10010100)。Redis 为这几种类型的值分别设置了相应的操作命令,让用户可以针对不同的值做不同的处理。
为字符串键设置值、获取字符串键的值、获取字符串值的长度,等等。
二
2.1为字符串键设置值
SET key value
将字符串键 key 的值设置为 value ,命令返回 OK 表示设置成功
如果字符串键 key 已经存在,那么用新值覆盖原来的旧值
复杂度为 O(1)
redis> SET msg "hello world"
redis> SET msg "goodbye" # 覆盖原来的值 "hello world"
SET key value [NX|XX] 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 # 键存在,指定 NX 选项是可行的
OK
2.2 获取字符串的值 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
2.3缓存程序的 API 及其实现
2.4仅在键不存在的情况下进行设置
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!
2.5同时设置或获取多个字符串键的值
2.6追加内容到字符串末尾
APPEND key value
将值 value 推入到字符串键 key 已储存内容的末尾。 O(N), 其中 N 为被推入值的长度。
redis> SET myPhone "nokia" OK
redis> APPEND myPhone "-1110" (integer) 10
redis> GET myPhone "nokia-1110"
2.7返回值的长度
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

三索引
字符串的索引(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"
四设置和获取数字
INCRBY key increment : 将 key 所储存的值加上增量 increment ,命 令返回操作执行之后,键 key 的当前值。O(1)
DECRBY key decrement : 将 key 所储存的值减去减量 decrement ,命 令返回操作执行之后,键 key 的当前值。O(1)
如果执行 INCRBY 或者 DECRBY 时,键 key 不存在,那么命令会将 键 key 的 值初始化为 0 ,然后再执行增加或者减少操作。
redis> INCRBY num 100 # 键 num 不存在,命令先将 num 的值初始化为 0 ,然后再执行加 100 操作
(integer) 100
redis> INCRBY num 25 # 将值再加上 25
(integer) 125
redis> DECRBY num 10 # 将值减少 10
(integer) 115
redis> DECRBY num 50 # 将值减少 50
(integer) 65
增一和减一
NCR 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 及其实现
c = Counter('page-counter', redis_client) # 创建一个名为 page-counter 的计数器
c.incr() # => 1
c.incr() # => 2
设置和获取二进制数据
SET,GET,SETNX,APPEND等命令同样可以用于设置二进制数据
#因为Redis自带的客户端redis-cli没办法方便的设置二进制数据
import redis
r=redis.Redis()
r.set('bits',0b10010100) #将字符串bits的值设置为二进制10010100
bin(int(r.get('bits'))) #获取字符串键bits存储的二进制值(需要进行转换)
r.append('bits', 0b111) #将ob111(也就是十进制的7) 推入到bits已有二进制位的末尾
bin(int(r.get('bits'))) #推入之前的值为0b10010100=148
#推入之后的值为0b10111001111=1487
六二进制位的索引
6.1 和储存文字时一样,字符串键在储存二进制位时,索引也是从 0 开始的。
但是和储存文字时,索引从左到右依次递增不同,当字符串键储存的是二进制位时,二进制位的索引会 从左到右依次 递减。

6.2设置二进制位的值 SETBIT key index value 将给定索引上的二进制位的值设置为 value ,命令返回被设置的位原来储存的旧值。 复杂度为 O(1) 。 redis> SETBIT bits 2 1 (integer) 0
6.3获取二进制位的值 GETBIT key index 返回给定索引上的二进制位的值。 复杂度为 O(1) 。 redis> GETBIT bits 7 #(integer) 1 redis> GETBIT bits 6 #(integer) 0 redis> GETBIT bits 4 #(integer) 1
7储存中文时的注意事项
STRLEN、SETRANGE 和 GETRANGE 不适用于中文
一个英文字符只需要使用 单个字节来储存,而一个中文字符却需要使用多个字节来储存
TRLEN、SETRANGE 和 GETRANGE 都是为英文设置的,它们只会在字符为单个字节的情况下正常工作,而一旦我们储存的是类似中文这样的多字节字符那么这三个命令就不再适用了。
STRLEN示例
redis-cli --raw # 在 redis-cli 中使用中文时,必须打开 --raw 选项,才能正常显示中文
redis> SET msg "世界你好" # 设置四个中文字符
redis> SET msg "世界你好" # 设置四个中文字符
世界你好
redis> STRLEN msg # 这里 STRLEN 显示了“世界你好”的字节长度为 12 字节
12 #但我们真正想知道的是 msg 键里面包含多少个字符
SETRANGE 和 GETRANGE 示例
SETRANGE 和 GETRANGE 的情况也是类似的:因为这两个命令所使用的索引是根据字 节而不是字符来编排的,
所以调用 SETRANGE或者GETRANGE来处理中文,得不到我们想要的结果。
redis> SET msg "世界你好"
redis> GETRANGE msg 2 3
redis> SETRANGE msg 2 "欢迎你"
redis> GET msg
#coding: utf-8
class Cache:
def __init__(selfself,client):
self.client = client
def put(self,name, content):
self.client.set(name,content)
def get(selfself,name):
return self.client.get(name)
# 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:
# 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)
# 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)