redis的基础---操作内存so easy
1, redis是做什么的?有哪些优势?
redis是帮助开发者在内存中操作数据的软件.
- redis可以做持久化:
AOF :可以定时把内存中的数据写在硬盘当中,即使宕机也可以重新把数据从文件中把数据读取到内存中.
缺点: 可能会造成数据丢失,数据不完整.
RDB :每执行一条命令,就往硬盘上写一条数据,完全保证数据不会丢失,数据完整.
缺点: 效率低
- 相当于是大字典
- 单进程单线程 可以有多连接
- redis的特点:
a. 持久化
b. 单进程,单线程
c. 5大数据类型
补充:
简单理解IO多路复用:
可以创建一个连接池,服务端与很多客户端创建连接,(因为在网络中连接是相对要耗费时间的,数据传输
相对较快),例如:此时服务端同时连接多名客户端,如果其中一个客户端请求数据,可以直接发过去,
如果很多客户同时请求数据: 可以选择单线程,单进程排队获取数据
也可以选择到多线程同时进行.
1.1 使用连接池
连接池的好处:
1, 资源重用
2, 更快的资源响应速度
3, 新的资源分配手段
例如: 设置某一应用最大可用数据库连接数的限制,避免某一应用独占所有数据库资源。
4, 统一的连接管理,避免数据库连接泄露
## 本质: 维护一个已经和服务端连接成功的socket.以后再次发送数据时,可以获取一个socket,直接send数据就行;
1.2 连接池实现的内部原理





2, redis的五大数据类型
redis={
k1:'123', 字符串
k2:[12,11,22,11,33,5], 列表
k3:{1,2,3,5}, 集合
k4:{name:123,age:18}, 字典
k5:{('alex',60),('eva-j',100),('日天':70)} 有序集合
}
# 注意事项: redis操作时,只有第一层value支持: list ,dict,.....
# 慎重使用hgetall,优先使用 hscan_iter
2.1 redis的五大数据类型-------字典
2.1.1. redis操作数据的方法(增删改查)
hset(name, key,value) # redis中的hash指的是字典
# name对应的是hash中设置的一个键值对(不存在,则创建;否则,修改)\
# 参数:
# name, redis的name
# key, name对应字典中的key
# value,name对应的hash中的value
# 注: hsetnx(name,key,value),当name对应的字典中不存在当前key时则创建(相当于添加)
hmset(name,mapping)
# 在name对应的字典中批量设置键值对
# 参数:
# name, redis的name
# mapping, 字典;如{'k1':'v1','k2':'v2'}
# 如:
# r.hmset('xx',{'k1':'v1','k2':'v2'})
hget(name,key)
# 在name对应的字典中根据key获取value
hmget(name,keys,*args)
# 在name对应的字典中获取多个key的值
# 参数:
# name,redis对应的name
# keys,要获取key集合,如: ['k1','k2','k3']
# *args,要获取的key,如:k1,k2,k3
# 如:
# r.mget('xx',['k1','k2'])
# 或
# print(r.hmget('xx','k1','k2'))
hgetall(name)
# 获取name对应的字典的所有键值
hlen(name)
# 获取name对应的字典中键值对的个数
hkeys(name)
# 获取name对应的字典中所有的key
hvals(name)
# 获取name对应的字典中的所有valve
hexists(name,key)
# 检查name对应的字典中是否存在当前传入的key
hdel(name,*key)
# 将name对应的字典中指定key的键值对删除
hincrby(name,key,amount=1)
# 自增name对应的字典中的指定key的值,不存在则创建key=amount
# 参数:
# name, redis中的name
# key, 字典对应的key
# amount 自增数(整数)
hincrbyfloat(name,key,amount=1.0)
# 自增name对应的字典中指定key的值,不存在则创建key=amount
# 参数:
# name redis中的name
# key, 字典中对应的key
# amount 自增数(浮点数)
hscan(name,cursor=0,match=None,count=None)
# 增量式迭代获取,对数据量大的数据非常有用,hacan可以实现分片的获取数据,并非一次性将数据全部获取完,从而放在内存被撑爆
# 参数:
# 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时,表示数据已经通过分片获取完毕
hscan_iter(name,match=None,count=None)
# 利用yield封装hscan创建生成器,实现分批去redis中获取数据
# 参数:
# match, 匹配指定key,默认None 表示所有的key
# count 每次分片最少获取个数,默认None表示采用Redis的默认分片数
如:
## 正确示范, 用生成器,每次取100条直到取完, 且不会占用过多内存
ret = conn.hscan_iter('k4',count=100)
for item in ret:
print(item)
2.1.2 hscan_iter -----redis为字典内置的生成器

2.2 redis五大数据类型------列表
2.2.1 列表的增删改查操作
lpush(name,values) # 在list中添加元素,每个新的元素都添加到列表的左边
例: conn.lpush('k1',11,22,33)
保存顺序为: 33,22,11
# 扩展 rpush(name,value) 表示从右向左操作
lpushx(name,value) # 在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边
# 扩展 rpush(name,value) 表示从右向左操作
llen(name) # name对应的list元素的个数
linsert(name,where,refvalue,value) # 在name对应的列表的指定位置插入新值
# 参数:
# name , redis的name
# where, before或after
# refvalue 标杆值,即:在它的前后插入数据
# value 要插入的数据
lset(name,index,value) # 对name对应的list中的某一个索引位置重新赋值 (更新操作)
# 参数:
# name redis的name
# index list的索引位置
# value 要设置的值
lrem(name,value,num) # 在name对应的list中删除指定的值
# 参数:
# name redis的name
# value 要删除的值
# num, num=0 删除列表中所有的指定值
# num=2 从前到后, 删除2个;
# num=-2 从后向前, 删除2个.
lpop(name) #在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素
# 扩展
# rpop(name) 表示从右向左操作
lindex(name,index) # 在name对应的列表中根据索引获取列表元素
lrange(name,start,end) # 在name对应的列表中分片获取数据
# 参数:
# name redis的name
# start 索引的起始位置
# end 索引结束的位置
ltrim(name,start,end) # 在name对应的列表中移除没有在start-end索引之间的值
# 参数
# name redis的name
# start 索引的起始位置
# end 索引的结束位置
rpoplpush(src,dst) # 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
# 参数
# src 要取数据的列表的name
# dst 要添加数据的列表的name
blpop(keys,timeout) # 将多个列表排列, 按照从左到右的顺序去pop对应列表的元素
# 参数:
# keys redis的name集合
# timeout 超时时间,当所有列表的所有元素获取完之后,阻塞等待列表内有数据的时间(秒), 0表示永远阻塞
# 更多:
# brpop(keys,timeout), 从右向左获取数据
brpoplpush(src,dst,timeout=0) # 从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧
# 参数:
# src 要取元素的列表对应的name
# sdt 要插入元素的猎豹对应的name
# timeout 当src对应的列表中没有数据时,阻塞等待其有数据的超时时间(秒),0表示永远阻塞
## 补充
堆/队列(queue) : 先进先出, 就像一个管道
栈: 后进先出,就像弹夹, 砌墙的砖头-----后来居上
2.2.2 自定义迭代器(灵感来自源码对字典做的迭代器)
# 通过yield创建一个生成器完成一点一点获取(通过字典操作的源码来的灵感)
conn.lpush('k1',*[11,22,33,444,55,42,45,56,76,88,79,34,23])
# 给redis的列表做一个生成器,使数据能够一点一点的取出,不至于占用大量的资源,引发爆栈
def list_iter(key,count=100):
index = 0
while True:
data_list=conn.lrange(key,index,index+count-1)
if not data_list:
break
index +=count
for item in data_list:
yield item
for item in list_iter('k1',count=20):
print(item)
2.2.3
事务 + 一次发送多个命令
"""
在redis中进行事务操作 ---如果成功就一起成功,失败就一起失败 同生共死
transaction n. 交易,买卖,业务
execute 执行
"""
import redis
conn=redis.Redis(host='10.0.0.210',port=6379,password=123456)
pipe = conn.pipeline(transaction=True)
pipe.multi()
pipe.set('k2','大风吹')
pipe.hset('k3','n1',666)
pipe.lpush('k4','吴琪')
pipe.execute()
3. 在pycharm中使用redis,控制内存
3.1 在Python中创建redis连接
应用场景:
D:\GIT&前后端分离(后端)\day110
1,自定义使用redis
D:\GIT&前后端分离(后端)\day110\app01
2,使用第三方组件
D:\GIT&前后端分离(后端)\day110\app02
配置:
# redis配置
CACHES ={
'default':{
"BACKEND":"django_redis.cache.RedisCache",
"LOCATION":"redis://10.0.0.210:6379",
"OPTIONS":{
"CLIENT_CLASS":"django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS":{"max_connections":1000},
"PASSWORD":123456,
},
},# 可以配置多个redis连接
}
使用:
from django.shortcuts import HttpResponse
# 借助django的redis组件,实现对内存的控制,需要在settings中设置redis的CACHES配置
from django_redis import get_redis_connection
def django_index(request):
conn=get_redis_connection("default")
return HttpResponse('设置成功')
def django_order(request):
conn=get_redis_connection('back')
return HttpResponse('获取成功')
3.2.1. 全站缓存(整个网站的所有页面都做缓存)


3.2.2 redis实现单页面缓存
import time
from django.views.decorators.cache import cache_page
@cache_page(60*15)
def django_index(request):
# 单视图缓存 需要用到装饰器, 装饰器的优先级比全局的优先级要高 ,ps: 对此页面做15分钟的缓存
ctime=str(time.time())
return HttpResponse(ctime)
3.2.3 redis实现对页面的某部分做缓存
def django_order(request):
# 对页面的某部分做缓存
return render(request,'order.html')
## order.html页面
{% load cache %} ## 导入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>advVS的地方</h1>
<div>
asdf
</div>
{% cache 5000 缓存key %}
缓存内容 ## 这里是单页面的局部视图的缓存,占用的内存空间更少,更精准.
{% endcache %}
</body>
</html>
浙公网安备 33010602011771号