简介
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.conf”,意思很明确,就是让redis根据这个配置文件的配置运行罢了,同时也可以看到,在启动完redis后台,终端不会进入redis控制台,这就是将redis运行后台了,我们可以查查看系统现在是不是有redis的进程:
1 | [root@localhost bin] |
关闭命令:
1 | 强制关闭:[root@localhost bin] |
因为后端启动redis,没办法像前端启动redis那样直接ctrl+c强制关闭redis,如果需要强制关闭,那只能通过杀死进程的方式停止redis。而正常关闭redis的命令与前端关闭一样,这里就不多说废话。
项目中,建议使用正常关闭。因为redis作为缓存来使用的话,将数据存储到内存中,如果使用正常关闭,则会将内存数据持久化到本地之后,再关闭。如果强制关闭,则不会进行持久化操作,可能会造成部分数据丢失。
Redis开启远程访问
redis默认只允许本地访问,要使redis可以远程访问可以修改redis.conf
开启远程访问
将第70行的bind注释,第90行将protected-mode改为no
设置密码
取消第502行的注释,并修改密码
重启redis:
1 |
|
最后我们使用redis客户端通过密码远程连接:
1 | #远程连接 |
redis.conf 配置项说明
1 | 1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程 |
python操作redis
1、连接方式
redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类
1 | import redis |
2、连接池
redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。
1 | import redis |
3、操作
1、String 操作
redis中的String在在内存中按照一个name对应一个value来存储
set()
1 | #在Redis中设置值,默认不存在则创建,存在则修改 |
1 | setex(name, value, time) |
mset()
1 |
|
get(name)
获取值
mget(keys, *args)
1 | #批量获取 |
getset(name, value)
1 | #设置新值,打印原值 |
getrange(key, start, end)
1 | #根据字节获取子序列 |
setrange(name, offset, value)
1 | #修改字符串内容,从指定字符串索引开始向后替换,如果新值太长时,则向后添加 |
setbit(name, offset, value)
1 | #对二进制表示位进行操作 |
getbit(name, offset)
1 | #获取name对应值的二进制中某位的值(0或1) |
bitcount(key, start=None, end=None)
1 | #获取对应二进制中1的个数 |
strlen(name)
1 | #返回name对应值的字节长度(一个汉字3个字节) |
incr(self, name, amount=1)
1 | #自增mount对应的值,当mount不存在时,则创建mount=amount,否则,则自增,amount为自增数(整数) |
incrbyfloat(self, name, amount=1.0)
1 | #类似 incr() 自增,amount为自增数(浮点数) |
decr(self, name, amount=1)
1 | #自减name对应的值,当name不存在时,则创建name=amount,否则,则自减,amount为自增数(整数) |
append(name, value)
1 | #在name对应的值后面追加内容 |
2、Hash 操作
redis中的Hash 在内存中类似于一个name对应一个dic来存储
hset(name, key, value)
1 | #name对应的hash中设置一个键值对(不存在,则创建,否则,修改) |
hget(name,key)
1 | r.hset("dic_name","a1","aa") |
hgetall(name)
1 | #获取name对应hash的所有键值 |
hmset(name, mapping)
1 | #在name对应的hash中批量设置键值对,mapping:字典 |
hmget(name, keys, *args)
1 | # 在name对应的hash中获取多个key的值 |
hlen(name)、hkeys(name)、hvals(name)
1 | dic={"a1":"aa","b1":"bb"} |
hexists(name, key)
1 | #检查name对应的hash是否存在当前传入的key |
hdel(name,*keys)
1 | #删除指定name对应的key所在的键值对 |
hincrby(name, key, amount=1)
1 | #自增hash中key对应的值,不存在则创建key=amount(amount为整数) |
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 | # 在name对应的list中添加元素,每个新的元素都添加到列表的最左边 |
rpush(name,values)
1 |
lpushx(name,value)
1 | #在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边 |
rpushx(name,value)
1 | #在name对应的list中添加元素,只有name已经存在时,值添加到列表的最右边 |
llen(name)
1 | # name对应的list元素的个数 |
linsert(name, where, refvalue, value))
1 | # 在name对应的列表的某一个值前或后插入一个新值 |
r.lset(name, index, value)
1 | #对list中的某一个索引位置重新赋值 |
r.lrem(name, value, num)
1 | #删除name对应的list中的指定值 |
lpop(name)
1 | #移除列表的左侧第一个元素,返回值则是第一个元素 |
lindex(name, index)
1 | #根据索引获取列表内元素 |
lrange(name, start, end)
1 | #分片获取元素 |
ltrim(name, start, end)
1 | #移除列表内没有在该索引之内的值 |
rpoplpush(src, dst)
1 |
brpoplpush(src, dst, timeout=0)
1 | #同rpoplpush,多了个timeout, timeout:取数据的列表没元素后的阻塞时间,0为一直阻塞 |
blpop(keys, timeout)
1 | #将多个列表排列,按照从左到右去移除各个列表内的元素 |
r.brpop(keys, timeout)
1 |
4、Set 操作
Set集合就是不允许重复的列表
sadd(name,values)
1 | #给name对应的集合中添加元素 |
smembers(name)
1 |
scard(name)
1 |
|
sdiff(keys, *args)
1 | #在第一个name对应的集合中且不在其他name对应的集合的元素集合 |
sdiffstore(dest, keys, *args)
1 |
sinter(keys, *args)
1 | # 获取多个name对应集合的并集 |
sinterstore(dest, keys, *args)
1 |
sismember(name, value)
1 | #检查value是否是name对应的集合内的元素 |
smove(src, dst, value)
1 |
spop(name)
1 |
srandmember(name, numbers)
1 | # 从name对应的集合中随机获取numbers个元素 |
srem(name, values)
1 | #删除name对应的集合中的某些值 |
sunion(keys, *args)
1 |
|
sunionstore(dest,keys, *args)
1 |
5、有序集合:
在集合的基础上,为每元素排序,元素的排序需要根据另外一个值来进行比较,所以,对于有序集合,每一个元素有两个值,即:值和分数,分数专门用来做排序。
zadd(name, *args, **kwargs)
1 | # 在name对应的有序集合中添加元素 |
zcard(name)
1 |
zcount(name, min, max)
1 | #获取有序集合中分数在[min,max]之间的个数 |
zincrby(name, value, amount)
1 | #自增有序集合内value对应的分数 |
zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)
1 | # 按照索引范围获取name对应的有序集合的元素 |
zrevrange(name, start, end, withscores=False, score_cast_func=float)
1 |
zrank(name, value)、zrevrank(name, value)
1 | #获取value值在name对应的有序集合中的排行位置(从0开始) |
zscore(name, value)
1 | #获取name对应有序集合中 value 对应的分数 |
zrem(name, values)
1 |
|
zremrangebyrank(name, min, max)
1 |
zremrangebyscore(name, min, max)
1 |
zinterstore(dest, keys, aggregate=None)
1 | r.zadd("zset_name", "a1", 6, "a2", 2,"a3",5) |
zunionstore(dest, keys, aggregate=None)
1 |
6、其他常用操作
delete(*names)
1 |
exists(name)
1 |
keys(pattern=’*’)
1 |
expire(name ,time)
1 |
rename(src, dst)
1 |
move(name, db))
1 |
randomkey()
1 |
type(name)
1 |
4、管道
redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。
1 | import redis |
5、发布和订阅
首先定义一个RedisHelper类,连接Redis,定义频道为monitor,定义发布(publish)及订阅(subscribe)方法。
1 | import redis |
发布者
1 | #发布 |
订阅者
1 | #订阅 |