当前位置: 首页 > news >正文

Python 框架学习 Django篇 (十) Redis 缓存

     开发服务器系统的时候,程序的性能是至关重要的。经过我们前面框架的学习,得知一个请求的处理基本分为接受http请求、数据库处理、返回json数据,而这3个部分中就属链接数据库请求的响应速度最慢,因为数据库操作涉及到数据库服务处理请求,读写硬盘数据

     而操作数据库的增、删、改、查中,查询属于读取数据,而删除、修改、增加属于写入数据,我们做缓存也主要是给查询这块的数据做优化

一、缓存的原理

      众所周知,从内存中读写数据的速度要比去磁盘中读写的速度要快,而缓存就是先将我们要查询的数据从mysql数据库中读取一份,然后放到内存中,因为避免了从硬盘读取表记录的操作,程序访问内存的速度要比访问数据库快很多,特别是当一个读操作要涉及到多张表的联合查询,或者这些表比较大,就会非常耗时

      而做缓存可以使用多种方案,最简单的直接通过python的字典做缓存,但这种方法同时也具有很大的弊端,比如不支持分布式,当业务量大的时候部署到不同主机会造成严重的资源占用问题,并且当有一台主机上的缓存数据需要更新时,要通知其他节点一起更新,比较麻烦, 还要防止 数据同步前 可能不同节点给出的数据不一致的问题,而RedisMemcached 是目前两种主流的缓存服务方案,我们这里使用redis做缓存

1、redis部署

网上装redis的教程很多我这里不在赘述,为了省事直接用docker部署了

mkdir /apps/demo/redis/{conf,data} -p
cd /apps/demo/redis#拉取镜像
docker pull redis:6.2.7

  vi conf/redis.conf

bind 0.0.0.0maxmemory 4GB
maxmemory-policy allkeys-lru
maxmemory-samples 10tcp-backlog 511aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
rdbcompression yes
rdbchecksum yesaof-rewrite-incremental-fsync yesrequirepass 123456
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command CONFIG ""activerehashing yes
dynamic-hz yes
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64

配置说明

bind 0.0.0.0     #允许外部访问## 内存优化
maxmemory 4GB                                   # 设置Redis实例的最大内存限制
maxmemory-policy allkeys-lru                    # 设置在达到最大内存限制时所采取的淘汰策略为LRU(最近最少使用)
maxmemory-samples 10                            # 指定在key的过期删除策略中随机抽取的样本数目## 网络优化
tcp-backlog 511                                 # 设置内核中由Redis监听的TCP连接的最大长度## 持久化优化
aof-rewrite-incremental-fsync yes               # 启用AOF(Append Only File)增量式文件同步
rdb-save-incremental-fsync yes                  # 使用增量传输来持久化RDB文件
rdbcompression yes                              # 开启RDB文件的压缩
rdbchecksum yes                                 # 启用RDB文件的校验和## AOF压缩
aof-rewrite-incremental-fsync yes               # 启用AOF(Append Only File)增量式文件同步## 安全
requirepass yourpassword                        # 设置Redis服务器连接密码
rename-command FLUSHDB ""                       # 重命名FLUSHDB命令
rename-command FLUSHALL ""                      # 重命名FLUSHALL命令
rename-command CONFIG ""                         # 重命名CONFIG命令## 性能优化
activerehashing yes                             # 启用集群环境的rehashing(对已有的键表重新分布)
dynamic-hz yes                                 
hash-max-ziplist-entries 512                    # 设置hash结构的压缩阈值
hash-max-ziplist-value 64                       # 设置hash结构的压缩阈值
list-max-ziplist-entries 512                    # 设置list结构的压缩阈值
list-max-ziplist-value 64                       # 设置list结构的压缩阈值
set-max-intset-entries 512                      # 设置intset编码的集合的最大元素数量
zset-max-ziplist-entries 128                    # 设置zset结构的压缩阈值
zset-max-ziplist-value 64                       # 设置zset结构的压缩阈值

2、启动服务

vi ./run.sh

 docker run -p 36379:6379 --name redis \-v ./data:/data \-v ./conf/redis.conf:/etc/redis/redis.conf \-d redis:6.2.7 \redis-server /etc/redis/redis.conf

运行

sh run.sh

二、Redis使用

Redis是一个数据仓库服务,这个仓库里面可以存储很多 数据对象

存储的每个数据对象都有一个key,根据这个key,可以找到这个对象。

要添加一个数据对象,必须为这个数据对象指定一个key,就像指定一个房间号

Redis key 对应的value支持多种数据对象,可以是字符串、列表、哈希对象

 

 查阅资料的时候发现有一篇同样讲缓存的帖子很不错,这里留个档

https://blog.csdn.net/qq_43745578/article/details/128569060

 1、登录redis

#登录redis容器
docker exec -it redis bash#通过redis客户端登录数据库
redis-cli -h 127.0.0.1#认证用户
auth 123456

 

2、redis数据库切换

redis数据库和mysql一样都是包含很多个数据库的,编号为0-15,通过select 命令切换不同的数据库使用,每个数据库我们可以看作是一个仓库用来存放货物,默认编号为0 ,现在我们切换到1号数据库然后进行下面的仓库,切换完后能看到端口后面跟着个1

select 1

 

3、添加数据

上面说了,redis可以存放各种类型的数据,字符串、列表、哈希对象等等,而根据不同类型的数据,redis也有想对应的命令,比如我们要存入的数据是一个字符串,那么新增的命令就是set,而对应的查询命令为 get  key名

127.0.0.1:6379[1]> set zhangsan:1 ynby
OK127.0.0.1:6379[1]> get zhangsan:1
"ynby"

4、查询所有的key

很多时候我们是不记得key的名称,就需要模糊查询一下key有那些

127.0.0.1:6379[1]> keys zha*
1) "zhangsan:1"
127.0.0.1:6379[1]>

5、删除数据

127.0.0.1:6379[1]> del zhangsan:1
(integer) 1
127.0.0.1:6379[1]> keys *
(empty array)

6、添加哈希值

如果我们要存入 Redis的对象比较复杂,比如用户信息,包括等级、金币、姓名等等,

可以使用哈希(Hash)对象,Redis 哈希对象的每个字段 ,术语称之为 field

存入Hashes,就使用客户端命令 hmset 或者 hset

#添加hash值
127.0.0.1:6379[1]> hmset user:2001 level 10 coin 1977 name 你好
OK#获取单个字段的值hget
127.0.0.1:6379[1]> hget user:2001 coin
"1977"#获取所有字段的值hgetall
127.0.0.1:6379[1]> hgetall user:2001
1) "level"
2) "10"
3) "coin"
4) "1977"
5) "name"
6) "\xe4\xbd\xa0\xe5\xa5\xbd"

上面案例中的name字段的值被utf8编码了,客户端程序在使用时根据需要进行相应解码

7、定义哈希表

既然 Hash 本身就是一个字典,我们通常还会把整个用户表都直接放入 一个hash里面

可以给这个hash对应的对象 起一个key名为 usertable

#添加表数据
hmset usertable u2001  id:2001|level:10|coin:1977|name:张三
hmset usertable u2002  id:2002|level:13|coin:1927|name:李四#查询表数据
127.0.0.1:6379[1]> hget usertable u2002
"id:2002|level:13|coin:1927|name:\xe6\x9d\x8e\xe5\x9b\x9b"

 步骤6、7保存的方法各有个的缺点,方案6是方便修改单个field的值,但是容易出现大量的key,方案7虽然全局查看key较为方便,但没办法修改单个field的值,只能一起修改

三、Django项目缓存配置

1、安装redis库

pip install django-redis

2、配置django全局缓存

Django_demo/Django_demo/settings.py

CACHES = {"default": {"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://101.43.156.78:36379/1","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient",# 密码'PASSWORD': '123456',  #没有密码就去掉这行}}
}

 上面的这段配置可以放在数据库 DATABASES 配置项的下方。LOCATION 配置项最后的数字1 是 DB number,指定redis的数据库号

3、使用缓存配置

不是任何数据库的数据都应该使用缓存,至少满足两个要求(频繁读取的数据 、较少变动的数据)

如果这个数据写入后基本就不会在修改了,但是需要经常性的读取,那么他就是一个值得缓存的数据

举个例子

      在前面编写的案例中,属于药品的信息就符合上面的两点要求,我们可以在处理列出药品 的API接口 的代码中,把数据库读出的内容进行缓存,这里我们采用上面的缓存方案二(redis使用-7)把所有的 列出药品都放在一个哈希对象中

      首先,我们需要为 列出药品的缓存 创建一个key,名字为 medicinelist因为我们将来会有很多种类型的数据要缓存,它们有不同的key,所以建议统一放在配置文件 settings.py

 Django_demo/Django_demo/settings.py

# 记录全局的缓存key,防止重复
class CK:# 列出药品 的 缓存 keyMedineList   = 'list_medicine'# 列出客户 的 缓存 keyCustomerList = 'list_customer'

这样的好处是,放在一起,如果有重复的key名,比较容易发现

4、修改查询数据的缓存配置

我们将原先的查询数据库返回的数据,交给redis

Django_demo/mgr/medicine.py

#添加
from Django_demo import settings
import json
import traceback
from django.core.paginator import Paginator, EmptyPage
from django.db.models import Q
from django_redis import get_redis_connection# 获取一个和Redis服务的连接
rconn = get_redis_connection("default")def listmedicine(request):try:# 查看是否有 关键字 搜索 参数keywords = request.params.get('keywords',None)# 要获取的第几页pagenum = request.params['pagenum']# 每页要显示多少条记录pagesize = request.params['pagesize']# 先看看缓存中是否有cacheField = f"{pagesize}|{pagenum}|{keywords}" # 缓存 fieldcacheObj = rconn.hget(settings.CK.MedineList,cacheField)# 缓存中有,需要反序列化if cacheObj:print('缓存命中')retObj = json.loads(cacheObj)# 如果缓存中没有,再去数据库中查询else:print('缓存中没有')# 返回一个 QuerySet 对象 ,包含所有的表记录qs = Medicine.objects.values().order_by('-id')if keywords:conditions = [Q(name__contains=one) for one in keywords.split(' ') if one]query = Q()for condition in conditions:query &= conditionqs = qs.filter(query)# 使用分页对象,设定每页多少条记录pgnt = Paginator(qs, pagesize)# 从数据库中读取数据,指定读取其中第几页page = pgnt.page(pagenum)# 将 QuerySet 对象 转化为 list 类型retlist = list(page)retObj = {'ret': 0, 'retlist': retlist,'total': pgnt.count}# 存入缓存rconn.hset(settings.CK.MedineList,cacheField,json.dumps(retObj))# total指定了 一共有多少数据return JsonResponse(retObj)except EmptyPage:return JsonResponse({'ret': 0, 'retlist': [], 'total': 0})except:print(traceback.format_exc())return JsonResponse({'ret': 2,  'msg': f'未知错误\n{traceback.format_exc()}'})

这样,我们就确保了,处理列出药品的请求时,优先从缓存中读取,如果没有再从数据库读取。

并且数据库读取到数据后,存入缓存,这样下次同样的请求就可以从缓存中获取数据了

5、添加缓存数据更新

      使用缓存一定要注意缓存数据的更新,我们前面做完了缓存,如果我们后面对药品数据做出了添加、修改、删除的操作,那么缓存里面的数据就和数据库不一致了,如果我们每次都更新缓存是很麻烦的,简单的方法就是直接删除对应的缓存数据,这样下次请求时缓存中没了数据,还是会去数据库中读取的,这样就能拿到最新的数据到缓存中

def addmedicine(request):info    = request.params['data']# 从请求消息中 获取要添加客户的信息# 并且插入到数据库中medicine = Medicine.objects.create(name=info['name'] ,sn=info['sn'] ,desc=info['desc'])# 同时删除整个 medicine 缓存数据# 因为不知道这个添加的药品会影响到哪些列出的结果# 只能全部删除rconn.delete(settings.CK.MedineList)return JsonResponse({'ret': 0, 'id':medicine.id})def modifymedicine(request):# 从请求消息中 获取修改客户的信息# 找到该客户,并且进行修改操作medicineid = request.params['id']newdata    = request.params['newdata']try:# 根据 id 从数据库中找到相应的客户记录medicine = Medicine.objects.get(id=medicineid)except Medicine.DoesNotExist:return  {'ret': 1,'msg': f'id 为`{medicineid}`的药品不存在'}if 'name' in  newdata:medicine.name = newdata['name']if 'sn' in  newdata:medicine.sn = newdata['sn']if 'desc' in  newdata:medicine.desc = newdata['desc']# 注意,一定要执行save才能将修改信息保存到数据库medicine.save()# 同时删除整个 medicine 缓存数据# 因为不知道这个修改的药品会影响到哪些列出的结果# 只能全部删除rconn.delete(settings.CK.MedineList)return JsonResponse({'ret': 0})def deletemedicine(request):medicineid = request.params['id']try:# 根据 id 从数据库中找到相应的药品记录medicine = Medicine.objects.get(id=medicineid)except Medicine.DoesNotExist:return  {'ret': 1,'msg': f'id 为`{medicineid}`的客户不存在'}# delete 方法就将该记录从数据库中删除了medicine.delete()# 同时删除整个 medicine 缓存数据# 因为不知道这个删除的药品会影响到哪些列出的结果# 只能全部删除rconn.delete(settings.CK.MedineList)return JsonResponse({'ret': 0})

6、测试访问药品表

下面测试一下查询药品表后redis是否缓存成功

vi main.py

import  requests,pprint#添加认证
payload = {'username': 'root','password': '12345678'
}
#发送登录请求
response = requests.post('http://127.0.0.1:8000/api/mgr/signin',data=payload)
#拿到请求中的认证信息进行访问
set_cookie = response.headers.get('Set-Cookie')# 构建添加 客户信息的 消息体,是json格式
payload = {'action': 'list_medicine','pagenum': 1,'pagesize' : 3
}url='http://127.0.0.1:8000/api/mgr/medicines/'if set_cookie:# 将Set-Cookie字段的值添加到请求头中headers = {'Cookie': set_cookie}# 发送请求给web服务response = requests.post(url,json=payload,headers=headers)pprint.pprint(response.json())

返回

{'ret': 0,'retlist': [{'desc': 'gmkl', 'id': 6, 'name': 'gmkl', 'sn': '111'}],'total': 1}

然后我们登录redis查看有没有我们写入的数据

127.0.0.1:6379[1]> hgetall list_medicine
1) "3|1|None"
2) "{\"ret\": 0, \"retlist\": [{\"id\": 6, \"name\": \"gmkl\", \"sn\": \"111\", \"desc\": \"gmkl\"}], \"total\": 1}"

7、测试添加药品表

vi main1.py

import  requests,pprint#添加认证
payload = {'username': 'root','password': '12345678'
}
#发送登录请求
response = requests.post('http://127.0.0.1:8000/api/mgr/signin',data=payload)
#拿到请求中的认证信息进行访问
set_cookie = response.headers.get('Set-Cookie')# 构建添加 客户信息的 消息体,是json格式
payload = {"action":"add_medicine","data":{"name":"lhms","sn":"test","desc":"test",}
}url='http://127.0.0.1:8000/api/mgr/medicines/'if set_cookie:# 将Set-Cookie字段的值添加到请求头中headers = {'Cookie': set_cookie}# 发送请求给web服务response = requests.post(url,json=payload,headers=headers)pprint.pprint(response.json())

返回

{'id': 7, 'ret': 0}

我们增加、删除、修改,都会将原先redis中的缓存清理掉

 

我们在用第6步的访问在查询下,查看redis缓存数据数据

127.0.0.1:6379[1]> hgetall list_medicine
1) "3|1|None"
2) "{\"ret\": 0, \"retlist\": [{\"id\": 7, \"name\": \"lhms\", \"sn\": \"test\", \"desc\": \"test\"}, {\"id\": 6, \"name\": \"gmkl\", \"sn\": \"111\", \"desc\": \"gmkl\"}], \"total\": 2}"

 

 缓存成功~

相关文章:

Python 框架学习 Django篇 (十) Redis 缓存

开发服务器系统的时候,程序的性能是至关重要的。经过我们前面框架的学习,得知一个请求的处理基本分为接受http请求、数据库处理、返回json数据,而这3个部分中就属链接数据库请求的响应速度最慢,因为数据库操作涉及到数据库服务处理…...

考研数学笔记:线性代数中抽象矩阵性质汇总

在考研线性代数这门课中,对抽象矩阵(矩阵 A A A 和矩阵 B B B 这样的矩阵)的考察几乎贯穿始终,涉及了很多性质、运算规律等内容,在这篇考研数学笔记中,我们汇总了几乎所有考研数学要用到的抽象矩阵的性质…...

C语言--假设共有鸡、兔30只,脚90只,求鸡、兔各有多少只​

一.题目描述 假设共有鸡、兔30只,脚90只,求鸡、兔各有多少只? 二.思路分析 本题是一个典型的穷举法例题,而穷举法,最重要的就是条件判断。⭐⭐ 本题中的条件很容易发现: 假设鸡有x只,兔有y只…...

nacos适配达梦数据库

一、下载源码 源码我直接下载gitee上nacos2.2.3的,具体链接:https://gitee.com/mirrors/Nacos/tree/2.2.3,具体如下图: 二、集成达梦数据库驱动 解压源码包,用idea打开源码,等idea和maven编译完成&#xff…...

CTFhub-RCE-读取源代码

源代码&#xff1a; <?php error_reporting(E_ALL); if (isset($_GET[file])) { if ( substr($_GET["file"], 0, 6) "php://" ) { include($_GET["file"]); } else { echo "Hacker!!!"; } } else {…...

Ansible playbook详解

playbook是ansible用于配置&#xff0c;部署&#xff0c;和被管理被控节点的剧本 playbook常用的YMAL格式&#xff1a;&#xff08;文件名称以 .yml结尾&#xff09; 1、文件的第一行应该以 "---" (三个连字符)开始&#xff0c;表明YMAL文件的开始。    2、在同一…...

Linux编辑器:vim的简单介绍及使用

目录 1.什么是vim 2.vim的基本概念 3.vim 的基本操作 4. 各模式下的命令集 4.1 正常模式命令集 4.2 末行模式命令集 5.补充 5.1 vim支持多文件编辑 5.2 vim 的配置 1.vim 配置原理 2. 常用简单配置选项&#xff1a; 3. 使用插件 1.什么是vim Vim 是从 vi 发展出…...

Redhat7查看时区、修改时区

问题&#xff1a; 安装好redhat7之后&#xff0c;发现时间和物理机上面的网络时间不一致&#xff0c;于是查看本着修改时间的目的&#xff0c;却发现原来是时区的问题。 解决步骤&#xff1a; 查看时区状态信息 timedatectl修改时区到亚洲/上海 timedatectl set-timezone A…...

OpenCV踩坑笔记使用笔记入门笔记整合SpringBoot笔记大全

springboot开启摄像头抓拍照片并上传实现&问题记录 NotAllowedErrot: 请求的媒体源不能使用&#xff0c;以下情况会返回该错误: 当前页面内容不安全&#xff0c;没有使用HTTPS没有通过用户授权NotFoundError: 没有找到指定的媒体通道NoReadableError: 访问硬件设备出错Ov…...

【数据结构】栈和队列的模拟实现(两个方式实现)

前言 &#x1f493;作者简介&#xff1a; 加油&#xff0c;旭杏&#xff0c;目前大二&#xff0c;正在学习C&#xff0c;数据结构等&#x1f440; &#x1f493;作者主页&#xff1a;加油&#xff0c;旭杏的主页&#x1f440; ⏩本文收录在&#xff1a;再识C进阶的专栏&#x1…...

OpenCV+相机校准和3D重建

相机校准至少需要10个测试图案&#xff0c;所需的重要输入数据是3D现实世界点集以及图像中这些点的相应2D坐标。3D点称为对象点&#xff0c;而2D图像点称为图像点。 准备工作 除了棋盘&#xff0c;我们还可以使用圆形网格。 在这种情况下&#xff0c;我们必须使用函数cv.find…...

2023.11.14-hive之表操作练习和文件导入练习

目录 需求1.数据库基本操作 需求2. 默认分隔符案例 需求1.数据库基本操作 -- 1.创建数据库test_sql,cs1,cs2,cs3 create database test_sql; create database cs1; create database cs2; create database cs3; -- 2.1删除数据库cs2 drop database cs2; -- 2.2在cs3库中创建…...

idea2023启动springboot项目如何指定配置文件

方法一&#xff1a; 方法二&#xff1a; 举例&#xff1a;...

在 uniapp 中 一键转换单位 (px 转 rpx)

在 uniapp 中 一键转换单位 px 转 rpx Uni-app 官方转换位置利用【px2rpx】插件Ctrl S一键全部转换下载插件修改插件 Uni-app 官方转换位置 首先在App.vue中输入这个&#xff1a; uni.getSystemInfo({success(res) {console.log("屏幕宽度", res.screenWidth) //屏…...

SQL对数据进行去重

工作中使用SQL对数据进行处理计算时可能会遇到这样的问题&#xff1b;读取的表数据会有重复&#xff0c;或者我们关注的几个字段的数据会有重复&#xff0c;直接使用原表数据会引起计算结果不准或者做表连接时产生笛卡尔积。 本文记录使用SQL进行数据去重的几种算法。 distinc…...

登录注册代码模板(Vue3+SpringBoot)[邮箱发送验证码(HTML)、RSA 加密解密(支持长文本)、黑暗与亮色主题切换、AOP信息校验]

文章归档&#xff1a;https://www.yuque.com/u27599042/coding_star/cx5ptule64utcr9e 仓库地址 https://gitee.com/tongchaowei/login-register-template 网页效果展示 相关说明 在该代码模板中&#xff0c;实现了如下功能&#xff1a; 邮箱发送验证码&#xff08;邮件内容…...

【计算机网络】VRRP协议理论和配置

目录 1、VRRP虚拟路由器冗余协议 1.1、协议作用 1.2、名词解释 1.3、简介 1.4、工作原理 1.5、应用实例 2、 VRRP配置 2.1、配置命令 2.2、拓扑与配置&#xff1a; 1、VRRP虚拟路由器冗余协议 1.1、协议作用 虚拟路由冗余协议(Virtual Router Redundancy Protocol&am…...

ubuntu操作系统的docker更换存储目录

前言 要将Docker的存储目录更改为/home/docker&#xff0c;你需要进行以下步骤&#xff1a; 目录 前言1、停止Docker服务2、创建新的存储目录3、编辑Docker配置文件4、启动Docker服务5、验证更改 1、停止Docker服务 首先停止Docker守护进程&#xff0c;可以使用以下命令&…...

【人工智能Ⅰ】6-机器学习之分类

【人工智能Ⅰ】6-机器学习之分类 6-1 机器学习在人工智能中的地位 学习能力是智能的本质 人工智能 > 机器学习 > 深度学习 什么是机器学习&#xff1f; baidu&#xff1a;多领域交叉学科&#xff08;做什么&#xff09; wiki&#xff1a;the study of algorithms and…...

本地部署_语音识别工具_Whisper

1 简介 Whisper 是 OpenAI 的语音识别系统&#xff08;几乎是最先进&#xff09;&#xff0c;它是免费的开源模型&#xff0c;可供本地部署。 2 docker https://hub.docker.com/r/onerahmet/openai-whisper-asr-webservice 3 github https://github.com/ahmetoner/whisper…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...