文章目录
1、定义
redis是一个key-value存储系统,和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型),这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的,在此基础上redis支持各种不同方式的排序,与memcached一样,为了保证效率,数据都是缓存在内存中,区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步
1、cs架构,key-value存储(没有表,各种关系)
2、redis是存储数据的软件,跟语言无关,纯内存数据库(所有数据都放在内存中)
3、速度非常快,支持的数据类型多样(5大数据类型: 字符串,列表,字典,集合,有序集合)
4、Memcached和redis比较
(1) redis是单线程,单进程,数据类型丰富(只针对于 redis 6.0以下)
(2) memcache多线程多进程,数据类型单一,
redis为什么单线程,单进程速度这么快?
-10w,生产单机6w左右
-纯内存数据库
-io多路复用,epoll模型(linux上支持),windows上支持select
-单线程单进程,避免了线程间切换
5、redis: 开源软件,c语言写的,早期版本2w3千行,对windows不支持 6.0.6
在不同平台编译 ---> 可执行文件 ---> 执行
windows官方: 把源码在windows上编译 ---> 可以允许在windows上(3.x)
1、使用Redis有哪些好处?
(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
(2) 支持丰富数据类型,支持string,list,set,sorted set,hash
(3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
(4) 丰富的特性: 可用于缓存消息,按key设置过期时间,过期后将会自动删除
2、redis相比memcached有哪些优势?
(1) memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型
(2) redis的速度比memcached快很多
(3) redis可以持久化其数据
3、redis常见性能问题和解决方案:
(1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件
(2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
(3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内
(4) 尽量避免在压力很大的主库上增加从库
(5) 主从复制不要用图状结构,用单向链表结构更为稳定,即: Master <- Slave1 <- Slave2 <- Slave3...
这样的结构方便解决单点故障问题,实现Slave对Master的替换,如果Master挂了,可以立刻启用Slave1做Master,其他不变
4、MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据
相关知识: redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略,redis提供6种数据淘汰策略:
voltile-lru: 从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl: 从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random: 从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru: 从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random: 从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐): 禁止驱逐数据
5、Memcache与Redis的区别都有哪些?
(1) 存储方式
Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小
Redis有部份存在硬盘上,这样能保证数据的持久性
(2) 数据支持类型
Memcache对数据类型支持相对简单
Redis有复杂的数据类型
(3) value大小
redis最大可以达到1GB,而memcache只有1MB
6、Redis 常见的性能问题都有哪些,如何解决?
(1) Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照
(2) Master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度,Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化,如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次
(3) Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象
(4) Redis主从复制的性能问题,为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内
7、redis 最适合的场景
Redis最适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别,那么可能大家就会有疑问,似乎Redis更像一个加强版的Memcached,那么何时使用Memcached,何时使用Redis呢?
如果简单地比较Redis与Memcached的区别,大多数都会得到以下观:
1、Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储
2、Redis支持数据的备份,即master-slave模式的数据备份
3、Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用
(1) 会话缓存(Session Cache)
最常用的一种使用Redis的情景是会话缓存(session cache),用Redis缓存会话比其他存储(如Memcached)的优势在于: Redis提供持久化,当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在他们还会这样吗?
幸运的是随着 Redis 这些年的改进,很容易找到怎么恰当的使用Redis来缓存会话的文档,甚至广为人知的商业平台Magento也提供Redis的插件
(2) 全页缓存(FPC)
除基本的会话token之外,Redis还提供很简便的FPC平台,回到一致性问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似PHP本地FPC
再次以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端
此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面
(3) 队列
Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用,Redis作为队列使用的操作,就类似于本地程序语言(如Python)对list的push/pop操作
如果你快速的在Google中搜索"Redis queues",你马上就能找到大量的开源项目,这些项目的目的就是利用Redis创建非常好的后端工具,以满足各种队列需求,例如Celery有一个后台就是使用Redis作为broker,你可以从这里去查看
(4) 排行榜/计数器
Redis在内存中对数字进行递增或递减的操作实现的非常好,集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构,所以,我们要从排序集合中获取到排名最靠前的10个用户–我们称之为"user_scores",我们只需要像下面一样执行即可:
当然,这是假定你是根据你用户的分数做递增的排序,如果你想返回用户及用户的分数,你需要这样执行:
ZRANGE user_scores 0 10 WITHSCORES
Agora Games就是一个很好的例子,用Ruby实现的,它的排行榜就是使用Redis来存储数据的,你可以在这里看到
(5) 发布/订阅
最后(但肯定不是最不重要的)是Redis的发布/订阅功能,发布/订阅的使用场景确实非常多,我已看见人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系统!
Redis提供的所有特性中,我感觉这个是喜欢的人最少的一个,虽然它为用户提供如果此多功能
2、redis的windows安装和配置
1、https://github.com/microsoftarchive/redis/releases
Redis-x64-3.2.100.msi: 一路下一步,安装完成(添加环境变量)
2、6379: 端口号
3、自动创建服务,服务运行
本质是一条命令: redis-server redis.windows-service.conf
redis-server 配置文件: 以这个配置文件启动服务
4、手动启动redis的服务端
redis-server: 服务端
redis-server: 启动但是使用的是默认配置
redis-server 配置文件: 以该配置文件启动
redis-cli: 客户端
redis-cli: 默认连接到本地的6379端口
redis-cli -h 127.0.0.1 -p 6379
图形化客户端: redis-desktop-manager: 图形化客户端(收费)
3、普通链接和连接池
1、使用python连接redis
2、安装redis模块: pip3 install redis
3、使用python代码连接redis服务端,python代码就是客户端,跟使用图形化界面是一样的
GUI ---> 可以开发出图形化界面的redis客户端
3.1、普通链接
redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py
from redis import Redis
# 普通链接
# 拿到一个redis连接
conn = Redis() # 默认参数可以直接实例化
# conn = Redis(host='127.0.0.1', port=6379)
# 使用连接操作
conn.set('name', 'allen')
# 获取操作
res = conn.get('name')
print(res) # b'allen'
conn.close()
3.2、连接池
redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销,默认每个Redis实例都会维护一个自己的连接池,可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池
# 连接池
import redis
# 创建出一个连接池
pool = redis.ConnectionPool(host='127.0.0.1', port=6379, max_connections=100)
# 从连接池中拿一个连接
conn = redis.Redis(connection_pool=pool)
conn.set('age', 18)
res = conn.get('age')
print(res) # b'18'
conn.close()
实际应用
redis_pool.py
import redis
POOL = redis.ConnectionPool(host='127.0.0.1', port=6379, max_connections=100)
使用
import redis
from redis_pool import POOL
conn = redis.Redis(connection_pool=POOL)
conn.set('gender', 'male')
res = conn.get('gender') # b'male'
print(res)
conn.close()
4、redis操作数据类型
4.1、redis之string操作
String操作,redis中的String在在内存中按照一个name对应一个value来存储,如图:
1、set(name, value, ex=None, px=None, nx=False, xx=False)
在Redis中设置值,默认不存在则创建,存在则修改
参数:
ex,过期时间(秒)
px,过期时间(毫秒)
nx,如果设置为True,则只有name不存在时,当前set操作才执行,值存在,就修改不了,执行没效果
xx,如果设置为True,则只有name存在时,当前set操作才执行,值存在才能修改,值不存在,不会设置新值
示例:
conn = redis.Redis(connection_pool=POOL)
conn.set('name', 'allen')
conn.set('name', 'lucy', nx=True) # 无法设置成功
conn.set('name', 'jack', xx=True) # 设置成功
conn.set('age', 18, xx=True) # 设置成功
conn.close()
2、setnx(name, value)
设置值,只有name不存在时,执行设置操作(添加),如果存在,不会修改
示例:
conn.setnx('name', 'tom') # 无法设置成功
3、setex(name, value, time)
设置值
参数:
time,过期时间(数字秒 或 timedelta对象)
示例:
conn.setex('name',3,'allen') # 3秒后消失
4、psetex(name, time_ms, value)
设置值
参数:
time_ms,过期时间(数字毫秒或timedelta对象)
5、mset(*args, **kwargs)
批量设置值
示例:
conn.mset({'k1': 111, 'k2': 222})
6、get(name)
获取值
7、mget(keys, *args)
批量获取
示例:
mget('k1', 'k2')
或
r.mget(['k1', 'k2'])
8、getset(name, value)
设置新值并获取原来的值
一次网络io,完成了取值和设置
示例:
conn.getset('name', 'allen') # 如果name之前不存在本次返回None,再访问返回allen
9、getrange(key, start, end)
获取子序列(根据字节获取,非字符)
前闭后闭区间
参数:
name,Redis的name
start,起始位置(字节)
end,结束位置(字节)
示例:
res = conn.getrange('name', 0, 3)
print(res) # b'alle'
# 等同于如下操作:
res = conn.get('name')
print(res[0:4]) # b'alle'
10、setrange(name, offset, value)
修改字符串内容,从指定字符串索引开始向后替换(新值太长时则向后添加)
参数:
offset,字符串的索引,字节(一个汉字三个字节)
value,要设置的值
示例:
# 原本name对应的值是allen
conn.setrange('name', 2, 'aaaaa')
print(conn.get('name')) # b'alaaaaa'
11、setbit(name, offset, value)
对name对应值的二进制表示的位进行操作
参数:
name,redis的name
offset,位的索引(将值变换成二进制后再进行索引)
value,值只能是1或 0
注: 如果在Redis中有一个对应: n1 = "foo",
那么字符串foo的二进制表示为: 01100110 01101111 01101111
所以,如果执行 setbit('n1', 7, 1),则就会将第7位设置为1
那么最终二进制则变成 01100111 01101111 01101111,即: "goo"
12、getbit(name, offset)
获取name对应的值的二进制表示中的某位的值(0或1)
示例:
获取bit位的第几个位置,看是1还是0
res = conn.getbit('n1',7)
print(res)
13、bitcount(key, start=None, end=None)
获取name对应的值的二进制表示中 1 的个数
参数:
key,Redis的name
start,位起始位置
end,位结束位置
end指的是bytes,前闭后闭区间
示例:
res=conn.bitcount('n1',0,1)
print(res)
14、bitop(operation, dest, *keys)
获取多个值,并将值做位运算,将最后的结果保存至新的name对应的值
参数:
operation,AND(并)、OR(或)、NOT(非)、XOR(异或)
dest,新的Redis的name
*keys,要查找的Redis的name
示例:
bitop("AND", 'new_name', 'n1', 'n2', 'n3')
获取Redis中n1,n2,n3对应的值,然后讲所有的值做位运算(求并集),然后将结果保存 new_name 对应的值中
15、strlen(name)
返回name对应值的字节长度(一个汉字3个字节),不存在的值返回0
16、incr(self, name, amount=1)
自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增
每次自增1
统计网页访问量,文章阅读量,粉丝数量,计数相关(不会存在并发安全的问题)
参数:
name,Redis的name
amount,自增数(必须是整数)
注: 同incrby
示例:
conn.incr('age')
conn.incr('age', 5)
conn.incr('age', -2)
17、incrbyfloat(self, name, amount=1.0)
自增name对应的值,当name不存在时,则创建name=amount,否则,则自增
参数:
name,Redis的name
amount,自增数(浮点型)
18、decr(self, name, amount=1)
自减name对应的值,当name不存在时,则创建name=amount,否则,则自减
参数:
name,Redis的name
amount,自减数(整数)
19、append(key, value)
在redis name对应的值后面追加内容
参数:
key,redis的name
value,要追加的字符串
示例:
conn.set('hobby', 'read')
conn.append('hobby', 'ing')
4.2、redis之hash操作
Hash操作,redis中Hash在内存中的存储格式如下图:
1、hset(name, key, value)
name对应的hash中设置一个键值对(不存在,则创建,否则,修改)
参数:
name,redis的name
key,name对应的hash中的key
value,name对应的hash中的value
注:
hsetnx(name, key, value),当name对应的hash中不存在当前key时则创建(相当于添加)
示例:
conn.hset('userinfo', 'name', 'allen')
conn.hset('userinfo', 'age', '18')
conn.hset('userinfo', 'gender', '男')
2、hmset(name, mapping)
在name对应的hash中批量设置键值对
参数:
name,redis的name
mapping,字典,如: {'k1':'v1', 'k2': 'v2'}
示例:
conn.hmset('userinfo2', {'name': 'allen1', 'age': '18', 'gender': '男'})
3、hget(name,key)
在name对应的hash中获取根据key获取value
示例:
conn.hget('userinfo', 'name')
4、hmget(name, keys, *args)
在name对应的hash中获取多个key的值
参数:
name,reids对应的name
keys,要获取key集合,如:['k1', 'k2', 'k3']
*args,要获取的key,如:k1,k2,k3
示例:
conn.hmget('userinfo', 'name', 'age', 'gender')
或
conn.hmget('userinfo', ['name', 'age', 'gender'])
5、hgetall(name)
获取name对应hash的所有键值
示例:
conn.hgetall('userinfo')
6、hlen(name)
获取name对应的hash中键值对的个数
示例:
conn.hlen('userinfo')
7、hkeys(name)
获取name对应的hash中所有的key的值
示例:
conn.hkeys('userinfo')
8、hvals(name)
获取name对应的hash中所有的value的值
示例:
conn.hvals('userinfo')
9、hexists(name, key)
检查name对应的hash是否存在当前传入的key
示例:
conn.hexists('userinfo', 'name')
conn.hexists('userinfo', 'name1')
10、hdel(name,*keys)
将name对应的hash中指定key的键值对删除
示例:
conn.hdel('userinfo', 'name', 'age')
11、hincrby(name, key, amount=1)
自增name对应的hash中的指定key的值,不存在则创建key=amount
参数:
name,redis中的name
key,hash对应的key
amount,自增数(整数)
示例:
conn.hincrby('userinfo', 'age', 5)
12、hincrbyfloat(name, key, amount=1.0)
自增name对应的hash中的指定key的值,不存在则创建key=amount
参数:
name,redis中的name
key,hash对应的key
amount,自增数(浮点数)
自增name对应的hash中的指定key的值,不存在则创建key=amount
13、hscan(name, cursor=0, match=None, count=None)
增量式迭代获取,对于数据大的数据非常有用,hscan可以实现分片的获取数据,并非一次性将数据全部获取完,从而防止内存被撑爆
参数:
name,redis的name
cursor,游标(基于游标分批取获取数据)
match,匹配指定key,默认None 表示所有的key
count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数
示例:
第一次: cursor1, data1 = r.hscan('xx', cursor=0, match=None, count=None)
第二次: cursor2, data1 = r.hscan('xx', cursor=cursor1, match=None, count=None)
...
直到返回值cursor的值为0时,表示数据已经通过分片获取完毕
for i in range(1000):
conn.hset('userinfo', 'user_{id}'.format(id=str(i)), '{id}'.format(id=str(i)))
print(conn.hgetall('userinfo')) # 这种方式不推荐
print(conn.hscan('userinfo', count=5))
14、hscan_iter(name, match=None, count=None)
利用yield封装hscan创建生成器,实现分批去redis中获取数据
参数:
match,匹配指定key,默认None表示所有的key
count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数
示例:
for item in r.hscan_iter('xx'):
print item
# 以后要使用hgetall的时候,要使用如下方式
for item in conn.hscan_iter('userinfo', count=10):
print(item)
4.3、redis之list操作
List操作,redis中的List在在内存中按照一个name对应一个List来存储,如图:
1、lpush(name,values)
在name对应的list中添加元素,每个新的元素都添加到列表的最左边
示例:
conn.lpush('l1',11,22,33)
保存顺序为: 33,22,11
扩展:
rpush(name, values) 表示从右向左操作
2、lpushx(name,value)
在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边
示例:
conn.lpushx('l1', 44) # l1存在,所以44可以放进去
conn.lpushx('xxx', 222) # xxx不存在,所以222放不进去
扩展:
rpushx(name, value) 表示从右向左操作
3、llen(name)
name对应的list元素的个数
示例:
conn.llen('l1')
4、linsert(name, where, refvalue, value))
在name对应的列表的某一个值前或后插入一个新值
参数:
name,redis的name
where,BEFORE或AFTER(小写也可以)
refvalue,标杆值,即: 在它前后插入数据(如果存在多个标杆值,以找到的第一个为准,不是下标索引)
value,要插入的数据
示例:
# l1中数据: [33,22,11]
conn.linsert('l1', 'after', 22, 44) # [33,22,44,11]
conn.linsert('l1', 'before', 22, 55) # [33,55,22,44,11]
5、lset(name, index, value)
对name对应的list中的某一个索引位置重新赋值
参数:
name,redis的name
index,list的索引位置
value,要设置的值
示例:
# l1中数据: [33,22,11]
conn.lset('l1', 1, 55) # [33,55,11]
5、lrem(name, value, num)
在name对应的list中删除指定的值
参数:
name,redis的name
value,要删除的值
num, num=0,删除列表中所有的指定值
num=2,从前到后,删除2个
num=-2,从后向前,删除2个
示例:
conn.lrem('l1', 0, 'allen')
conn.lrem('l1', 3, 'allen')
conn.lrem('l1', -2, 'allen')
6、lpop(name)
在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素
示例:
conn.lpop('l1')
更多:
rpop(name) 表示从右向左操作
7、lindex(name, index)
在name对应的列表中根据索引获取列表元素
示例:
conn.lindex('l1', 2)
8、lrange(name, start, end)
在name对应的列表分片获取数据
参数:
name,redis的name
start,索引的起始位置
end,索引结束位置 print(re.lrange('aa',0,re.llen('aa')))
示例:
conn.lrange('l1', 1, 3) # 前闭后闭区间
conn.lrange('l1', 0, 0) # 取出第一个值
9、ltrim(name, start, end)
在name对应的列表中移除没有在start-end索引之间的值
参数:
name,redis的name
start,索引的起始位置
end,索引结束位置(大于列表长度,则代表不移除任何)
示例:
conn.ltrim('l1', 1, 3) # 返回下标为1到3对应的值,其余的全删除
10、rpoplpush(src, dst)
从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
参数:
src,要取数据的列表的name
dst,要添加数据的列表的name
示例:
conn.rpoplpush('l1', 'l1') # 也可以使用两个列表操作
11、blpop(keys, timeout)
将多个列表排列,按照从左到右去pop对应列表的元素
参数:
keys,redis的name的集合
timeout,超时时间,当元素所有列表的元素获取完之后,阻塞等待列表内有数据的时间(秒),0表示永远阻塞
示例:
conn.blpop('l1') # 如果l1里面有值直接返回,没有值会一直阻塞等到有值再返回
更多:
brpop(keys, timeout),从右向左获取数据
爬虫实现简单分布式: 多个url放到列表里,往里不停放URL,程序循环取值,但是只能一台机器运行取值,可以把url放到redis中,多台机器从redis中取值,爬取数据,实现简单分布式
12、brpoplpush(src, dst, timeout=0)
从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧
参数:
src,取出并要移除元素的列表对应的name
dst,要插入元素的列表对应的name
timeout,当src对应的列表中没有数据时,阻塞等待其有数据的超时时间(秒),0表示永远阻塞
13、自定义增量迭代
由于redis类库中没有提供对列表元素的增量迭代,如果想要循环name对应的列表的所有元素,那么就需要:
(1) 获取name对应的所有列表
(2) 循环列表
但是,如果列表非常大,那么就有可能在第一步时就将程序的内容撑爆,所有有必要自定义一个增量迭代的功能,借助lrange
# 向列表中插入10000个数据
for i in range(10000):
conn.lpush('l_test', 'test_%s' % i)
# 类似于字典的hgetall,一次性全取出来,存在的问题是,因为不知道列表有多大,很有可能撑爆内存,不推荐
res = conn.lrange('l_test', 0, conn.llen('l_test'))
print(res)
# 自定义方法,类似于hscan_iter取值
def lscan_iter(name, conn, count=10):
cursor = 0
length = conn.llen(name)
while cursor < length:
data = conn.lrange(name, cursor, (cursor + count) - 1)
if data:
cursor += count
for item in data:
yield item
else:
break
# 获取值
for i in lscan_iter('l_test', conn, 20):
print(i)
集合和有序集合参考:https://blog.csdn.net/wcg920212/article/details/111847924
5、redis之其它操作
1、delete(*names)
根据删除redis中的任意数据类型
示例:
conn.delete('name')
2、exists(name)
检测redis的name是否存在
示例:
conn.delete('name')
3、keys(pattern='*')
根据模型获取redis的name
更多:
KEYS * 匹配数据库中所有key
KEYS h?llo 匹配hello,hallo和hxllo等
KEYS h*llo 匹配hllo和heeeeello等
KEYS h[ae]llo 匹配 hello和hallo,但不匹配 hillo
示例:
conn.keys('n*')
conn.keys('n?me')
4、expire(name ,time)
为某个redis的某个name设置超时时间
示例:
conn.expire('name', 5)
5、rename(src, dst)
对redis的name重命名
示例:
conn.rename('name', 'new_name')
6、move(name, db))
将redis的某个值移动到指定的db下,redis的库是隔离的
示例:
conn.move('name', 3) # 将name移动到了3号库中
7、randomkey()
随机获取一个redis的name(不删除)
示例:
conn.randomkey()
8、type(name)
获取name对应值的类型
示例:
conn.type('name')
9、scan(cursor=0, match=None, count=None)
scan_iter(match=None, count=None)
同字符串操作,用于增量迭代获取key
6、django中使用redis
6.1、通用方案
redis_pool.py
import redis
POOL=redis.ConnectionPool(host='127.0.0.1',port=6379,max_connections=100)
views.py
from utils.redis_pool import POOL
import redis
def test_redis(request):
conn=redis.Redis(connection_pool=POOL)
age=str(conn.get('age'),encoding='utf-8')
return HttpResponse('年龄是: %s' % age)
6.2、基于django-redis方案
安装django-redis模块
pip3 install django-redis
配置文件
# setting中redis配置
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100}
# "PASSWORD": "123",
}
}
}
views.py
from django_redis import get_redis_connection
def test_django_redis(request):
# 从连接池中拿到连接
conn=get_redis_connection()
age = str(conn.get('age'), encoding='utf-8')
return HttpResponse('年龄是: %s' % age)
# 配置文件中配置以后,也可以这样使用
from django.core.cache import cache
cache.set('name','allen',4) # 往缓存中放key和value,其实放到了redis中了
cache.set('xxx',函数名称) # 也可以存放进去,因为set的时候使用了pickle,所以可以存放