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

Redis应用笔记

Redis应用笔记

  • 一、 前言
  • 二、 Redis八种常用数据类型
    • 2.1 Redis的五种基本数据类型
    • 2.2 Redis的三种特殊数据类型
  • 三、发现Redis热Key方案
    • 3.1 使用 Redis 自带的 --hotkeys 参数来查找
    • 3.2 使用MONITOR 命令
    • 3.3 借助开源项目
  • 四、解决 hotkey
  • 五、Redis 内存碎片
    • 5.1 为何会有Redis 内存碎片
    • 5.2 查看Redis内存碎片信息
    • 5.3 清理 Redis 内存碎片
  • 六、Redis缓存预热
    • 6.1 预热工具
    • 6.2 启动预热
      • 6.2.1 Spring Boot特定逻辑接口
      • 6.2.2 使用 InitializingBean 接口
      • 6.2.3 使用@PostConstruct 注解
      • 6.2.4 定时任务预热
      • 6.2.5 缓存器预热

一、 前言

夯实Redis基础以及生产环境应用优化的笔记~
在这里插入图片描述

二、 Redis八种常用数据类型

  • 5 种基础数据类型:String(字符串)、List(列表)、Set(集合)、Hash(散列)、Zset(有序集合)。
  • 3 种特殊数据类型:HyperLogLog(基数统计)、Bitmap(位图)、Geospatial (地理位置)。

2.1 Redis的五种基本数据类型

Redis 5 种基本数据类型对应底层数据结构:

StringListHashSetZset
SDSLinkedList/ZipList/QuickListDict、ZipListDict、IntsetZipList、SkipList
缓存 Session、Token、图片地址、序列化后的对象、计数、分布式锁最新文章、最新动态、消息队列用户信息、商品信息、文章信息、购物车信息网站 UV 统计、文章点赞、动态点赞、共同好友(交集)、共同粉丝(交集)、共同关注(交集)、好友推荐(差集)、音乐推荐(差集)、订阅号推荐(差集+交集)、抽奖系统、随机点名排行榜、优先级任务队列

2.2 Redis的三种特殊数据类型

Bitmap (位图)HyperLogLog(基数统计)Geospatial (地理位置)
用户签到情况、活跃用户情况、用户行为统计(比如是否点赞过某个视频)数据量巨大的计数场景:热门网站每日/每周/每月访问 ip 数统计、热门帖子 uv 统计需要管理使用地理空间数据的场景:附近的人

三、发现Redis热Key方案

3.1 使用 Redis 自带的 --hotkeys 参数来查找

Redis 4.0.3 版本中新增 hotkeys 参数,该参数能够返回所有 key 的被访问次数。但会增加 Redis 实例的 CPU 和内存消耗(全局扫描),因此需要谨慎使用。

使用该方案的前提条件是 Redis Server 的 maxmemory-policy 参数设置为 LFU 算法,不否则会报错:

Error: ERR An LFU maxmemory policy is not selected, access frequency not tracked. Please note that when switching between policies at runtime LRU and LFU data will take some time to adjust.

Redis 中有两种 LFU 算法:

  • volatile-lfu(least frequently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰。
  • allkeys-lfu(least frequently used):当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的 key。

配置文件 redis.conf 中的示例:

# 使用 volatile-lfu 策略
maxmemory-policy volatile-lfu# 或者使用 allkeys-lfu 策略
maxmemory-policy allkeys-lfu

3.2 使用MONITOR 命令

MONITOR 命令是 Redis 提供的一种实时查看 Redis 的所有操作的方式,可以用于临时监控 Redis 实例的操作情况,包括读写、删除等操作。

由于该命令对 Redis 性能的影响比较大,因此禁止长时间开启 MONITOR(生产环境中建议谨慎使用该命令)。

# redis-cli
127.0.0.1:6379> MONITOR
OK
1683638260.637378 [0 172.17.0.1:61516] "ping"
1683638267.144236 [0 172.17.0.1:61518] "smembers" "mySet"
1683638268.941863 [0 172.17.0.1:61518] "smembers" "mySet"
1683638269.551671 [0 172.17.0.1:61518] "smembers" "mySet"
1683638270.646256 [0 172.17.0.1:61516] "ping"
1683638270.849551 [0 172.17.0.1:61518] "smembers" "mySet"
1683638271.926945 [0 172.17.0.1:61518] "smembers" "mySet"
1683638274.276599 [0 172.17.0.1:61518] "smembers" "mySet2"
1683638276.327234 [0 172.17.0.1:61518] "smembers" "mySet"

可以选择在合适的时机短暂执行 MONITOR 命令并将输出重定向至文件,在关闭 MONITOR 命令后通过对文件中请求进行归类分析即可找出这段时间中的 hotkey。

3.3 借助开源项目

京东零售的 hotkey 这个项目不光支持 hotkey 的发现,还支持 hotkey 的处理。
在这里插入图片描述

四、解决 hotkey

  • 读写分离:主节点处理写请求,从节点处理读请求。
  • 使用 Redis Cluster:将热点数据分散存储在多个 Redis 节点上。
  • 二级缓存:hotkey 采用二级缓存的方式进行处理,将 hotkey 存放一份到 JVM 本地内存中(可以用 Caffeine)。

五、Redis 内存碎片

内存碎片可简单理解为不可用的空闲内存。
例如:操作系统为任务分配 32 字节的连续内存空间,而存储数据实际只需要使用 24 字节内存空间,那这多余出来的 8 字节内存空间如果后续没办法再被分配存储其他数据的话,就可以被称为内存碎片。
Redis 内存碎片虽然不会影响 Redis 性能,但是会增加内存消耗。

5.1 为何会有Redis 内存碎片

1、Redis 存储数据的时候向操作系统申请的内存空间可能会大于数据实际需要的存储空间。Redis官网表明:Redis 使用zmalloc方法(Redis自己实现的内存分配方法)进行内存分配的时候,除要分配 size 大小的内存之外,还会多分配 PREFIX_SIZE 大小的内存。
zmalloc 方法源码:

void *zmalloc(size_t size) {// 分配指定大小的内存void *ptr = malloc(size+PREFIX_SIZE);if (!ptr) zmalloc_oom_handler(size);
#ifdef HAVE_MALLOC_SIZEupdate_zmalloc_stat_alloc(zmalloc_size(ptr));return ptr;
#else*((size_t*)ptr) = size;update_zmalloc_stat_alloc(size+PREFIX_SIZE);return (char*)ptr+PREFIX_SIZE;
#endif
}

源码地址:https://github.com/antirez/redis-tools/blob/master/zmalloc.c
另外,Redis 可使用多种内存分配器来分配内存( libc、jemalloc、tcmalloc),默认使用 jemalloc,按照一系列固定的大小(8 字节、16 字节、32 字节……)来分配内存的。

当程序申请的内存大小最接近某个固定值时,jemalloc会给它分配相应大小的空间。
例如程序需要申请 17 字节的内存,jemalloc会直接给它分配 32 字节的内存,这样会导致有 15 字节内存的浪费。
实际jemalloc专门针对内存碎片问题做过优化,一般不会存在过度碎片化问题。

2、频繁修改Redis中的数据会产生内存碎片。
Redis官网表明:当Redis中的某个数据删除时,Redis通常不会轻易释放内存给操作系统。
在这里插入图片描述

文档地址:https://redis.io/topics/memory-optimization

5.2 查看Redis内存碎片信息

使用 info memory 命令即可查看 Redis 内存相关的信息。
Redis官方文档有详细的介绍:https://redis.io/commands/INFO 。
在这里插入图片描述
Redis 内存碎片率的计算公式:

mem_fragmentation_ratio= used_memory_rss / used_memory内存碎片率 = 操作系统实际分配给Redis的物理内存空间大小 / Redis内存分配器为存储数据实际申请使用的内存空间大小

内存碎片率的值越大代表内存碎片率越严重,那多大的内存碎片率才需要清理呢?
通常认为 mem_fragmentation_ratio > 1.5 就需要清理内存碎片。mem_fragmentation_ratio > 1.5 意味着使用Redis存储实际大小2G的数据需要使用大于3G的内存。
快速查看内存碎片率命令:

> redis-cli -p 6379 info | grep mem_fragmentation_ratio

而碎片率小于 1 时:

  • Redis 内存碎片率低并非只跟 SWAP 有关,生产环境通常建议禁用 SWAP。

  • 复制积压缓冲区配置较大、业务数据量较小的情况下极容易造成碎片率 远低于 1,这是正常现象,无需优化或调整。

  • 通常将线上环境复制缓冲区的值 repl-backlog-size 设置的比较大,目的是防止主库频繁出现全量复制而影响性能。

  • 随着业务数据量增长,Redis 内存碎片率比值会逐渐趋于 1。

5.3 清理 Redis 内存碎片

Redis4.0-RC3 版本以后自带内存整理,可以避免内存碎片率过大的问题。
直接通过 config set 命令将 activedefrag 配置项设置为 yes 即可。

config set activedefrag yes

具体清理时间需要通过两个参数控制:

# 内存碎片占用空间达到 500mb 的时候开始清理
config set active-defrag-ignore-bytes 500mb
# 内存碎片率大于 1.5 的时候开始清理
config set active-defrag-threshold-lower 50

通过 Redis 自动内存碎片清理机制可能会对 Redis 的性能产生影响,可通过两个参数来减少对 Redis 性能的影响:

# 内存碎片清理所占用 CPU 时间的比例不低于 20%
config set active-defrag-cycle-min 20
# 内存碎片清理所占用 CPU 时间的比例不高于 50%
config set active-defrag-cycle-max 50

另外,重启节点可以做到内存碎片重新整理。如果采用的是高可用架构的 Redis 集群的话,可将碎片率过高的主节点转换为从节点,以便进行安全重启。(我上月遇到过,手工清理效果不佳,最后是重启节点解决,还是重启大法好使~)

六、Redis缓存预热

  • 减少冷启动影响:当系统重启或新启动时,缓存是空的,这被称为冷启动。冷启动可能导致首次请求处理缓慢,因为数据需要从慢速存储(如数据库)检索。
  • 提高数据访问速度:通过预先加载常用数据到缓存中,可以确保数据快速可用,从而加快数据访问速度。
  • 平滑流量峰值:在流量高峰期之前预热缓存可以帮助系统更好地处理高流量,避免在流量激增时出现性能下降。
  • 保证数据的时效性:定期预热可以保证缓存中的数据是最新的,特别是对于高度依赖于实时数据的系统。
  • 减少对后端系统的压力:通过缓存预热,可减少对数据库或其他后端服务的直接查询,从而减轻负载。

6.1 预热工具

  • RedisBloom:RedisBloom 是 Redis 的一个模块,提供多个数据结构,包括布隆过滤器、计数器、和 TopK 数据结构等。其中,布隆过滤器可以用于 Redis 缓存预热,通过将预热数据添加到布隆过滤器中,可以快速判断一个键是否存在于缓存中
  • Redis Bulk loading:这是一个官方基于 Redis 协议批量写入数据的工具
  • Redis Desktop Manager:Redis Desktop Manager 是一个图形化的 Redis 客户端,可以用于管理 Redis 数据库和进行缓存预热。通过 Redis Desktop Manager,可以轻松地将预热数据批量导入到 Redis 缓存中。

6.2 启动预热

6.2.1 Spring Boot特定逻辑接口

Spring Boot用于在应用程序启动后执行特定逻辑的接口:CommandLineRunnerApplicationRunner。在SpringApplication的 run方法中其实就是 callRunners(context, applicationArguments); 的实现。

private void callRunners(ApplicationContext context, ApplicationArguments args) {List<Object> runners = new ArrayList<>();runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());AnnotationAwareOrderComparator.sort(runners);for (Object runner : new LinkedHashSet<>(runners)) {if (runner instanceof ApplicationRunner) {callRunner((ApplicationRunner) runner, args);}if (runner instanceof CommandLineRunner) {callRunner((CommandLineRunner) runner, args);}}
}

可以新建两个类来使用。
MyCommandLineRunner.java:

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;@Component
public class MyCommandLineRunner implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {// 在应用启动后执行缓存预热逻辑// ...}
}

MyApplicationRunner.java:

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;@Component
public class MyApplicationRunner implements ApplicationRunner {@Overridepublic void run(ApplicationArguments args) throws Exception {// 在应用启动后执行缓存预热逻辑// ...}
}

6.2.2 使用 InitializingBean 接口

实现 InitializingBean 接口,并在 afterPropertiesSet 方法中执行缓存预热的逻辑。这样Spring 在初始化 Bean 时会调用 afterPropertiesSet 方法。

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;@Component
public class CachePreloader implements InitializingBean {@Overridepublic void afterPropertiesSet() throws Exception {// 执行缓存预热逻辑// ...}
}

6.2.3 使用@PostConstruct 注解

使用 @PostConstruct 注解标注一个方法,该方法将在 Bean 的构造函数执行完毕后立即被调用。在这个方法中执行缓存预热的逻辑。

import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;@Component
public class CachePreloader {@PostConstructpublic void preloadCache() {// 执行缓存预热逻辑// ...}
}

6.2.4 定时任务预热

启动预热有个问题,就是一旦启动之后,如果需要预热新的数据,或者需要修改数据,就不支持,那在应用的运行过程中,可通过定时任务来实现缓存的更新预热。
通常依赖这种方式来确保缓存中的数据是最新的,避免因为业务数据的变化而导致缓存数据过时。

@Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
public void scheduledCachePreload() {// 执行缓存预热逻辑// ...
}

也可使用 xxl-job 等定时任务实现。

6.2.5 缓存器预热

有些缓存框架提供缓存加载器的机制,可在缓存中不存在数据时,自动调用加载器加载数据到缓存中。这样可以简化缓存预热的逻辑。而实际项目中也需要两级缓存增加效率,例如:我们项目中使用Caffeine实现:

import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import org.springframework.stereotype.Service;import java.util.concurrent.TimeUnit;@Service
public class MyCacheService {private final LoadingCache<String, String> cache;public MyCacheService() {this.cache = Caffeine.newBuilder().refreshAfterWrite(1, TimeUnit.MINUTES)  // 配置自动刷新,1分钟刷新一次.build(key -> loadDataFromSource(key));  // 使用加载器加载数据}public String getValue(String key) {return cache.get(key);}private String loadDataFromSource(String key) {// 从数据源加载数据的逻辑// 这里只是一个示例,实际应用中可能是从数据库、外部服务等获取数据System.out.println("Loading data for key: " + key);return "Value for " + key;}
}
  • 使用Caffeine.newBuilder().refreshAfterWrite(1, TimeUnit.MINUTES)配置缓存的自动刷新机制,即每个缓存项在写入后的 1 分钟内,如果有读请求,Caffeine 会自动触发数据的刷新。

  • loadDataFromSource 方法是用于加载数据的自定义方法。可在此方法中实现从数据源(例如数据库、外部服务)加载数据的逻辑。

相关文章:

Redis应用笔记

Redis应用笔记 一、 前言二、 Redis八种常用数据类型2.1 Redis的五种基本数据类型2.2 Redis的三种特殊数据类型 三、发现Redis热Key方案3.1 使用 Redis 自带的 --hotkeys 参数来查找3.2 使用MONITOR 命令3.3 借助开源项目 四、解决 hotkey五、Redis 内存碎片5.1 为何会有Redis …...

html实现好看的塔罗牌、十二星座运势网站源码

文章目录 1.设计来源1.1 十二星座1.2 所有界面效果图 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/deta…...

万字长文带你入门shell编程(超详细)

一、概述 Shell 是计算机操作系统中用户与操作系统内核之间的接口层&#xff0c;它提供了一种方式让用户能够通过命令行界面&#xff08;CLI&#xff09;与操作系统交互。Shell 可以被视为一个命令解释器&#xff0c;它接收用户输入的命令&#xff0c;解析这些命令&#xff0c…...

音质提升秘籍:专业音频剪辑软件汇总

现在欣赏传输音频文件比以前简单多了&#xff0c;这些音频的质量也影响了听众的体验与感受。所以使用一些靠谱的音频剪辑工具处理音频能让你的音频文件呈现更好的效果。 1.福昕音频剪辑 链接直达>>https://www.foxitsoftware.cn/audio-clip/ 这是一款电脑端软件。别看…...

idea配置

在我们使用idea的时候会进行配置主要就idea编译器的下载&#xff0c;maven资源管理器&#xff0c;Tomcat服务器 在IntelliJ IDEA的官网进入http://www.jetbrains.com/idea/ 如图如果你是大学生的话一般学校会有相关的激活码直接选择左边的.exe文件下载&#xff0c;直接的就是企…...

将 WinForms 中的 Panel 替换为 WPF 的 WindowsFormsHost 元素

要将 WinForms 中的 Panel 替换为 WPF 的 WindowsFormsHost 元素&#xff0c;你需要执行以下步骤&#xff1a;1. 添加对 WindowsFormsIntegration 的引用&#xff1a;确保你的项目引用了 WindowsFormsIntegration 和 PresentationCore、PresentationFramework 程序集&#xff0…...

C++ ---- vector的底层原理剖析及其实现

vector 一、定义二、常用接口及模拟实现三、vector迭代器失效问题四、使用memcpy拷贝会出现的问题五、二维数组vector<vector< T >> vv 一、定义 vector 是 C 标准模板库&#xff08;Standard Template Library, STL&#xff09;中的一个非常有用的容器。它是一个…...

跑酷视频素材去哪里下载?哪里有跑酷游戏视频素材?

在这个快节奏的视觉时代&#xff0c;跑酷视频因其惊险和动感吸引了众多动作爱好者和视频创作者的目光。如果您正在寻找高质量的跑酷视频素材来丰富您的项目&#xff0c;无论是增强视频的视觉冲击力还是展现跑酷运动的魅力&#xff0c;以下几个推荐的网站将是您的理想选择。 蛙…...

Centos 7配置问题

在VMWare12上面安装Centos 7 Linux虚拟机&#xff0c;在切换到命令界面时&#xff0c;需要登录用户名和密码&#xff0c;但发现输入用户后有字符显示&#xff0c;但是密码没有。 经过一系列查看后&#xff0c;发现这个是Linux的一种机制&#xff0c;即当你输入密码时不显示&…...

浮动IP(Floating IP)计费;OpenStack算力共享;OpenStack实现资源虚拟化;算力调度策略

目录 浮动IP(Floating IP)计费 浮动IP的定义与作用 计费中的浮动IP数据 浮动IP在计费中的作用 OpenStack算力共享 一、OpenStack在算力共享中的角色 二、OpenStack与算力共享的结合方式 三、实际应用案例 算力调度策略 算力计费策略 OpenStack实现资源虚拟化 1.虚…...

Android 源码单独编译Settings模块

一般我们编译源码,只需要在源码的根目录下执行三个命令就行 . build/envsetup.sh 或者source build/envsetup.sh lunch 选择编译目标 make -j60make 不带参数的编译方式是直接编译整个系统,我们也可以使用make带模块名或者使用mmm等命令单独编译某个模块。 首先找到对应模块…...

虚拟机类加载机制

与那些编译时需要进行连接的语言不同&#xff0c;在java语言中&#xff0c;类型的 动态加载&#xff1a;编写一个面向接口的应用程序&#xff0c;可以等到运行时再指定其实现类。 类加载&#xff1a;加载-连接-初始化-使用-卸载 一个类被调用时&#xff0c;会将其class文件从…...

Google Earth Engine(GEE)——逐月筛选影像,并给影像集合添加新的属性

简介 导入影像集合首先,您需要导入您要筛选的影像集合。使用Google Earth Engine的ImageCollection类来导入影像集合。您可以通过ee.ImageCollection()函数传递影像集合的ID或通过一个ee.ImageCollection()对象导入影像集合。 例如,导入Landsat 8卫星每月影像集合的代码如下…...

如何从智联招聘网站快速抓取职位详情?两大技巧揭秘

摘要&#xff1a; 本文将揭秘如何利用Python爬虫技术&#xff0c;高效且合法地从智联招聘网站抓取职位详情信息。通过实战示例&#xff0c;展现两大核心技巧&#xff0c;助你在大数据时代抢占先机&#xff0c;为你的市场分析、人才研究提供强大支持。 一、引言&#xff1a;数据…...

C#知识|ini文件操作

哈喽,你好啊,我是雷工! 本节学习ini文件的操作,之前练习过通过ini文件导出采集模块的配置信息,然后再另一个模块中导入配置信息,如此实现快速配置采集模块,提高效率。 以下为学习笔记。 01 认识ini文件 ini文件是一种文件格式,类似txt,xml等, ini文件在上位机开发中使…...

Linux系统学习之路

一、Linux基础训练 https://mp.weixin.qq.com/mp/appmsgalbum?actiongetalbum&__bizMzUxNjMwMzk4MQ&scene1&album_id3544800080551952390&count3#wechat_redirect...

DNS介绍与部署-Day 01

1. 什么是DNS DNS&#xff08;Domain Name System&#xff09;域名系统&#xff0c;是一种采用客户端/服务器机制&#xff0c;负责实现计算机名称与IP地址转换的系统。DNS作为一种重要的网络服务&#xff0c;既是Internet工作的基础&#xff0c;同时在企业内部网络中也得到了广…...

python 图片爬虫记录

感谢大家的点赞。再补充一点。 对于这个 url https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEqB5nighYsMZE7kexaVNJfxy3OkRutNEKatksw9u5f-ckHNROLzFyx2Uty3zYWNEaeOmzsljGr3eARiDWaM9DM8G2hPuPf8uZP0NO3kNUCnM2Cjb3ZKtLhJDBwqeR4ElpJ7ID5_wIHGQ/s200 这个url最…...

本地安装Llama3.1与LobeChat可视化UI界面并实现远程访问大模型实战

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

MSF回弹木马在Ubuntu中测试

1.创建文件 网站地址为192.168.30.129 首先在Ubuntu中use/local/nginx/sbin路径下创建一个PHP文件&#xff1b; 如图所示&#xff1a; 然后进入网页下载PHP文件如图所示&#xff1a; 什么都不显示说明这个没有问题就怕访问失败。 2.使用蚂键连接网站 在蚂键中的URL地址栏中…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

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

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

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...