Redis介绍与安装
redis:缓存数据库 非关系型数据库
什么是 NoSQL ?
NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,泛指非关系型的数据库。
Redis的应用场景
- 缓存
- 任务队列
- 网站访问统计
- 应用排行榜
- 数据过期处理
- 分布式集群架构中的 session 分离
优点:
- 易扩展
- 灵活的数据模型
- 大数据量,高性能
- 高可用
下载 官网下载即可 https://redis.io/download/
已mac为例
下载好后解压 然后把解压好的包 放到/usr/local/文件夹下
# 进入到redis目录
cd /usr/local/redis-7.0.9
# 编译测试
sudo make test
# 安装
sudo make install
# 启动服务端
redis-server 指定配置文件 如果不指定,会默认
# 客户端连接redis
1 方式一
redis-cli #默认连接本地的6379端口
2 方式二:
redis-cli -h 地址 -p 端口
redis图形化操作软件
Redis Desktop Manager
直接下载安装即可
Redis普通连接和连接池
# python 相当于客户端,操作redis
# 安装模块:pip install redis
#补充: django 中操作mysql,没有连接池的,一个请求就是一个mysql连接
-可能会有问题,并发数过高,导致mysql连接数过高,影响mysql性能
-使用django连接池:htt .51cto.com/liangdongchang/5140039
python普通链接Redis
# 安装redis 模块:pip install redis
# 1 导入模块的Redis类
from redis import Redis
conn = Redis()
# 可以点击Redis查看可配置的参数 链接地址 端口号 链接的库等
# host="localhost",port=6379,db=0,
# 添加值 KV键值对形式
conn.set('name','moon')
# 获取值get KEY得到value
print(conn.get('name'))
连接池链接
###pool.py
import redis
POOL = redis.ConnectionPool(max_connections=10, host='127.0.0.1', port=6379) # 创建一个大小为10的redis连接池
### 测试代码
import redis
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(1000):
t = Thread(target=task) # 每次都是一个新的连接,会导致 的连接数过多
t.start()
# 单例模式:设计模式 23 中设计模式
-全局只有一个 这个对象
p1=Person() # p1 对象
p2=Person() # p2 新对象
-单例模式的6种方式
-1 模块导入方式
-2 。。。
Redis value数据类型
# redis 是key-value形式存储
# redis 数据放在内存中,如果断电,数据丢失---》需要有持久化的方案
# 5 种数据类型,value类型
-字符串:用的最多,做缓存;做计数器
-列表: 简单的消息队列
-字典(hash):缓存
-集合:去重
-有序集合:排行榜
Redis 字符串类型操作
conn = Redis()
# 可以点击Redis查看可配置的参数 链接地址 端口号 链接的库等
# 默认为 host="localhost",port=6379,db=0,
# 添加值 KV键值对形式 ex=过期时间(秒)
conn.set('name','moon',ex=30)
conn.set('name','moon111',nx=True)
conn.set('age','moon222',xx=True)
conn.setnx('name','张无忌')
# 相当于 conn.set(nx=True) 只要name有值就不会再更改
ex,过期时间(秒)
px,过期时间(毫秒)
nx,如果设置为True,则只有name不存在时,当前set操作才执行,值存在,就修改不了,执行没效果
xx,如果设置为True,则只有name存在时,当前set操作才执行,值存在才能修改,值不存在,不会设置新值
conn.mset({'k1':'v1','k2':'v2'})
# 批量设置值
# 获取值get KEY得到value
print(conn.get('name'))
conn.mget(['k1', 'k2'])
# 批量获取
如:
mget('k1', 'k2')
或
mget(['k3', 'k4'])
conn.close()
# getset(name, value)
res = conn.getset('k1','v11')
# 设置新值并获取原来的值
print(res) # v1
类似切片取值
# getrange(key, start, end)
res = conn.getrange('k1', 0, 1)
# 取出k1的值 并只要值的 0到1 2个字节
print(res)
获取值的字节长度
# strlen(name)
# 返回name对应值的字节长度(一个汉字3个字节)
res = conn.strlen('k1')
# 一个中文算3个字节 英文和数字都是一个字节
print(res)
conn.close()
整型值的 自增 自减 加减
# 自增 name对应的值,
# 自增数(必须是整数)
# incr(self, name, amount=1)
conn.incr('k3',amount=2)
# 对K3的值 自增2
print(conn.get('k3'))
# 自减,只能是整数,自身也必须是整数
conn.decr('k3',amount=1)
# 对K3的值 自减1
print(conn.get('k3'))
# 自增或自减可以是小数 或整数都可以
# incrbyfloat(self, name, amount=1.0)
conn.incrbyfloat('k3',amount=2.2)
conn.incrbyfloat('k3',amount=-20)
# 对K3的值 自增2
print(conn.get('k3'))
append(key, value)
在redis name对应的值后面追加内容
# 追加,在redis name对应的值后面追加内容
conn.append('k3','ok')
# 对K3的值 字符串后面追加ok eg:张无忌ok
print(conn.get('k3'))
Redis 列表类型操作
List操作,redis中的List在在内存中按照一个name对应一个List来存储。如图
lpush 插入数据 lrange获取数据
conn = Redis()
lpush(name,values)
conn.('l1',1,2,3,4)
# 创建一个键为 l1 值为 一个列表,列表中 依次添加 1,2,3,4
# 如果键不存在则创建,如果键存在 则 对值 头部追加 从左插入
# rpush 则对值进行尾部插入 从右插入
lpushx(name,values)
# 只有name存在 才可以加入数据,不存在则不生效
conn.llen('l1')
# 获取列表值 个数
#在列表中 某个数据前或者后插入数值
linsert(name, where, refvalue, value)
# key 前或者后 标杆 插入的数据
# 如果标杆不存在 则无法插入数据
conn.linsert('l2','after','22','33')
conn.linsert('l1','before','22','11')
# 对l1对应的list中的某一个索引位置重新赋值
conn.lset('l1',0,'9')
# l1的值 的索引0位置 重新赋值为 数据 9
# 在对应的list中删除指定的值
# 删除了l1 列表中的xxx 删除一个,
conn.lrem('l1',1,'xxx')
conn.lrem('l1',-1,'xxx')
# 从右开始删除一个xxx
conn.lrem('l1',0,'xxx')
# 0代表删除列表中所有的xxx
# 从左侧弹出 从头部
res = conn.lpop('l1')
# 从右侧弹出 从尾部
print(res)
res = conn.rpop('l1')
print(res)
# 按照索引位置取值 从0开始
res = conn.lindex('l1',1)
print(res)
# 按照索引位置取值 从0开始
res = conn.lrange('l1',0,1)
print(res)
获取列表内所有的值
res = conn.lrange('l1',0,conn.llen('l1'))
# 从开头到结束
conn.ltrim('l1',2,4)
# 只保留列表中 从索引位置 2 到 4 的数据
blpop
可以做简单的消息队列使用
res = conn.blpop('l1')
# 从列表左侧弹出一个数据,如果列表空了 代码就会一直等待接收
这样就可以 实现消息队列,等待存入数据,存入数据后 因为在blpop等待中
所以会立即取出
自定义增量迭代
如果列表内数据巨大,那就有必要增量迭代的功能
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)
Redis Hash类型操作
存储操作
conn = Redis()
conn.hset('d1', mapping={'name':'moon','age':18})
# key = d1 value = {'name':'moon','age':18}
取值操作
print(conn.hget('d1','age'))
# 取单个 返回单个数据
print(conn.hmget('d1','name','age'))
# 取更多 返回是列表
print(conn.hgetall('d1'))
# 取出所有的键值对
print(conn.hlen('d1'))
# Hash中key的个数
print(conn.hkeys('d1'))
# 取出所有的Kye
print(conn.hvals('d1'))
# 取出所有的value
查询/修改操作
print(conn.hexists('d1','hobby'))
# 查询是否有这个key 返回 True 或者 false
conn.hset('d1','hobby','篮球')
# 对字典新增键值对
conn.hdel('d1','hobby')
# 删除某个key
conn.hincrby('d1','age',amount=2)
# 对字典中的某个值 自增或自减 前提数据必须为整数
conn.hincrby('d1','age',amount=-1)
conn.hset('d1','hobby','足球')
# d1 有 bobby 则修改值 无则新增键值对
Redis数据通用方法
''' 通用操作,不指定类型,所有类型都支持
1 delete(*names)
2 exists(name)
3 keys(pattern='*')
4 expire(name ,time)
5 rename(src, dst)
6 move(name, db))
# 移动数据库
7 randomkey()
8 type(name)
'''
import redis
conn = redis.Redis()
# 1 delete(*names)
# conn.delete('name', 'userinfo2')
# conn.delete(['name', 'userinfo2']) # 不能用它
# conn.delete(*['name', 'userinfo2']) # 可以用它
# 2 exists(name)
# res=conn.exists('userinfo')
# print(res)
# 3 keys(pattern='*')
# res=conn.keys('w?e') # ?表示一个字符, * 表示多个字符
# print(res)
# 4 expire(name ,time)
# conn.expire('userinfo',3)
# 5 rename(src, dst)
# conn.rename('hobby','hobby111')
# 6 move(name, db))
# conn.move('hobby111',8)
# 7 randomkey()
# res=conn.randomkey()
# print(res)
# 8 type(name)
# print(conn.type('girls'))
print(conn.type('age'))
conn.close()
redis管道的使用
类似mysql中的事务,例如 银行转账 a对b转账100元
# redis支持事务吗 单实例才支持所谓的事物,支持事务是基于管道的
-执行命令 一条一条执行
-张三 金额 -100 conn.decr('zhangsan_je',100)
挂了
-你 金额 100 conn.incr('李四_je',100)
- 把这两条命令,放到一个管道中,先不执行,执行excute,一次性都执行完成
conn.decr('zhangsan_je',100) conn.incr('李四_je',100)
# 如何使用
import redis
conn = redis.Redis()
p=conn.pipeline(transaction=True)
# 开启一条管道
p.multi()
# 开启批量处理
p.decr('zhangsan_je', 100)
# 在管道中放入操作
p.incr('lisi_je', 100)
# 在管道中放入操作
p.execute()
# 一次性执行管道中的所有操作
# 这样就可以保证 一致性 要不代码都成功 要不都不成功
在django中使用redis
方式一:自定义包方案(通用的,不针对与框架,所有框架都可以用)
eg:统计某个接口的访问次数
第一步:在utils文件夹内 创建redis_pool文件
import redis
POOL = redis.ConnectionPool(max_connections=20)
# 现在redis_pool.py中 创建一个链接池
第二步:
在需要用的接口 导入这个POOL用
在views.py中
from LufeiApi.utils.redis_pool import POOL
import redis
@action(methods=['GET'],detail=False)
def text(self,request):
conn = redis.Redis(connection_pool=POOL)
# 生成一个redis对象
conn.incr('n1',amount=1)
# 对redis中的 ni key的值 进行自增1
res = conn.get('n1')
# 获取对应的值
return MyResponse({'次数':res})
方式二:django内置缓存更换为redis (推荐django使用)可以存对象
安装 django_redis 模块
在配置文件中添加配置代码
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379",
# redis的链接地址
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100}
# 自带链接池
# "PASSWORD": "123",
}
}
}
然后在需要用的地方 直接导入
from django.core.cache import cache
cache.set('n1',1)
cache.get('n1')
# 这样就替换了django自带的内容,存的数据都存到了redis中 直接可以通过这种方式存取
def text(self,request):
user = User.objects.filter(username='moon').first()
cache.set(user.username,user)
# 直接存对象进去 key=对象的名字 value=对象
res = cache.get('moon')
# 取出来还是个对象可以直接.数据
return MyResponse({'phone':res.phone})
方法三:正常连接redis使用
-方案二:第三方: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})
标签:name,res,redis,使用,print,Redis,conn
From: https://www.cnblogs.com/moongodnnn/p/17196190.html