但行好事,莫问前程

挖了太多坑,一点点填回来

Redis实验(1)

linux, python, redis

研究了一下redis的常用技巧。

除了SET方法之外,redis还有MSET方法可以批量设置,如果发现有同名的key存在,就会覆盖原有的key。如果不想覆盖已经存在的key,请使用MSETNX方法。

用法:MSET key value [key value …]

1
2
3
4
5
6
7
redis> MSET key1 "Hello" key2 "World"
OK
redis> GET key1
"Hello"
redis> GET key2
"World"
redis> 

用法:MSETNX key value [key value …]

1
2
3
4
5
6
7
8
9
redis> MSETNX key1 "Hello" key2 "there"
(integer) 1
redis> MSETNX key2 "there" key3 "world"
(integer) 0
redis> MGET key1 key2 key3
1) "Hello"
2) "there"
3) (nil)
redis> 

查讯key就要使用KEYS方法,文档中提到KEYS方法速度很快,虽然时间复杂度是O(N),但是在一台入门级的笔记本电脑上,搜索100W条key,redis只需要40毫秒左右。但是在生产环境上,还是尽量不要使用KEYS命令,而是使用set来进行查询。

Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases. This command is intended for debugging and special operations, such as changing your keyspace layout. Don’t use KEYS in your regular application code. If you’re looking for a way to find keys in a subset of your keyspace, consider using sets.

用法:KEYS pattern

1
2
3
4
5
6
7
8
9
10
11
12
13
14
redis> MSET one 1 two 2 three 3 four 4
OK
redis> KEYS *o*
1) "two"
2) "one"
3) "four"
redis> KEYS t??
1) "two"
redis> KEYS *
1) "two"
2) "three"
3) "one"
4) "four"
redis> 

在redis里,排序是一件比较复杂的事情,官方文档写得很详细

用法:SORT key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern …]] [ASC|DESC] [ALPHA] [STORE destination]。正常排序还是很好理解的,直接SORT key LIMIT offset count ASC|DESC ALPHA即可,LIMIT和SQL语句中的含义一样,一般用来做分页用;ASC|DESC就是升序/降序排列;ALPHA表示将元素都当作字符串对待。

不过在使用外部key进行排序的时候,就有点复杂了。

举个例子,SORT mylist BY weight_* GET object_*。首先就要求你在mylist中存储是所有weight_*的id,而这句话的意思就是根据weight进行升序排序,并获得对应的id,并由此获得对应的排序完成的object值。用SQL来描述就是:SELECT object FROM table ORDER BY weight ASC;。同样还有用hashes来进行排序的——SORT mylist BY weight_*->fieldname GET object_*->fieldname,这就好比SELECT b.fielname FROM weight a LEFT JOIN object b ON a.id=b.id ORDER BY a.fieldname ASC;。更详细的内容,还是参考文档

下面是一部分测试代码,里面有更详细的注释。

(demo.py) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#coding: utf-8

import redis
import random
import string


def gen_random_string(length=10, chars=string.ascii_letters+string.digits):
    """
    生成指定长度的随机字符串
    """
    return "".join([random.choice(chars) for x in range(length)])


r = redis.Redis(db=1)
r.flushdb()

data = dict(
    caiknife=1,
    cai=2,
    zhi=3,
    jiang=4,
    knife=5,
    test=6
)

r.mset(data)

print r.mget(['cai', 'caiknife'])
"""
获得key=cai和key=caiknife的值
['2', '1']
"""

print r.keys('*cai*')
"""
匹配包含cai的key
['cai', 'caiknife']
"""

print r.keys('c??')
"""
匹配以c开头,长度为3的key
['cai']
"""

print r.keys('k[n]*')
"""
匹配k开头,包含0个或者多个n的key
['knife']
"""

print r.keys('*')
"""
匹配所有key
['zhi', 'test', 'jiang', 'knife', 'cai', 'caiknife']
"""

r.flushdb()

"""
生成10个随机数据 id    name    score
"""
data = [dict(id=x, score=random.randint(0, 100), name=gen_random_string()) for x in range(1, 11)]

for d in data:
    r.lpush('id', d['id'])
    r.set('name:%d' % d['id'], d['name'])
    r.set('score:%d' % d['id'], d['score'])


for d in sorted(data, key=lambda x: x['score']):
    print d
"""
按照score进行升序排序
{'score': 7, 'name': 'Uir8Pfo27c', 'id': 2}
{'score': 17, 'name': 'oFhLHSu42X', 'id': 7}
{'score': 19, 'name': 'C3DWCos4wq', 'id': 10}
{'score': 56, 'name': 'I7JRymyPJ5', 'id': 9}
{'score': 58, 'name': 'gJPkpD1TGn', 'id': 6}
{'score': 63, 'name': 'Vzt7gy2349', 'id': 1}
{'score': 75, 'name': 'eRHfRbeWrW', 'id': 4}
{'score': 77, 'name': 'Kja64ofoP1', 'id': 3}
{'score': 85, 'name': 'VRRPhp5Vmz', 'id': 8}
{'score': 94, 'name': 'm5mKg1s7Ji', 'id': 5}
"""

print r.sort('id', by='score:*')
"""
根据score获得排序后的id
['2', '7', '10', '9', '6', '1', '4', '3', '8', '5']
"""

print r.sort('id', by='score:*', get=['#', 'name:*', 'score:*'])
"""
根据score获得排序后的id, name, score, 返回的是一个N*M的数组,N是id的数量,M是GET中所取属性的数量
['2', '7', '10', '9', '6', '1', '4', '3', '8', '5']
['2', 'Uir8Pfo27c', '7', 
 '7', 'oFhLHSu42X', '17', 
 '10', 'C3DWCos4wq', '19', 
 '9', 'I7JRymyPJ5', '56', 
 '6', 'gJPkpD1TGn', '58', 
 '1', 'Vzt7gy2349', '63', 
 '4', 'eRHfRbeWrW', '75', 
 '3', 'Kja64ofoP1', '77', 
 '8', 'VRRPhp5Vmz', '85', 
 '5', 'm5mKg1s7Ji', '94']
"""

Have a nice day!