Redis
一、Redis介绍
Redis是一种非关系型数据库,基于内存、key-value存储的数据库,性能非常高。
由于Redis是内存存储,数据都在内存中,所以重启就没了(没有做持久化)
性能很高,io多路复用,epoll模型,但官方不支持windows
Redis五大数据类型:
string(字符串)、list(列表)、set(集合)、hash(哈希类型)、sorted sets(有序集合)
关系型数据库:MySQL,Oracle,DB2,SQL Server 等
非关系型数据库:Redis,MongoDB 等
安装
Redis是使用c语言写的,c不能跨平台,还好有第三方已经在windows上编译好了,拿到就是可执行文件
# 下载地址(非官方)
https://github.com/tporadowski/redis/releases/
# 下载安装直接一直无脑下一步就行
# 下载之后会自动做成windows服务,自动启动服务
# 我们也可以使用命令手动启动
redis-server.exe
redis-server.exe 配置文件路径
# 客户端连接
redis-cli
redis-cli -h 127.0.0.1 -p 6379
二、Redis连接和连接池连接
# redis模块安装
pip install redis
##############################################################
# 普通连接
import redis
# 拿到一个连接,通过连接操作数据
conn = redis.Redis(host='localhost', port=6379)
conn.set('name', 'poco')
conn.close()
##############################################################
# 连接池连接
import redis
# 创建池,池的大小是10,最多放10个连接
POOL = redis.ConnectionPool(max_connections=10)
# 从池中获取连接
conn = redis.Redis(connection_pool=POOL)
conn.set('age', 19)
conn.close()
'''
如果POOL = redis...这行创建池的代码被反复执行(放在线程里写),就会创建N多个池,为了避免这种情况,需要做成单例()
'''
三、Redis操作
1、字符串操作
import redis
conn = redis.Redis()
'''
ex,过期时间(秒)
px,过期时间(毫秒)
nx,如果设置为True,则只有name不存在时,当前set操作才执行,值存在,就修改不了,执行没效果
xx,如果设置为True,则只有name存在时,当前set操作才执行,值存在才能修改,值不存在,不会设置新值
'''
conn.set('hobby', '篮球', ex=5) # 五秒后数据就没了
conn.set('age', 18, nx=True) # 如果有age存在, 操作不执行
# 设置值,只有name不存在时,执行设置操作(添加),如果存在,不会修改
conn.setnx('name', 'poco') # 和nx效果一样
# 批量存入值
conn.mset({'name1':'lyf','name2':'ycy'})
# get获取值,mget批量获取值
print(conn.get('name1'))
print(conn.mget('name1', 'name2'))
# get和set结合,获取值并修改值
print(conn.getset('name1','glnz'))
# 取出0到2索引对应的字节
print(conn.getrange('name1', 0, 2))
# 修改name1索引3之后的值为EEEEE
conn.setrange('name1', 3, 'EEEEE')
# 获取name1的字节数
print(conn.strlen('name1'))
# 执行一次自增+1
conn.incr('age')
# 自减
conn.decr('age')
# 浮点型自增,自增1.5
conn.incrbyfloat('age', 1.5)
conn.close()
2、哈希操作
import redis
conn = redis.Redis()
# 哈希的set,存值
conn.hset('hash1', 'name', 'poco')
conn.hset('hash1', 'age', '18')
# 哈希的get,取值
print(conn.hget('hash1','age'))
# 批量存值
conn.hmset('hash1', mapping={'name': 'poco', 'age': 22})
# 批量取值
print(conn.hmget('hash1', ['name', 'age']))
# 获取所有值(生产环境中慎用)
print(conn.hgetall('hash1'))
# 获取所有key值
print(conn.hkeys('hash1'))
# 获取所有value值
print(conn.hvals('hash1'))
# 检查hash1里age这个key值是否存在
print(conn.hexists('hash1', 'age'))
# 分批获取
for item in conn.hscan_iter('hash1'):
print(item)
conn.close()
3、列表操作
import redis
conn = redis.Redis()
# 列表的存值,班级是name,后面的是列表的元素
conn.lpush('班级', '1班', '2班', '3班')
# name存在时才可以添加值
conn.lpushx('班级', '4班')
# 获取name对应的list元素的个数
print(conn.llen('班级'))
# 在name对应的列表的某个元素的前或者后插入一个新值(before表示前,after表示后)
conn.linsert('班级', 'after', '3班', '3.5班')
# 为name对应的list中的某一个索引位置重新赋值
conn.lset('班级', 1, '加强班')
# 在name对应的list中删除指定的值
conn.lrem('班级', 0, '加强班') # 移除所有的'加强班'
conn.lrem('班级', 1, '加强班') # 从左往右移除一个'加强班'
conn.lrem('班级', -2, '加强班') # 从右往左移除两个'加强班'
# 删除name对应的list中最左侧的元素,并且返回这个值
res = conn.lpop('班级')
res2 = conn.rpop('班级') # 删除最右侧
# 获取name列表中的某个索引对应的元素
print(conn.lindex('班级', 1))
# 获取name列表中0到3索引的元素(包括0和3)
print(conn.lrange('班级', 0, 3))
# 只保留索引1到3的元素(包括1和3)
conn.ltrim('班级', 1, 3)
# 取出name对应列表的第一个元素,如果没有值则阻塞,一直到有值为止
res = conn.blpop('班级')
print(res)
print(conn.blpop('班级', 3)) # 可以设置timeout来指定阻塞的时间
conn.close()
Redis通用操作
import redis
conn = redis.Redis()
# 直接删除redis的任意数据类型
conn.delete('info')
# 判断redis的name是否存在,返回1和0
print(conn.exists('name2'))
# 获取所有key值,可以过滤
print(conn.keys('*')) # 获取所有key值
print(conn.keys('n*')) # 获取n开头的所有k值
print(conn.keys(pattern='nam?')) # ?为任意的一个字符
# 为info设置一个过期时间
conn.expire('info', 5) # 5秒后过期
# 重命名
conn.rename('info', 'INFO') # 把info重新命名为INFO
# 将redis的某个类型移动到指定的db下
conn.move('INFO', 5)
# 随机弹出一个name
print(conn.randomkey())
# 查看某个key的类型
print(conn.type('name'))
conn.close()
四、Redis管道
Redis是非关系型数据库,不支持事务,所以我们通过管道来模拟事务
我们模拟两个账号转账,只有两条命令同时执行,才会成功,中间但凡有一条命令没能执行,则管道的命令全都执行失败
管道:将所有的命令放在管道里统一执行
import redis
conn = redis.Redis()
# 创建管道
pipe = conn.pipeline(transaction=True)
# 开启事务
pipe.multi()
# 向管道中放入一条命令
pipe.decrby('poco', '50') # poco减50
# 又向管道放入一条命令
pipe.incrby('hy', '50') # hy加50
pipe.execute() # 让管道中的命令执行
五、Django使用Redis
通用方案
'''
建一个pool.py,写如下代码
'''
import redis
POOL = redis.ConnectionPool(max_connections=1000) # 连接池大小为1000
'''
然后在使用的位置将pool里的POOL导入过来使用
'''
from .pool import POOL
import redis
def test(request):
conn = redis.Redis(connection_pool=POOL)
res = conn.get('name')
print(res)
return HttpResponse('ok')
Django方案
# 安装django-redis模块
pip install django-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",
}
}
}
# 然后在使用的位置使用
from django_redis import get_redis_connection
def test(request):
conn = get_redis_connection() #从连接池中拿一个连接
res=conn.get('name') # 拿到redis的name
print(res)
return HttpResponse('ok')
# 一旦使用了它,后续的djagno缓存,都缓存到redis中
cache.set('name','xxx')
'''django的缓存很高级,可以缓存python中所有的数据类型,包括对象---》把对象通过pickle序列化成二进制,存到redis的字符串中'''

浙公网安备 33010602011771号