当前位置:Gxlcms > 数据库问题 > redis数据库

redis数据库

时间:2021-07-01 10:21:17 帮助过:10人阅读

Redis-x64-3.2.100(1).msi: redis安装包
redis-desktop-manager-0.9.3.817.exe:redis管理工具

#安装介绍网站
https://www.cnblogs.com/liuqingzheng/p/9831331.html

二.简介

‘‘‘
-mysql,oracle:关系型数据库
-redis,mongodb:菲关系型数据库/nosql
    -redis储存在内存中,redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步
    -mongodb储存在硬盘上

-redis一般用来
    -做缓存
    -session数据
    -游戏排行
    -对速度要求比较高的数据储存
    -做消息队列

-redis是key-value的存储,支持持久化,像py中的字典,有五大数据类型:
    -字符串
    -列表
    -字典
    -集合
    -有序集合
    redis={
        k1:‘123‘,      字符串
        k2:[1,2,3,4],   列表/数组
        k3:{1,2,3,4}     集合
        k4:{name:lqz,age:12}  字典/哈希表
        k5:{(‘lqz‘,18),(‘egon‘,33)}  有序集合
}
#redis支持上述五大数据类型,但是它只支持一层


-比较redis和Memcached
    -redis 支持5大数据类型
    -redis支持持久化
    -单线程,单进程,速度是非常快
    -Memcached不能持久化,只支持字符串
    
-存redis的token
    三种方案:
        -request.user 是字典或者用户id
        -request.user 就是user对象,在redis中存的value值是pickle之后的字符串
        -request.user 就是user对象,在redis中存的value值是json格式数据

三.python操作redis

1.安装redis模块
2.简单操作
‘‘‘
import redis
#拿到redis的连接
conn=redis.Redis(host=‘127.0.0.1‘,port=6379,password=12345)
#插入字符串数据
conn.set(‘age‘,‘18‘)
#获取数据
name=conn.get(‘name‘)
#redis中存的都是byte格式
print(name)
‘‘‘

1.redis连接池

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

#必须是单例
 -实现单例的方式
    ①当其以模块导入实现单例,这是python中一种天然的单例方式
    ②__new__实现单例
    ③装饰器来控制实现单例
‘‘‘
#模块导入实现单例
-新建一个模块
import redis                    POOL=redis.ConnectionPool(host=‘127.0.0.1‘,port=6379,password=12345,max_connections=1000)

-使用连接池
#导入池子
from conn_pool import POOL
# 每次执行这句话,从池子中取一个链接
conn=redis.Redis(connection_pool=POOL)
‘‘‘

2.redis之字符串操作

#重点掌握
get set mget mset incr decr append

#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操作才执行,值存在才能修改,值不存在,不会设置新值

2.setnx(name, value) #设置值,只有name不存在时,执行设置操作(添加),如果存在,不会修改

3.setex(name, time, value) # 设置值
# 参数:
    # time,过期时间(数字秒 或 timedelta对象)

4.psetex(name, time_ms, value) # 设置值
# 参数:
    # time_ms,过期时间(数字毫秒 或 timedelta对象

5.mset(*args, **kwargs) #批量设置值
如:
    mset(k1=v1, k2=v2)
    或
    mset({k1: v1, k2: v2})

6.get(name) #获取值

7.mget(names, *args) #批量获取
如:
    mget(k1, k2)
    或
    mget([k3, k4])

8.getset(name, value) #设置新值并获取原来的值

9.getrange(name, start, end)
# 获取子序列(根据字节获取,非字符)
# 参数:
    # name,Redis 的 name
    # start,起始位置(字节)
    # end,结束位置(字节)
# 如: "henry" ,0-2表示 "hen" 前闭后闭,全闭区间

10.setrange(name, offset, value)
# 修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)
# 参数:
    # offset,字符串的索引,字节(一个汉字三个字节)
    # value,要设置的值

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)

13.bitcount(name, start=None, end=None)
# 获取name对应的值的二进制表示中 1 的个数
# 参数:
    # name,Redis的name
    # start,位起始位置
    # end,位结束位置

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个字节)

16.incr(self, name, amount=1) #amount默认为1 用于浏览量等
# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。
 
# 参数:
    # name,Redis的name
    # amount,自增数(必须是整数)
 
# 注:同incrby

17.incrbyfloat(self, name, amount=1.0)
# 自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增。
 
# 参数:
    # name,Redis的name
    # amount,自增数(浮点型)

18.decr(self, name, amount=1) #amount默认为1
# 自减 name对应的值,当name不存在时,则创建name=amount,否则,则自减。
 
# 参数:
    # name,Redis的name
    # amount,自减数(整数)

19.append(name, value)
# 在redis name对应的值后面追加内容
 
# 参数:
    name, redis的name
    value, 要追加的字符串

20.自定义增量迭代
# 由于redis类库中没有提供对列表元素的增量迭代,如果想要循环name对应的列表的所有元素,那么就需要:
    # 1、获取name对应的所有列表
    # 2、循环列表
# 但是,如果列表非常大,那么就有可能在第一步时就将程序的内容撑爆,所有有必要自定义一个增量迭代的功能:
def scan_list(name,count=1000) #count为默认一次取出数据的个数
    cursor=0
    while True:
        if cursor >= re.llen(name):
            break
        ret = re.lrange(name,cursor,count+cursor-1)
        cursor+=count
        for i in ret:
            yield i
#使用
for i in scan_list(l1,100):#一次取100条数据
    print(i)

3.redis之列表操作

#List操作,redis中的List在在内存中按照一个name对应一个List来存储。

1.r.lpush(name,values)
# 在name对应的list中添加元素,每个新的元素都添加到列表的最左边
 
# 如:
    # r.lpush(‘l1‘, 1,2,3)
    # 保存顺序为: 3,2,1
    
    # r.lpush(‘l2‘,*[1,2,3])
    #保持顺序为: 3,2,1
 
# 扩展:
    # rpush(name, values) 表示从右向左操作
    
2.r.lpushx(name,value)
# 在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边,如果name不存在不进行任何操作
 
# 更多:
    # rpushx(name, value) 表示从右向左操作
    
3.r.llen(name)
# name对应的list元素的个数

4.r.linsert(name, where, refvalue, value))
# 在name对应的列表的某一个值前或后插入一个新值
 
# 参数:
    # name,redis的name
    # where,BEFORE或AFTER(小写也可以)
    # refvalue,标杆值,即:在它前后插入数据(如果存在多个标杆值,以找到的第一个为准)
    # value,要插入的数据
    # r.linsert(‘l1‘,‘BEFORE‘,‘3‘,‘p‘) 在l1列表中3的前面加一个p

5.r.lset(name, index, value)
# 对name对应的list中的某一个索引位置重新赋值
 
# 参数:
    # name,redis的name
    # index,list的索引位置
    # value,要设置的值
    
6.r.lrem(name, num, value)
# 在name对应的list中删除指定的值
 
# 参数:
    # name,redis的name
    # num,  num=0,删除列表中所有的指定值;
           # num=2,从前到后,删除2个;
           # num=-2,从后向前,删除2个
    # value,要删除的值

7.r.lpop(name)
# 在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素
 
# 更多:
    # rpop(name) 表示从右向左操作

8.r.lindex(name, index)
#在name对应的列表中根据索引获取列表元素

9.r.lrange(name, start, end)
# 在name对应的列表分片获取数据
# 参数:
    # name,redis的name
    # start,索引的起始位置
    # end,索引结束位置  print(r.lrange(‘aa‘,0,r.llen(‘aa‘)))  
    #前闭后闭区间

10.r.ltrim(name, start, end)
# 在name对应的列表中移除没有在start-end索引之间的值
# 参数:
    # name,redis的name
    # start,索引的起始位置
    # end,索引结束位置(大于列表长度,则代表不移除任何)
    #前闭后闭区间
    
11.r.rpoplpush(src, dst)
# 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
# 参数:
    # src,要取数据的列表的name
    # dst,要添加数据的列表的name
    
12.blpop(name, timeout)
# 从左到右去pop对应列表的元素
 
# 参数:
    # name,redis的name
    # timeout,超时时间,当所有列表的元素获取完之后,将会阻塞,然后等待列表内有数据的时间(秒), 0 表示永远阻塞,默认是0
 
# 更多:
    # r.brpop(keys, timeout),从右向左获取数据
爬虫实现简单分布式:多个url放到列表里,往里不停放URL,程序循环取值,但是只能一台机器运行取值,可以把url放到redis中,多台机器从redis中取值,爬取数据,实现简单分布式,一个负责爬连接,一个负责取数据存数据库

13.brpoplpush(src, dst, timeout=0)
# 从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧
 
# 参数:
    # src,取出并要移除元素的列表对应的name
    # dst,要插入元素的列表对应的name
    # timeout,当src对应的列表中没有数据时,阻塞等待其有数据的超时时间(秒),0 表示永远阻塞

4.redis之字典(Hash)操作

#Hash操作,redis中Hash在内存中的存储格式
name -> k1->v1
        k2->v2
        k3->v3

1.hset(name, key, value)
# name对应的hash中设置一个键值对(不存在,则创建;否则,修改)
 
# 参数:
    # name,redis的name
    # key,name对应的hash中的key
    # value,name对应的hash中的value
#r.hset(‘n1‘,‘name‘,‘henry‘)
# 注:
    # hsetnx(name, key, value),当name对应的hash中不存在当前key时则创建(相当于添加),存在不进行任何操作

2.hmset(name, mapping)
# 在name对应的hash中批量设置键值对
 
# 参数:
    # name,redis的name
    # mapping,字典,如:{‘k1‘:‘v1‘, ‘k2‘: ‘v2‘}
 
# 如:
    # r.hmset(‘xx‘, {‘k1‘:‘v1‘, ‘k2‘: ‘v2‘})

3.hget(name,key)
# 在name对应的hash中根据key获取value

4.hmget(name, keys)
# 在name对应的hash中获取多个key的值
 
# 参数:
    # name,reids对应的name
    # keys,要获取key集合,如:[‘k1‘, ‘k2‘, ‘k3‘] 
       # 第一个参数为name,后面也可以直接写‘k1‘,‘k2‘,‘k3‘
     
# 如:
    # r.mget(‘xx‘, [‘k1‘, ‘k2‘])
    #
    # print(r.hmget(‘xx‘, ‘k1‘, ‘k2‘))
    
5.hgetall(name)
# 把字典中的所有键-值对取出来,如果存储的数据量过大,尽量慎用
# 获取name对应hash的所有键值
print(re.hgetall(xxx).get(bname))

6.hlen(name)
# 获取name对应的hash中键值对的个数

7.hkeys(name)
# 获取name对应的hash中所有的key的值

8.hvals(name)
# 获取name对应的hash中所有的value的值

9.hexists(name, key)
# 检查name对应的hash是否存在当前传入的key

10.hdel(name,*keys)
# 将name对应的hash中指定key的键值对删除,返回值为你删除了几个键值对
print(re.hdel(xxx,sex,name))

11.hincrby(name, key, amount=1)
# 自增name对应的hash中的指定key的值,不存在则创建key=amount
# 参数:
    # name,redis中的name
    # key, hash对应的key
    # amount,自增数(整数)
re.hincrby(n1,age,amount=1) #n1中的age字段的值自增1,不存在则创建age字段值为1
    
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时,表示数据已经通过分片获取完毕

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

5.其它操作

1.delete(*names)
# 根据删除redis中的任意数据类型

2.exists(name)
# 检测redis的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 

4.expire(name ,time)
# 为某个redis的某个name设置超时时间

5.rename(src, dst)
# 对redis的name重命名为

6.move(name, db))
# 将redis的某个值移动到指定的db下

7.randomkey()
# 随机获取一个redis的name(不删除)

8.type(name)
# 获取name对应值的类型

9.scan(cursor=0, match=None, count=None)
scan_iter(match=None, count=None)
# 用于增量迭代获取key

6.管道

redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。
#注意:关系型数据库存在事务,菲关系型数据库不存在事务,但是我们可以通过管道模拟出事务

import redis
 
pool = redis.ConnectionPool(host=10.211.55.4, port=6379)
r = redis.Redis(connection_pool=pool)

pipe = r.pipeline(transaction=True)
pipe.multi()
pipe.set(name, alex)
pipe.set(role, sb)
 
pipe.execute()

7.Django中使用redis

方式一

建立redis_pool.py
import redis
POOL = redis.ConnectionPool(host=127.0.0.1, port=6379,password=1234,max_connections=1000)

视图函数中使用:
import redis
from django.shortcuts import render,HttpResponse
from utils.redis_pool import POOL

def index(request):
    conn = redis.Redis(connection_pool=POOL)
    conn.hset(kkk,age,18)

    return HttpResponse(设置成功)
def order(request):
    conn = redis.Redis(connection_pool=POOL)
    conn.hget(kkk,age)

    return HttpResponse(获取成功)

方式二

安装django-redis模块
pip3 install django-redis

setting里配置:
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",
        }
    },
    "aa": {
        "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",
        }
    },
}

视图函数:
from django_redis import get_redis_connection
conn = get_redis_connection(default)  #可以选择自己要操作的服务器,默认default
print(conn.hgetall(xxx))

 

redis数据库

标签:djang   response   结果   周期性   简介   rgs   情况下   ash   持久化   

人气教程排行