Redis使用
Redis
1.Redis介绍安装
redis:
缓存数据库--大部分时间做缓存 但是不仅仅能做缓存
非关系型数据库--区别于mysql关系型数据库
# 存储方式:
k:v形式存储 没有表的概念
# 安装:
-mac 源码编译安装
-linux 源码编译安装
-win 微软自己,基于源码,改动,编译成安装包
# 最新5.x版本 https://github.com/tporadowski/redis/releases/
# 最新3.x版本 https://github.com/microsoftarchive/redis/releases 一路下一步,安装完释放出两个命令,会把redis自动加入到服务中
redis-server # mysqld 服务端的启动命令
redis-cli # mysql 客户端的启动命令
# 安装目录
redis-server
redis-cli
redis.windows-service.conf 配置文件
-bind 127.0.0.1 # 服务,跑在的地址
-port 6379 #监听的端口
# 启动redis
1.方式一:
在服务中 点击启动 后台启动
2.方式二:
使用命令
redis-server 指定配置文件 如果不指定 会默认
# 客户端连接redis
1.方式一:
redis-cli #默认连接本地的6379端口
2.方式二:
redis-cli -h 地址 -p 端口
3.使用图形化客户端操作
-Redis Desktop Manager :开源的 原来免费 后来收费 推荐用
-Qt5 qt是个平台 专门用来做图形化界面的
-可以使用c++写
-可以使用pycharm写 pyqt5 使用python写图形化界面
-resp-2022.1.0.0.exe 一路下一步 安装完启动起来
-Redis Client 小众
图形化界面 连接redis 输入地址和端口 点击连接即可
#redis默认有16个库 默认连进去就是第0个
2.Redis普通连接池和连接池
#python 相当于客户端 操作redis
安装模块 pip install redis
补充:
django中操作mysql 没有连接池 一个请求就是一个mysql连接
使用django连接池参考:https://blog.51cto.com/liangdongchang/5140039:
2.1普通连接
1.导入模块的Redis类
from redis import Redis
2.实例化的到一个对象
conn = Redis(host=127.0.0.1,post=6397)
3.使用conn 操作redis
#获取值
print(conn.get('name')) #b'lzy'
#设置值
conn.set('age',19)
conn.close()
2.2连接池连接
import redis
POOL = redis.ConnectionPool(max_connections=10,host='127.0.0.1',port=6379)
--------------------------------------------------
from threading import Thread
from pool import POOL
def task():
#做成模块后导入 无论导入多少次 导入的都是哪一个POOL对象
conn =redis.Redis(connection_pool=POOL)
print(conn.get('name'))
for i in range(10):
t = Thread(target=task)
t.start()
单例模式:
设计模式 23种设计模式:
模块天然就是单例的,因为模块只会被加载一次,加载之后,其他脚本里如果使用import 二次加载这个模块时,会从sys.modules里找到已经加载好的模块,模块里的对象天然就是单例的,即使是在多线程环境下也是如此
3.Redis之字符串类型
redis 数据放在内存中 如果断电 数据丢失 -- 就需要有持久化的方案
3.1 5种数据类型
value类型
字符串 :用的最多 做缓存 做计数器
列表:简单的消息队列
hash:缓存
集合:去重
有序集合:排行榜
3.2 字符串类型的使用
'''
1 set(name, value, ex=None, px=None, nx=False, xx=False)
2 setnx(name, value)
3 setex(name, value, time)
4 psetex(name, time_ms, value)
5 mset(*args, **kwargs)
6 get(name)
7 mget(keys, *args)
8 getset(name, value)
9 getrange(key, start, end)
10 setrange(name, offset, value)
11 setbit(name, offset, value)
12 getbit(name, offset)
13 bitcount(key, start=None, end=None)
14 bitop(operation, dest, *keys)
15 strlen(name)
16 incr(self, name, amount=1)
# incrby
17 incrbyfloat(self, name, amount=1.0)
18 decr(self, name, amount=1)
19 append(key, value)
'''
import redis
from redis import Redis
conn = Redis(host='127.0.0.1',port=6379)
# 1 set(name, value, ex=None, px=None, nx=False, xx=False)
# conn.set('hobby','basketball',ex=5)
#ex:过期时间 单位秒
# conn.set('hobby','basketball',px=5000)
#px:过期时间 单位毫秒
# conn.set('xxx','lll',nx=True) #redis --实现分布式锁 底层基于nx实现的
#nx:如果设置为true 则只有name不存在的时候 才修改值(直接新增) 值存在就不能修改
# conn.set('UUU','xxx',xx=True)
#xx:如果设置为true 则只有name存在时 set才操作 值才能改 之不存在不会设置新值
# 2 setnx(name, value)
# 等同于:conn.set('xxx','lll',nx=True)
#3 setex(name, time, value)
#等同于:conn.set('hobby',5,'basketball')
#4 psetex(name, time_ms, value)
#等同于:conn.set('hobby',5000,'basketball')
#5 mset(*args, **kwargs)
# conn.mset({'wife':'lyf','hobby':'basketball'})
#批量修改值 传字典
#6 get(name)
# print(str(conn.get('wife'),encoding='utf-8'))
#获取值
#7 mget(keys, *args)
# print(conn.mget('wife', 'hobby'))
#获取多个数据值
# 8 getset(name, value)
#conn.getset('wife','fbb')
#把原来的取出 再修改成新的值
#9 getrange(key, start, end)
# res = str(conn.getrange('wife',0,1),encoding='utf-8')
# print(res)
#获取字节长度 不是字符长度
# 10 setrange(name, offset, value)
# conn.setrange('hobby',1,'xx')
#从第2个字符开始 连着覆盖xx
# ---- 比特位---操作
# 11 setbit(name, offset, value)
# 12 getbit(name, offset)
# 13 bitcount(key, start=None, end=None)
# ---- 比特位---操作
# 14 bitop(operation, dest, *keys) 获取多个值,并将值做位运算,将最后的结果保存至新的name对应的值
# 15 strlen(name)
# print(conn.strlen('hobby'))
#统计字符长度
# 16 incr(self, name, amount=1)
# conn.incr('age')
#自增1 不会出现并发安全的问题 单线程架构 并发量高
# 17 incrbyfloat(self, name, amount=1.0)
# conn.incrbyfloat('age',1.2)
#自增小数点
# 18 decr(self, name, amount=1)
# conn.decr('age',-1)
#减1
# 19 append(key, value)
conn.append('hobby','++++hhh')
#在尾部追加
conn.close()
4.Redis之字符串类型
'''
1 lpush(name, values)
2 rpush(name, values) 表示从右向左操作
3 lpushx(name, value)
4 rpushx(name, value) 表示从右向左操作
5 llen(name)
6 linsert(name, where, refvalue, value))
7 r.lset(name, index, value)
8 r.lrem(name, value, num)
9 lpop(name)
10 rpop(name) 表示从右向左操作
11 lindex(name, index)
12 lrange(name, start, end)
13 ltrim(name, start, end)
14 rpoplpush(src, dst)
15 blpop(keys, timeout)
16 r.brpop(keys, timeout),从右向左获取数据
17 brpoplpush(src, dst, timeout=0)
'''
from redis import Redis
conn = Redis(host='127.0.0.1',port=6379)
# '''
# 1 lpush(name, values)
# conn.lpush('name','joyce')
# 从左侧插入
# conn.lpush('name','gjx','gxy')
# 从左侧插入多个
# 2 rpush(name, values)
# conn.rpush('name','lzy')
# 表示从右侧插入
# 3 lpushx(name, value)
# conn.lpushx('name','zzh')
# conn.lpushx('hobby','zzh')
#当k存在时 v从左侧添加 k不存在时 v不添加
# 4 rpushx(name, value)
# conn.rpushx('name','ksh')
#当k存在时 v从右侧添加 k不存在时 v不添加
# 5 llen(name)
# print(conn.llen('name'))
#查看v中的 对应的list个数
# 6 linsert(name, where, refvalue, value))
# conn.linsert('name','before','joyce','kks')
#where=before/after refvalue=目标对象 value=值 在哪个目标对象前面或后面加一个值
# 7 lset(name, index, value)
# conn.lset('name',2,'666')
#将索引为2的value改为666
# 8 lrem(name, num , value)
# conn.lrem('name',2,'ksh')
#从ksh左侧开始删除2个
# conn.lrem('name',-2,'ksh')
#从ksh右侧开始删除2个
# conn.lrem('name',0,'ksh')
#全部删除
# 9 lpop(name)
# print(conn.lpop('name'))
#弹出左边第一个list
# 10 rpop(name) 表示从右向左操作
# print(conn.rpop('name'))
#弹出又边第一个list
# 11 lindex(name, index)
# print(str(conn.lindex('name', 1), encoding='utf-8'))
#获取左边数索引为1的list
# 12 lrange(name, start, end)
# print(conn.lrange('name', 0, 2))
# 前闭后闭区间
# 13 ltrim(name, start, end)
# conn.ltrim('name',1,2)
# 前闭后闭区间 删除
# 14 rpoplpush(src, dst)
# conn.rpoplpush(0,1)
# 15 blpop(keys, timeout)
# print(conn.blpop('name',2))
#可以做消息队列使用阻塞式弹出 如果没有 就阻塞
# 16 brpop(keys, timeout)
# conn.brpop('name',2)
# 从右向左获取数据
# 17 brpoplpush(src, dst, timeout=0)
# conn.brpoplpush()
# '''
conn.close()
5.Redis之hash类型
'''
1 hset(name, key, value)
2 hmset(name, mapping)
3 hget(name,key)
4 hmget(name, keys, *args)
5 hgetall(name)
6 hlen(name)
7 hkeys(name)
8 hvals(name)
9 hexists(name, key)
10 hdel(name,*keys)
11 hincrby(name, key, amount=1)
12 hincrbyfloat(name, key, amount=1.0)
13 hscan(name, cursor=0, match=None, count=None)
14 hscan_iter(name, match=None, count=None)
'''
conn = Redis(host='127.0.0.1',port=6379)
# '''
# 1 hset(name, key, value)
# conn.hset('1','name','lzy')
# conn.hset('1',mapping={'name1':'lll','name2':'zzz'})
#添加数据/添加多个数据
# 2 hmset(name, mapping)
#直接用conn.hset('1',mapping={'name1':'lll','name2':'zzz'})
# 3 hget(name,key)
# print(conn.hget('1', 'name'))
#取值
# 4 hmget(name, keys, *args)
# print(conn.hmget('1', 'name', 'name1'))
#获取k值 传多个
# 5 hgetall(name)
# print(conn.hgetall('1'))
#获取所有字典
# 6 hlen(name)
# print(conn.hlen('1'))
#获取name里的字典个数
# 7 hkeys(name)
# print(conn.hkeys('1'))
#获取所有k
# 8 hvals(name)
# print(conn.hvals('1'))
#获取所有值
# 9 hexists(name, key)
# print(conn.hexists('1', 'name8'))
#判断name里有没有这个k 有就返回True 没有就是 false
# 10 hdel(name,*keys)
# print(conn.hdel('1','name1','name2'))
#删除
# 11 hincrby(name, key, amount=1)
# conn.hincrby('1','age')
#自增1 默认是1 可以自己自定义
# 12 hincrbyfloat(name, key, amount=1.0)
# conn.hincrbyfloat('1','name',1.5)
##自增小数 默认是1.0 可以自己自定义
# 13 hscan(name, cursor=0, match=None, count=None)
print(conn.hscan('1',cursor=0,count=2))
# 14 hscan_iter(name, match=None, count=None)
#
# '''
conn.close()
6.Redis管道
redis支持事务是基于管道的
将两条命令都放入管道中 执行的时候统一执行 如果在执行中途断开操作 那两条命令执行都不成功
import redis
conn = redis.Redis()
p=conn.pipeline(transaction=True)
p.multi()
p.decr('zhangsan_je', 100)
# raise Exception('崩了')
p.incr('lisi_je', 100)
p.execute()
conn.close()
7.django中使用redis
方式一:自定义包方案 (所有框架都可以用)
第一步:写一个pool.py
import redis
POOL = redis.ConnectionPool(max_connections=100)
第二步:以后在使用的地方,直接导入使用即可
conn = redis.Redis(connection_pool=POOL)
conn.incr('count')
res = conn.get('count')
方式二:django方案
方案一: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",
}
}
}
-在使用redis的地方:cache.set('count', res+1)
-pickle序列化后,存入的
-方案二:第三方:django-redis模块
from django_redis import get_redis_connection
def test_redis(request):
conn=get_redis_connection()
print(conn.get('count'))
return JsonResponse({'count': '今天这个接口被访问的次数为:%s'}, json_dumps_params={'ensure_ascii': False})