目录
Redis使用
安装
Python操作Redis普通连接
1 pip install redis
#简单使用
from redis import Redis
#获取redis连接
conn = Redis(host='127.0.0.1',port=6379)
#key取值
ret = conn.get('name')
print(ret)#b'alex'
Python操作Redis连接池
#redis_pool
edis_pool.py
import redis
#连接池对象,最大连接数100
POOL = redis.ConnectionPool(host='127.0.0.1',port=6379,max_connections=100)
#redis_pool
edis_pool.py
import redis
from redis_pool import POOL
#执行这句话就是从连接池拿出一个连接
r = redis.Redis(connection_pool=POOL)
ret = r.get('name')
print(ret)#b'alex'
Redis数据类型
string(字符串)
list(列表)
set(集合)
zset(有序集合)
hash(哈希)
String(字符串)操作
string在内存中按照一个name一个value来存储,看图1
#加*表示重点
set(name, value, ex=None, px=None, nx=False, xx=False)*
#设置值,不存在则创建,存在则修改,
参数:
ex过期时间秒
px过期时间毫秒
nx为True时,key不存在时,才会执行,key存在则不执行操作
xx为True时,key不存在时,不会执行操作,key存在才会执行
setnx(name, value)
#设置值,key不存在,才会执行,存在不会执行操作
setex(name, value, time)
#设置值,参数time过期时间数字秒,或timedelta对象
psetex(name, time_ms, value)
#设置值,参数time_ms过期时间数字毫秒,或timedelta对象
mset(*args,**kwargs)*
#批量设置值,如
mset(k1='v1',k2='v2')
mset({'k1':'v1','k2':'v2'})
get(key)*
#获取值
mget(keys,*args)*
#批量获取,如
mget('k1','k2')
mget(['k1','k2'])
getset(name, value)*
#设置值并获取原来的值
getrange(key, start, end)
#获取子序列,根据字节获取,非字符,参数:
start开始位置的索引(前闭后闭)#汉字占3个字节
end结束位置的的索引(前闭后闭)
setrange(name, offset, value)
#修改字符串内容,从指定索引向后修改,新值比原值长则向后添加,参数:
0ffset开始修改字符串的索引,汉字占3个字节
value指要设置的指
setbit(name, offset, value)
#对key对应的值的二进制(010101001)进行操作,参数:
offset开始位的索引,需要将值转成二进制(1字节等于8位二进制)索引
value值只能是0或1
getbit(name, offset)
# 获取key对应值开始索引的二进制的值0或1
bitcount(key, start=None, end=None)
#获取key对应值的二进制的值中的1的个数,参数:
strat二进制起始位置
end二进制结束位置
bitop(operation, dest, *keys)
#获取多个值,并将值做位运算,将最后的值保存至新的key对应的值,参数:
operation可以是AND(并)、OR(或)、NOT(非)、XOR(异或)
dest新的key名
*keys要查找的key
如:
conn.bitop('AND','name_1','name1','name2','name3')
#获取key,'name1','name2','name3'对应的值,做位运算(并集),然后将结果保存到name_1对应的值中
strlen(name)
#返回key对应值的字节长度(汉字三个字节)
incr(self, name, amount=1)#incrby(self, name, amount=1)*
#自增key对应的值,当key不存在时,则创建key对应值是amount的值,否则则自增,参数:
amount自增数,必须是整数
incrbyfloat(self, name, amount=1.0)
#自增key对应的值,key不存在时,则创建key=amount,否则自增,参数:
amount自增数,必须是浮点型
decr(self, name, amount=1)*
#自减key对应的值,key不存在时,则创建key=amount,否则则自减,参数:
amount自减数,必须是整数
append(key, value)*
#在key对应的值后面追加内容,参数:
value要追加的字符串
图1
Hash(哈希)操作
#Hash在内存中的存储格式,value值必须是字符串类型,看图1
#加*表示重点
hset(name, key, value)*
#name对应的hash中设置一个键值对,不存在创建,存在则修改,参数:
name指redis存储hash的name
key指name对应的hash的key
value指name对应的hash的value
hmset(name, mapping)*
#在name对应的hash中批量设置键值对,参数:
mapping是字典,比如{'k1':'v1','k2','v2'}
hget(name,key)*
#在name对应的hash中获取根据key获取value值
hmget(name, keys, *args)*
#在name对应的hash中获取多个key对应的值。参数:
keys要获取key的集合,如['k1','k2','k3']
*args要获取的key,如k1,k2,k3
实例:
hmget('name',['k1','k2','k3'])
hmget('name',k1,k2,k3)
hgetall(name)
#获取name对应的hash的所有键值
hlen(name)
#获取name对应的hash的键值对的个数
hkeys(name)
#获取name对应的hash的所有的key的值
hvals(name)
#获取name对应的hash的所有的value的值
hexists(name, key)
#检查name对应的hash是否存在key
hdel(name,*keys)
#将name对应的hash指定的key的键值对删除
hincrby(name, key, amount=1)*
#自增name对应的hash中指定的key的值,不存在则创建key=amount,参数:
amount自增数,必须是整数
hincrbyfloat(name, key, amount=1.0)
#自增name对应的hash中指定key的值,不存在则创建key=amount,参数:
amount自增数,必须是浮点数
hscan(name, cursor=0, match=None, count=None)
#增量式迭代获取,对于数据大的非常有用,hscan可以实现分片式获取数据,并非一次性将数据全部获取,导致内存被撑爆,参数:
cursor游标,基于游标分批获取数据
match匹配指定key,默认None,表示所有的key
count每次分片最少获取个数,默认None表示采用redis默认分片个数
hscan_iter(name, match=None, count=None)
#利用yield封装hscan创建生成器,实现分批去redis中获取数据,参数:
match匹配指定key,默认Nnoe,表示所有的key
count每次分片最少获取个数,默认None表示采用redis的默认分片个数
实例:for item in r.hscan_iter('xx'):
print item
# 区分hgetall和hscan_iter
List(列表)操作
#List在内存中按照一个name对应一个List来存储,看图1
#加*表示重点
lpush(name,values)*
#在name对应的list中添加元素,每个新的元素都添加到列表的最左边,如:
r.lpush('oo', 11,22,33)
结果为: 33,22,11
# 扩展:
rpush(name, values) 表示从右向左操作
lpushx(name,value)
#在name对应的list中添加元素,只有name存在时,值添加到list最左边
扩展:rpushx(name, value) 表示从右向左操作
llen(name)*
#name对应的list元素的个数
linsert(name, where, refvalue, value))
#在name对应的list的某一个值前面或后面插入一个值,参数:
where可以式BEFORE或AFTER(小写也可以)
refvalue标杆值,在它前后插入数据,如果存在多个标杆值,以找到的第一个为准
value要插入的值
r.lset(name, index, value)
#对name对应的list的某一个索引位置重新赋值,参数:
index指需要重新赋值的索引位置
value要设置的值
r.lrem(name, value, num)
#在name对应的list中删除指定的值,参数:
value要删除的值
num:
num=0表示删除该list中所有指定值
num=2表示从前到后删除两个
num=-2表示从后到前删除两个
lpop(name)*
#在name对应的list左侧获取第一个元素并在list中移除,返回值则是该元素
扩展:rpop(name) 表示从右向左操作
lindex(name, index)
#在name对应的list中根据索引获取list元素
lrange(name, start, end)*
#在name对应的list分片获取数据,参数:
start开始的索引位置
end结束的索引位置
ltrim(name, start, end)
#在name对应的list中移除没有在start-end索引之间的值,参数:
start开始的索引位置
end结束的索引位置
rpoplpush(src, dst)
#从一个列表取出最右边的元素,提示添加到另一个list的最左边,参数:
src要获取数据的list的name
dst要添加数据的list的name
blpop(keys, timeout)*
#将多个list排列,按照从左到右去pop对应list的元素,参数:
keys是个集合,要pop元素的集合
timeout超时时间,当元素所有list的元素获取玩之后,阻塞等待list内数据局的时间秒,0表示医院阻塞,
扩展:r.brpop(keys, timeout),从右向左获取数据,应用场景:爬虫实现简单分布式:多个url放到列表里,往里不停放URL,程序循环取值,但是只能一台机器运行取值,可以把url放到redis中,多台机器从redis中取值,爬取数据,实现简单分布式
brpoplpush(src, dst, timeout=0)
#从一个列表的右侧移除一个元素,并将其添加到另一个list的左侧,参数:
src取出并要移除元素的list的name
dst要插入元素的list的name
timeout当src对应的list中没有数据时,阻塞等待其有数据的超时时间秒,0表示医院阻塞
自定义增量迭代
# 由于redis类库中没有提供对列表元素的增量迭代,如果想要循环name对应的列表的所有元素,那么就需要:
# 1、获取name对应的所有列表
# 2、循环列表
# 但是,如果列表非常大,那么就有可能在第一步时就将程序的内容撑爆,所有有必要自定义一个增量迭代的功能:
import redis
conn=redis.Redis(host='127.0.0.1',port=6379)
# conn.lpush('test',*[1,2,3,4,45,5,6,7,7,8,43,5,6,768,89,9,65,4,23,54,6757,8,68])
# conn.flushall()
def scan_list(name,count=2):
index=0
while True:
data_list=conn.lrange(name,index,count+index-1)
if not data_list:
return
index+=count
for item in data_list:
yield item
print(conn.lrange('test',0,100))
for item in scan_list('test',5):
print('---')
print(item)
Set(集合)操作
其他操作
delete(*names)
#删除redis中任意数据类型
exists(name)
#检查redis的name是否存在
keys(pattern='*')
#根据模型获取redis的name,其他参数:
KEYS * 匹配数据库中所有 key 。
KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
KEYS h*llo 匹配 hllo 和 heeeeello 等。
KEYS h[ae]llo 匹配 hello 和 hallo ,不匹配 hillo
expire(name ,time)
#为某个redis的某个name设置超时时间
rename(src, dst)
#对redis的name重命名
move(name, db)
#将redis的某个值移动到指定的db下
randomkey()
#随机获取一个redis的name,不删除
type(name)
#获取nmae对应值的类型
scan(cursor=0, match=None, count=None)
scan_iter(match=None, count=None)
#同字符串操作,用于增量迭代获取key
管道
如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。#redis默认在执行每次请求都会创建(连接申请连接池)和断开(归还连接池)一次性操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作(要么全部成功,要么全部失败)。
#test.py
import redis
pool = redis.ConnectionPool(host='10.211.55.4', port=6379)
r = redis.Redis(connection_pool=pool)
# pipe = r.pipeline(transaction=False)
pipe = r.pipeline(transaction=True)
pipe.multi()
pipe.set('name', 'alex')
pipe.set('role', 'sb')
pipe.execute()
Django使用Redis
#方式一,通用方式
#utils
edis_pool.py
import redis
#POOL连接池,max_connections=100指最大连接数是100
POOL = redis.ConnectionPool(host='127.0.0.1',port=6379,max_connections=100)
#app01views.py
import redis
from utils.redis_pool import POOL
from django.shortcuts import render, HttpResponse
def index(request):
conn = redis.Redis(connection_pool=POOL)
conn.set('hobby','sleep')
return HttpResponse('设置成功')
def order(request):
conn = redis.Redis(connection_pool=POOL)
ret = conn.get('hobby')
print(ret)
return HttpResponse('获取成功')
#方式二,安装django-redis模块
pip install django-redis
#settings.py配置
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
conn = get_redis_connection('default')
print(conn.hgetall('xxx'))
接口缓存
#luffyapiappshomeviews.py,BannerView类内
def banner_list(self,request,*args,**kwargs):
banner_list = cache.get('banner_list')
if not banner_list:
#缓存没有去数据拿
response = super().list(request,*args,**kwargs)
#加到缓存
cache.set('banner_list',response.data,60*60*24)#banner_list一天过期
return Response(data=banner_list)