Redis


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)	
作者:linqiaobao
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/linqiaobao/p/13680786.html