redis的基础---操作内存so easy

1, redis是做什么的?有哪些优势?

redis是帮助开发者在内存中操作数据的软件.

1
2
3
4
5
- redis可以做持久化:
    AOF :可以定时把内存中的数据写在硬盘当中,即使宕机也可以重新把数据从文件中把数据读取到内存中.
    缺点: 可能会造成数据丢失,数据不完整.
    RDB :每执行一条命令,就往硬盘上写一条数据,完全保证数据不会丢失,数据完整.
    缺点: 效率低<br>- 相当于是大字典<br><br>- 单进程单线程 可以有多连接<br><br>- redis的特点:<br>    a. 持久化<br>    b. 单进程,单线程<br>    c. 5大数据类型<br>

 补充:

1
2
3
4
5
简单理解IO多路复用:
        可以创建一个连接池,服务端与很多客户端创建连接,(因为在网络中连接是相对要耗费时间的,数据传输
    相对较快),例如:此时服务端同时连接多名客户端,如果其中一个客户端请求数据,可以直接发过去,
    如果很多客户同时请求数据: 可以选择单线程,单进程排队获取数据
    也可以选择到多线程同时进行.   

 1.1 使用连接池

1
2
3
4
5
6
7
8
连接池的好处:
    1, 资源重用
    2, 更快的资源响应速度
    3, 新的资源分配手段
            例如: 设置某一应用最大可用数据库连接数的限制,避免某一应用独占所有数据库资源。
    4, 统一的连接管理,避免数据库连接泄露
     
## 本质: 维护一个已经和服务端连接成功的socket.以后再次发送数据时,可以获取一个socket,直接send数据就行;

 1.2 连接池实现的内部原理

 

 

 

 

 

 

 

 

 

 2, redis的五大数据类型

1
2
3
4
5
6
7
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)}                  有序集合
        }<br># 注意事项: redis操作时,只有第一层value支持: list ,dict,.....<br># 慎重使用hgetall,优先使用 hscan_iter<br>

 2.1  redis的五大数据类型-------字典

  2.1.1. redis操作数据的方法(增删改查)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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 列表的增删改查操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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  自定义迭代器(灵感来自源码对字典做的迭代器)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 通过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中进行事务操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
事务 + 一次发送多个命令
"""
在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连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
应用场景:
    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实现单页面缓存

1
2
3
4
5
6
7
8
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实现对页面的某部分做缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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>

 

posted @   凉城以北  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
点击右上角即可分享
微信分享提示