redis

简介

1,redis是什么

redis是NoSql的一种,NoSql,全名:Not Only Sql,是一种非关系型数据库,它不能替代关系弄数据库,只是关系型数据库的一个补充,是可以解决高并发、高可用、高扩展、大数据存储等一系列问题而产生的数据库解决方案。

redis是一种支持Key-Value等多种数据结构的存储系统。可用于缓存,事件发布或订阅,高速队列等场景。该数据库使用ANSI C语言编写,支持网络,redis支持的键值类型有:String字符类型、map散列类型、list列表类型、set集合类型、sortedset有序集合类型。基于内存,可持久化。

2,redis的应用场景有哪些

1,会话缓存(最常用)

2,消息队列,比如支付

3,活动排行榜或计数

4,发布,订阅消息(消息通知)

5,商品列表,评论列表等

安装Redis

下载redis:

1
wget http://download.redis.io/releases/redis-3.0.0.tar.gz

使用ll命令查看当前目录下所有文件

可以看到redis-3.0.0.tar.gz就是刚刚下载的redis压缩包,现在对其解压:

1
tar -zxvf redis-3.0.0.tar.gz

再使用ll命令查看当前目录下所有文件

编译安装Redis

进入redis源码:

1
cd redis-3.0.0

通过ll命令可以看到Redis源码目录下的所有文件,接下来就需要对源码进行编译了:

1
make

使用make命令编译Redis需要c语言环境,CentOS自带c语言环境,若是使用其他Linux系统中没有c语言环境,则需要安装,如yum安装: yum install gcc-c++

编译过后,就是安装了,安装Redis的命令如下:

1
make install PREFIX=/usr/local/redis

该命令中,前面的”make install PREFIX=”是固定的,而”/usr/local/redis”是Redis的安装目录,一般就这么写,如若需要安装在其他地方,只需将此路径更换即可。

最后,查看Redis是否安装成功:

1
cd /usr/local/redis/

使用ll命令,可以看到bin文件夹,说明Redis已经安装成功。

Redis启动与停止

Redis有两种启动,分别是:前端启动、后端启动。要启动Redis,就需要到Redis的bin目录下执行启动命令,先看看bin目录结构:

启动的配置:

第一步,需要把redis源码目录下的redis.conf文件复制到redis安装目录的bin目录下。

第二步,修改redis.conf文件,将daemonize的值改为yes后保存。

启动的命令:

1
[root@localhost bin]# ./redis-server redis.conf

可以发现后端启动命令就只是比前端启动命令多了” redis.conf”,意思很明确,就是让redis根据这个配置文件的配置运行罢了,同时也可以看到,在启动完redis后台,终端不会进入redis控制台,这就是将redis运行后台了,我们可以查查看系统现在是不是有redis的进程:

1
[root@localhost bin]# ps -aux | grep redis

关闭命令:

1
2
强制关闭:[root@localhost bin]# kill -9 进程id
正常关闭:[root@localhost bin]# ./redis-cli shutdown

因为后端启动redis,没办法像前端启动redis那样直接ctrl+c强制关闭redis,如果需要强制关闭,那只能通过杀死进程的方式停止redis。而正常关闭redis的命令与前端关闭一样,这里就不多说废话。

项目中,建议使用正常关闭。因为redis作为缓存来使用的话,将数据存储到内存中,如果使用正常关闭,则会将内存数据持久化到本地之后,再关闭。如果强制关闭,则不会进行持久化操作,可能会造成部分数据丢失。

Redis开启远程访问

redis默认只允许本地访问,要使redis可以远程访问可以修改redis.conf

开启远程访问

将第70行的bind注释,第90行将protected-mode改为no

设置密码

取消第502行的注释,并修改密码

重启redis:

1
2
3
4
5
#首先查询到redis的pid后,kill掉,然后重启
[root@localhost bin]# ps -ef|grep redis
root 20940 1 0 12:12 ? 00:00:18 ./redis-server *:6379
[root@localhost bin]# kill 20940
[root@localhost bin]# ./redis-server redis.conf

最后我们使用redis客户端通过密码远程连接:

1
2
#远程连接
./redis-cli -h 你服务器的ip -p 6379 -a 你的密码

redis.conf 配置项说明

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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程

    daemonize no

2. 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定

    pidfile /var/run/redis.pid

3. 指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字

    port 6379

4. 绑定的主机地址

    bind 127.0.0.1

5.当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能

    timeout 300

6. 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose

    loglevel verbose

7. 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null

    logfile stdout

8. 设置数据库的数量,默认数据库为0,可以使用SELECT <dbid>命令在连接上指定数据库id

    databases 16

9. 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合

    save <seconds> <changes>

    Redis默认配置文件中提供了三个条件:

    save 900 1

    save 300 10

    save 60 10000

    分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。

 

10. 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大

    rdbcompression yes

11. 指定本地数据库文件名,默认值为dump.rdb

    dbfilename dump.rdb

12. 指定本地数据库存放目录

    dir ./

13. 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步

    slaveof <masterip> <masterport>

14. 当master服务设置了密码保护时,slav服务连接master的密码

    masterauth <master-password>

15. 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH <password>命令提供密码,默认关闭

    requirepass foobared

16. 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息

    maxclients 128

17. 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区

    maxmemory <bytes>

18. 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no

    appendonly no

19. 指定更新日志文件名,默认为appendonly.aof

     appendfilename appendonly.aof

20. 指定更新日志条件,共有3个可选值:
    no:表示等操作系统进行数据缓存同步到磁盘(快)
    always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
    everysec:表示每秒同步一次(折中,默认值)

    appendfsync everysec

 

21. 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)

     vm-enabled no

22. 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享

     vm-swap-file /tmp/redis.swap

23. 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0

     vm-max-memory 0

24. Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值

     vm-page-size 32

25. 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。

     vm-pages 134217728

26. 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4

     vm-max-threads 4

27. 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启

    glueoutputbuf yes

28. 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法

    hash-max-zipmap-entries 64

    hash-max-zipmap-value 512

29. 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)

    activerehashing yes

30. 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件

    include /path/to/local.conf

python操作redis

1、连接方式

  redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类

1
2
3
4
5
import redis

r = redis.Redis(host='192.168.0.110', port=6379,db=0)
r.set('name', 'zhangsan') #添加
print (r.get('name')) #获取

2、连接池

redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。

1
2
3
4
5
6
import redis

pool = redis.ConnectionPool(host='192.168.0.110', port=6379)
r = redis.Redis(connection_pool=pool)
r.set('name', 'zhangsan') #添加
print (r.get('name')) #获取

3、操作

1、String 操作

redis中的String在在内存中按照一个name对应一个value来存储

set()
1
2
3
4
5
6
7
8
#在Redis中设置值,默认不存在则创建,存在则修改
r.set('name', 'zhangsan')
'''参数:
set(name, value, ex=None, px=None, nx=False, xx=False)
ex,过期时间(秒)
px,过期时间(毫秒)
nx,如果设置为True,则只有name不存在时,当前set操作才执行,同setnx(name, value)
xx,如果设置为True,则只有name存在时,当前set操作才执行'''
1
2
3
4
5
setex(name, value, time)
#设置过期时间(秒)

psetex(name, time_ms, value)
#设置过期时间(豪秒
mset()
1
2
3
4
#批量设置值
r.mset(name1='zhangsan', name2='lisi')
#或
r.mget({"name1":'zhangsan', "name2":'lisi'})
get(name)

获取值

mget(keys, *args)
1
2
3
4
5
#批量获取
print(r.mget("name1","name2"))
#或
li=["name1","name2"]
print(r.mget(li))
getset(name, value)
1
2
3
#设置新值,打印原值
print(r.getset("name1","wangwu")) #输出:zhangsan
print(r.get("name1")) #输出:wangwu
getrange(key, start, end)
1
2
3
#根据字节获取子序列
r.set("name","zhangsan")
print(r.getrange("name",0,3))#输出:zhan
setrange(name, offset, value)
1
2
3
4
5
6
#修改字符串内容,从指定字符串索引开始向后替换,如果新值太长时,则向后添加
r.set("name","zhangsan")
r.setrange("name",1,"z")
print(r.get("name")) #输出:zzangsan
r.setrange("name",6,"zzzzzzz")
print(r.get("name")) #输出:zzangszzzzzzz
setbit(name, offset, value)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#对二进制表示位进行操作
''' name:redis的name
offset,位的索引(将值对应的ASCII码变换成二进制后再进行索引)
value,值只能是 10 '''

str="345"
r.set("name",str)
for i in str:
print(i,ord(i),bin(ord(i)))#输出 值、ASCII码中对应的值、对应值转换的二进制
'''
输出:
51 0b110011
52 0b110100
53 0b110101'''

r.setbit("name",6,0)#把第7位改为0,也就是3对应的变成了0b110001
print(r.get("name"))#输出:145
getbit(name, offset)
1
2
3
4
#获取name对应值的二进制中某位的值(01)
r.set("name","3") # 对应的二进制0b110011
print(r.getbit("name",5)) #输出:0
print(r.getbit("name",6)) #输出:1
bitcount(key, start=None, end=None)
1
2
3
4
5
6
#获取对应二进制中1的个数
r.set("name","345")#0b110011 0b110100 0b110101
print(r.bitcount("name",start=0,end=1)) #输出:7
''' key:Redis的name
start:字节起始位置
end:字节结束位置'''
strlen(name)
1
2
3
#返回name对应值的字节长度(一个汉字3个字节)
r.set("name","zhangsan")
print(r.strlen("name")) #输出:8
incr(self, name, amount=1)
1
2
3
4
5
6
#自增mount对应的值,当mount不存在时,则创建mount=amount,否则,则自增,amount为自增数(整数)
print(r.incr("mount",amount=2))#输出:2
print(r.incr("mount"))#输出:3
print(r.incr("mount",amount=3))#输出:6
print(r.incr("mount",amount=6))#输出:12
print(r.get("mount")) #输出:12
incrbyfloat(self, name, amount=1.0)
1
#类似 incr() 自增,amount为自增数(浮点数)
decr(self, name, amount=1)
1
#自减name对应的值,当name不存在时,则创建name=amount,否则,则自减,amount为自增数(整数)
append(name, value)
1
2
3
4
5
#在name对应的值后面追加内容
r.set("name","zhangsan")
print(r.get("name")) #输出:'zhangsan
r.append("name","lisi")
print(r.get("name")) #输出:zhangsanlisi

2、Hash 操作

redis中的Hash 在内存中类似于一个name对应一个dic来存储

hset(name, key, value)
1
2
#name对应的hash中设置一个键值对(不存在,则创建,否则,修改)
r.hset("dic_name","a1","aa")
hget(name,key)
1
2
3
r.hset("dic_name","a1","aa")
#在name对应的hash中根据key获取value
print(r.hget("dic_name","a1"))#输出:aa
hgetall(name)
1
2
#获取name对应hash的所有键值
print(r.hgetall("dic_name"))
hmset(name, mapping)
1
2
3
4
#在name对应的hash中批量设置键值对,mapping:字典
dic={"a1":"aa","b1":"bb"}
r.hmset("dic_name",dic)
print(r.hget("dic_name","b1"))#输出:bb
hmget(name, keys, *args)
1
2
3
4
# 在name对应的hash中获取多个key的值
li=["a1","b1"]
print(r.hmget("dic_name",li))
print(r.hmget("dic_name","a1","b1"))
hlen(name)、hkeys(name)、hvals(name)
1
2
3
4
5
6
7
8
9
10
11
dic={"a1":"aa","b1":"bb"}
r.hmset("dic_name",dic)

#hlen(name) 获取hash中键值对的个数
print(r.hlen("dic_name"))

#hkeys(name) 获取hash中所有的key的值
print(r.hkeys("dic_name"))

#hvals(name) 获取hash中所有的value的值
print(r.hvals("dic_name"))
hexists(name, key)
1
2
#检查name对应的hash是否存在当前传入的key
print(r.hexists("dic_name","a1"))#输出:True
hdel(name,*keys)
1
2
#删除指定name对应的key所在的键值对
r.hdel("dic_name","a1")
hincrby(name, key, amount=1)
1
2
#自增hash中key对应的值,不存在则创建key=amount(amount为整数)
print(r.hincrby("demo","a",amount=2))
hincrbyfloat(name, key, amount=1.0)
1
#自增hash中key对应的值,不存在则创建key=amount(amount为浮点数)
hscan(name, cursor=0, match=None, count=None)
hscan_iter(name, match=None, count=None)

3、List 操作

redis中的List在在内存中按照一个name对应一个List来存储

lpush(name,values)
1
2
3
# 在name对应的list中添加元素,每个新的元素都添加到列表的最左边
r.lpush("list_name",2)
r.lpush("list_name",3,4,5)#保存在列表中的顺序为5432
rpush(name,values)
1
#同lpush,但每个新的元素都添加到列表的最右边
lpushx(name,value)
1
#在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边
rpushx(name,value)
1
#在name对应的list中添加元素,只有name已经存在时,值添加到列表的最右边
llen(name)
1
2
# name对应的list元素的个数
print(r.llen("list_name"))
linsert(name, where, refvalue, value))
1
2
3
4
5
6
7
8
# 在name对应的列表的某一个值前或后插入一个新值
r.linsert("list_name","BEFORE","2","SS")#在列表内找到第一个元素2,在它前面插入SS

'''参数:
name: redis的name
where: BEFORE(前)或AFTER(后)
refvalue: 列表内的值
value: 要插入的数据'''
r.lset(name, index, value)
1
2
#对list中的某一个索引位置重新赋值
r.lset("list_name",0,"bbb")
r.lrem(name, value, num)
1
2
3
4
5
6
7
8
9
#删除name对应的list中的指定值
r.lrem("list_name","SS",num=0)

''' 参数:
name: redis的name
value: 要删除的值
num: num=0 删除列表中所有的指定值;
num=2 从前到后,删除2个;
num=-2 从后向前,删除2个'''
lpop(name)
1
2
#移除列表的左侧第一个元素,返回值则是第一个元素
print(r.lpop("list_name"))
lindex(name, index)
1
2
#根据索引获取列表内元素
print(r.lindex("list_name",1))
lrange(name, start, end)
1
2
#分片获取元素
print(r.lrange("list_name",0,-1))
ltrim(name, start, end)
1
2
#移除列表内没有在该索引之内的值
r.ltrim("list_name",0,2)
rpoplpush(src, dst)
1
2
3
# 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
#src 要取数据的列表
#dst 要添加数据的列表
brpoplpush(src, dst, timeout=0)
1
2
#同rpoplpush,多了个timeout, timeout:取数据的列表没元素后的阻塞时间,0为一直阻塞
r.brpoplpush("list_name","list_name1",timeout=0)
blpop(keys, timeout)
1
2
3
4
5
6
7
8
9
10
#将多个列表排列,按照从左到右去移除各个列表内的元素
r.lpush("list_name",3,4,5)
r.lpush("list_name1",3,4,5)

while True:
print(r.blpop(["list_name","list_name1"],timeout=0))
print(r.lrange("list_name",0,-1),r.lrange("list_name1",0,-1))

'''keys: redis的name的集合
timeout: 超时时间,获取完所有列表的元素之后,阻塞等待列表内有数据的时间(秒), 0 表示永远阻塞'''
r.brpop(keys, timeout)
1
#同blpop,将多个列表排列,按照从右像左去移除各个列表内的元素

4、Set 操作

Set集合就是不允许重复的列表

sadd(name,values)
1
2
3
#给name对应的集合中添加元素
r.sadd("set_name","aa")
r.sadd("set_name","aa","bb")
smembers(name)
1
#获取name对应的集合的所有成员
scard(name)
1
2
#获取name对应的集合中的元素个数
r.scard("set_name")
sdiff(keys, *args)
1
2
3
4
5
6
#在第一个name对应的集合中且不在其他name对应的集合的元素集合
r.sadd("set_name","aa","bb")
r.sadd("set_name1","bb","cc")
r.sadd("set_name2","bb","cc","dd")

print(r.sdiff("set_name","set_name1","set_name2"))#输出:{aa
sdiffstore(dest, keys, *args)
1
#相当于把sdiff获取的值加入到dest对应的集合中
sinter(keys, *args)
1
2
3
4
5
6
# 获取多个name对应集合的并集
r.sadd("set_name","aa","bb")
r.sadd("set_name1","bb","cc")
r.sadd("set_name2","bb","cc","dd")

print(r.sinter("set_name","set_name1","set_name2"))#输出:{bb
sinterstore(dest, keys, *args)
1
#获取多个name对应集合的并集,再讲其加入到dest对应的集合中
sismember(name, value)
1
#检查value是否是name对应的集合内的元素
smove(src, dst, value)
1
#将某个元素从一个集合中移动到另外一个集合
spop(name)
1
#从集合的右侧移除一个元素,并将其返回
srandmember(name, numbers)
1
2
# 从name对应的集合中随机获取numbers个元素
print(r.srandmember("set_name2",2))
srem(name, values)
1
2
#删除name对应的集合中的某些值
print(r.srem("set_name2","bb","dd"))
sunion(keys, *args)
1
2
#获取多个name对应的集合的并集
r.sunion("set_name","set_name1","set_name2")
sunionstore(dest,keys, *args)
1
#获取多个name对应的集合的并集,并将结果保存到dest对应的集合中

5、有序集合:

在集合的基础上,为每元素排序,元素的排序需要根据另外一个值来进行比较,所以,对于有序集合,每一个元素有两个值,即:值和分数,分数专门用来做排序。

zadd(name, *args, **kwargs)
1
2
3
4
# 在name对应的有序集合中添加元素
r.zadd("zset_name", "a1", 6, "a2", 2,"a3",5)
#或
r.zadd('zset_name1', b1=10, b2=5)
zcard(name)
1
#获取有序集合内元素的数量
zcount(name, min, max)
1
2
#获取有序集合中分数在[min,max]之间的个数
print(r.zcount("zset_name",1,5))
zincrby(name, value, amount)
1
2
#自增有序集合内value对应的分数
r.zincrby("zset_name","a1",amount=2)#自增zset_name对应的有序集合里a1对应的分数
zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)
1
2
3
4
5
6
7
8
9
10
# 按照索引范围获取name对应的有序集合的元素
aa=r.zrange("zset_name",0,1,desc=False,withscores=True,score_cast_func=int)
print(aa)
'''参数:
name redis的name
start 有序集合索引起始位置
end 有序集合索引结束位置
desc 排序规则,默认按照分数从小到大排序
withscores 是否获取元素的分数,默认只获取元素的值
score_cast_func 对分数进行数据转换的函数'''
zrevrange(name, start, end, withscores=False, score_cast_func=float)
1
#同zrange,集合是从大到小排序的
zrank(name, value)、zrevrank(name, value)
1
2
3
4
#获取value值在name对应的有序集合中的排行位置(从0开始)
print(r.zrank("zset_name", "a2"))

print(r.zrevrank("zset_name", "a2"))#从大到小排序
zscore(name, value)
1
2
#获取name对应有序集合中 value 对应的分数
print(r.zscore("zset_name","a1"))
zrem(name, values)
1
2
#删除name对应的有序集合中值是values的成员
r.zrem("zset_name","a1","a2")
zremrangebyrank(name, min, max)
1
#根据排行范围删除
zremrangebyscore(name, min, max)
1
#根据分数范围删除
zinterstore(dest, keys, aggregate=None)
1
2
3
4
5
6
7
r.zadd("zset_name", "a1", 6, "a2", 2,"a3",5)
r.zadd('zset_name1', a1=7,b1=10, b2=5)

# 获取两个有序集合的交集并放入dest集合,如果遇到相同值不同分数,则按照aggregate进行操作
# aggregate的值为: SUM MIN MAX
r.zinterstore("zset_name2",("zset_name1","zset_name"),aggregate="MAX")
print(r.zscan("zset_name2"))
zunionstore(dest, keys, aggregate=None)
1
#获取两个有序集合的并集并放入dest集合,其他同zinterstore,

6、其他常用操作

delete(*names)
1
#根据name删除redis中的任意数据类型
exists(name)
1
#检测redis的name是否存在
keys(pattern=’*’)
1
#根据* ?等通配符匹配获取redis的name
expire(name ,time)
1
# 为某个name设置超时时间
rename(src, dst)
1
# 重命名
move(name, db))
1
# 将redis的某个值移动到指定的db下
randomkey()
1
#随机获取一个redis的name(不删除)
type(name)
1
# 获取name对应值的类型

4、管道

redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。

1
2
3
4
5
6
7
8
9
10
import redis
pool = redis.ConnectionPool(host='192.168.0.110', port=6379)
r = redis.Redis(connection_pool=pool)

pipe = r.pipeline(transaction=True)

r.set('name', 'zhangsan')
r.set('name', 'lisi')

pipe.execute()

5、发布和订阅

首先定义一个RedisHelper类,连接Redis,定义频道为monitor,定义发布(publish)及订阅(subscribe)方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import redis

class RedisHelper(object):
def __init__(self):
self.__conn = redis.Redis(host='192.168.0.110',port=6379)#连接Redis
self.channel = 'monitor' #定义名称

def publish(self,msg):#定义发布方法
self.__conn.publish(self.channel,msg)
return True

def subscribe(self):#定义订阅方法
pub = self.__conn.pubsub()
pub.subscribe(self.channel)
pub.parse_response()
return pub

发布者

1
2
3
4
5
#发布
from RedisHelper import RedisHelper

obj = RedisHelper()
obj.publish('hello')#发布

订阅者

1
2
3
4
5
6
7
8
9
#订阅
from RedisHelper import RedisHelper

obj = RedisHelper()
redis_sub = obj.subscribe()#调用订阅方法

while True:
msg= redis_sub.parse_response()
print (msg)