Redis速学

一、介绍Redis

基本概念和特点

Redis是一个开源的内存数据库,它主要用于数据缓存和持久化。其数据存储在内存中,这使得它具有非常快的读写速度。Redis支持多种数据结构,包括字符串、哈希、列表、集合和有序集合,这使得它非常灵活,能够适应各种不同的数据处理需求。此外,Redis也支持数据持久化,可以将数据保存到磁盘上,确保数据不会因服务器重启而丢失。

优势和适用场景

Redis的优势在于快速、灵活、丰富的数据结构和持久化功能。适用场景包括但不限于:

  • 数据缓存:用于加速对数据库或外部API的访问,减轻后端系统压力。
  • 会话缓存:用于存储用户会话信息,提高网站性能和扩展性。
  • 消息队列:实现发布/订阅模式,处理异步任务和事件驱动架构。
  • 实时分析:存储和处理实时数据,如统计数据、计数器等。
  • 计数器和排行榜:用于实时计数和排名功能。

演示安装和配置Redis

演示如何安装和配置Redis可以涉及以下步骤:

  1. 下载和安装Redis软件包
  2. 配置Redis实例,包括端口设置、内存限制、持久化选项等
  3. 启动Redis服务器
  4. 使用命令行工具连接到Redis并执行一些基本操作,如设置键值对、操作数据结构等。

二、Redis数据结构及其适用场景

字符串

  • 设置字符串:使用命令 SET key value,例如 SET user:1000:name "Alice"
  • 获取字符串:使用命令 GET key,例如 GET user:1000:name
  • 删除字符串:使用命令 DEL key,例如 DEL user:1000:name
  • 适用场景:用于缓存用户会话信息、存储临时数据等。

哈希

  • 添加哈希字段:使用命令 HSET key field value,例如 HSET user:1000 age 30
  • 获取哈希字段:使用命令 HGET key field,例如 HGET user:1000 age
  • 删除哈希字段:使用命令 HDEL key field,例如 HDEL user:1000 age
  • 适用场景:存储用户信息、对象属性,如用户资料、商品信息等。

列表

  • 在列表头部插入元素:使用命令 LPUSH key value,例如 LPUSH news:latest "New article"
  • 在列表尾部插入元素:使用命令 RPUSH key value,例如 RPUSH news:latest "Another article"
  • 删除列表元素:使用命令 LPOP keyRPOP key,例如 LPOP news:latest
  • 适用场景:消息队列、新闻推送、最新动态等。

集合

  • 添加集合元素:使用命令 SADD key member,例如 SADD tags:redis "database"
  • 获取集合元素:使用命令 SMEMBERS key,例如 SMEMBERS tags:redis
  • 删除集合元素:使用命令 SREM key member,例如 SREM tags:redis "database"
  • 适用场景:标签系统、唯一值管理、好友列表等。

有序集合

  • 添加有序集合元素:使用命令 ZADD key score member,例如 ZADD leaderboard 1000 "PlayerA"
  • 获取有序集合元素:使用命令 ZRANGE key start stop,例如 ZRANGE leaderboard 0 9
  • 删除有序集合元素:使用命令 ZREM key member,例如 ZREM leaderboard "PlayerA"
  • 适用场景:排行榜、范围查询、按分数排序的数据存储。

三、Redis持久化

Redis提供了两种持久化方式:快照(snapshot)和日志(journal)持久化。这些机制可以确保在Redis服务器重启时数据不会丢失。

1. 快照持久化

快照持久化通过将当前数据集的副本写入磁盘来实现持久化。Redis会周期性地将数据集快照写入磁盘。当Redis重启时,可以通过加载最近的快照来恢复数据。

配置快照持久化

在Redis配置文件中,可以通过以下设置配置快照持久化:

save 900 1     # 在900秒(15分钟)内,如果至少有1个键被修改,则保存快照
save 300 10    # 在300秒(5分钟)内,如果至少有10个键被修改,则保存快照
save 60 10000  # 在60秒内,如果至少有10000个键被修改,则保存快照

上述配置表示了在不同时间段内触发快照保存的条件。可以根据实际情况调整这些设置。

2. 日志持久化

日志持久化(也称为AOF持久化)记录了服务器接收到的所有写操作命令,以此来重放这些命令来恢复原始数据集。AOF持久化可以确保更高的数据安全性,但通常会占用更多的磁盘空间。

配置日志持久化

在Redis配置文件中,可以通过以下设置启用AOF持久化:

appendonly yes     # 启用AOF持久化

还可以设置AOF持久化的文件名和重写策略等参数。

管理持久化功能

除了配置文件之外,可以使用Redis的命令行工具或者客户端连接来管理持久化功能。例如,可以手动触发快照保存或者AOF重写。

  • 手动触发快照保存:使用 SAVE 命令或 BGSAVE 命令。
  • 手动触发AOF重写:使用 BGREWRITEAOF 命令。

通过了解和配置Redis的持久化功能,可以确保数据在重启或者故障恢复时不会丢失,并且可以根据需求来调整持久化机制以平衡数据安全和性能。

四、Redis高级特性

1. 发布/订阅功能

Redis的发布/订阅功能允许客户端订阅频道并接收发布到该频道的消息。这种模式使得多个客户端可以订阅感兴趣的频道并接收相关信息,从而构建实时通信和消息传递系统。

使用发布/订阅功能

  • 订阅频道:客户端可以使用 SUBSCRIBE 命令来订阅一个或多个频道,以接收相关消息。
    SUBSCRIBE channel
    
  • 发布消息:客户端可以使用 PUBLISH 命令向指定的频道发布消息。
    PUBLISH channel message
    

2. 事务支持

Redis的事务支持通过 MULTIEXECDISCARDWATCH 等命令来实现。这使得客户端可以将多个命令打包成一个事务,然后一次性、原子性地执行这些命令。

使用事务

  • 开启事务:使用 MULTI 命令来开启一个事务块。
  • 添加命令:在事务块内,添加要执行的命令。
  • 执行事务:使用 EXEC 命令来执行事务中的所有命令,或者使用 DISCARD 命令来取消事务。
  • 监视键:使用 WATCH 命令来监视一个或多个键,如果在事务执行过程中这些键被修改,则事务将被取消。

3. 构建高级应用

这些高级特性可以用于构建诸如实时消息系统、事务性操作和分布式锁等高级应用程序。例如,可以使用发布/订阅功能构建实时聊天应用,使用事务来确保多个命令的原子性执行,或者使用WATCH来实现分布式锁的功能。

(1)实时消息系统

利用Redis的发布/订阅功能,可以构建实时消息系统。例如,假设我们有一个在线聊天应用,用户可以订阅属于他们的聊天频道,当其他用户发送消息时,消息将被发布到相应的频道,而订阅该频道的用户将实时接收到消息。这种模式可以实现实时通信,例如即时聊天和实时通知等功能。

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;public class RealTimeMessagingSystem {public static void main(String[] args) {// 订阅者new Thread(() -> {Jedis jedis = new Jedis("localhost");jedis.subscribe(new JedisPubSub() {@Overridepublic void onMessage(String channel, String message) {System.out.println("Received message: " + message + " from channel: " + channel);}}, "real-time-channel");jedis.close();}).start();// 发布者new Thread(() -> {Jedis jedis = new Jedis("localhost");try {Thread.sleep(1000); // 等待订阅者准备好jedis.publish("real-time-channel", "Hello, Redis!");} catch (InterruptedException e) {e.printStackTrace();} finally {jedis.close();}}).start();}
}

(2) 事务性操作

Redis的事务支持可以用于执行一系列命令,要么全部执行,要么全部不执行,具有原子性。这在需要确保多个命令按照特定顺序执行或者一起执行时非常有用。举例来说,假设我们需要在银行应用中从一个账户转账到另一个账户。我们可以使用Redis的事务性操作来确保扣款和存款两个操作要么同时成功,要么同时失败,从而避免出现数据不一致的情况。Redis 事务可以通过 MULTI、EXEC、DISCARD 和 WATCH 命令来实现。事务保证了一系列命令的原子性执行。

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;public class TransactionalOperations {public static void main(String[] args) {Jedis jedis = new Jedis("localhost");// 开始事务Transaction t = jedis.multi();try {t.set("foo", "bar");t.set("hello", "world");// 执行事务t.exec();} catch (Exception e) {// 如果出现异常,放弃事务t.discard();} finally {jedis.close();}}
}

(3)分布式锁

Redis的原子性操作和分布式特性使其成为构建分布式锁的理想选择。通过利用Redis的SETNX命令(SET if Not eXists),可以在分布式环境中实现互斥锁。这在需要确保某个操作在分布式系统中只能被一个实例执行时非常有用,比如控制对共享资源的访问。

分布式系统是由多台计算机组成的系统,这些计算机通过网络相互连接并协同工作,以完成共同的任务和目标。在分布式系统中,各个计算机节点可以独立运行,并通过消息传递或共享状态来协调彼此的行为,从而实现更大规模的计算和处理能力。
关键特点包括:

  1. 并行处理: 分布式系统能够并行处理任务,通过将任务分配给不同的节点,从而提高整体系统的处理能力和性能。
  2. 容错性: 分布式系统通常具有一定的容错能力,即使某个节点出现故障,系统仍然能够继续运行。
  3. 可伸缩性: 分布式系统通常具有良好的可伸缩性,可以通过增加节点来扩展系统的处理能力。
  4. 资源共享: 分布式系统中的节点可以共享资源(如存储、计算资源等),从而实现更高效的资源利用。
  5. 分布式存储: 分布式系统通常具有分布式存储的能力,可以将数据分布存储在不同的节点上,以实现更高的数据可靠性和容量。

分布式锁是一种用于在分布式系统中实现互斥访问的技术。在分布式系统中,多个节点可能需要同时访问共享资源或执行某个关键操作,因此需要一种机制来确保在任意时刻只有一个节点能够访问该资源或执行该操作,以避免数据不一致或竞争条件的发生。
分布式锁通常用于以下场景:

  1. 避免资源冲突: 当多个节点需要访问共享资源(如数据库、文件、缓存等)时,分布式锁可以确保同一时刻只有一个节点能够访问该资源,从而避免冲突和数据不一致。
  2. 防止重复操作: 在某些情况下,需要确保某个操作只能被执行一次,分布式锁可以用来保证该操作在分布式系统中的幂等性。

常见的实现分布式锁的方式包括利用分布式存储系统(如Redis、ZooKeeper等)来协调各个节点之间的锁状态,以及利用乐观锁和悲观锁等技术来实现分布式环境下的互斥访问。

SETNX 是 Redis 中的一条命令,用于设置一个键的值,当且仅当该键不存在时。SETNX 是 “SET if Not eXists” 的缩写。

其语法为:

SETNX key value

其中 key 是要设置的键,value 是要设置的值。

如果 key 不存在,则会将 key 设置为 value,并返回 1,表示设置成功。如果 key 已经存在,则不做任何操作,返回 0,表示设置失败。

这个命令通常用于实现分布式锁,因为它可以确保只有一个客户端能够成功地设置某个键,从而实现互斥操作。

import redis.clients.jedis.Jedis;public class DistributedLock {public static void main(String[] args) {Jedis jedis = new Jedis("localhost");// 尝试获取锁String lockKey = "lock:key";long acquired = jedis.setnx(lockKey, String.valueOf(System.currentTimeMillis()));if (acquired == 1) {try {// 锁的业务逻辑System.out.println("Lock acquired!");// ...} finally {// 释放锁jedis.del(lockKey);}} else {System.out.println("Could not acquire lock!");}jedis.close();}
}

在这个分布式锁的例子中,我们使用 setnx 命令尝试设置一个锁。如果返回值是 1,表示我们成功获取了锁。在锁的业务逻辑执行完毕后,我们通过删除键来释放锁。如果返回值不是 1,表示锁已经被其他进程持有。

请注意,这个分布式锁的实现是最基本的,它没有处理锁的超时问题。在实际应用中,你可能需要使用更复杂的模式,比如 Redlock 算法,或者使用 Redisson 这样的库,它提供了更加健壮的分布式锁实现。

五、Redis在实际应用中的使用

首先,确保Java 项目中包含了 Redis 客户端库,比如 Jedis。可以通过 Maven 或者 Gradle 将其添加到你的项目依赖中。

Maven 依赖示例

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>最新版本</version>
</dependency>

Redis作为缓存系统的最佳实践

Redis 作为缓存系统的最佳实践包括以下方面:

  1. 缓存热点数据:将经常访问的数据缓存在 Redis 中,以减轻后端数据库的压力,提高数据访问速度。

  2. 选择合适的数据结构:根据实际需求选择合适的数据结构,如字符串、哈希、列表、集合、有序集合等,以最大程度地发挥 Redis 的性能优势。

  3. 设置合理的过期时间:对于缓存的数据,根据数据的更新频率和重要性,设置合理的过期时间,避免缓存数据过期而导致的数据不一致性。

  4. 使用预热机制:在系统启动或重启时,通过预热机制将热点数据加载到缓存中,避免大量请求直接打到后端数据库。

  5. 实现缓存穿透保护:采用布隆过滤器或在缓存中存储空对象等方式,防止缓存穿透,即针对不存在的数据频繁请求导致的直接访问后端数据库。

  6. 考虑高可用和扩展性:使用 Redis 的主从复制和集群功能,确保缓存系统的高可用性和扩展性。

import redis.clients.jedis.Jedis;public class RedisCacheExample {public static void main(String[] args) {// 连接到 RedisJedis jedis = new Jedis("localhost", 6379);// 假设我们要缓存用户的个人资料String userKey = "user:12345";jedis.hset(userKey, "name", "Alice");jedis.hset(userKey, "age", "30");jedis.hset(userKey, "email", "alice@example.com");// 设置缓存过期时间为 1 小时jedis.expire(userKey, 3600);// 从缓存中获取用户的个人资料System.out.println(jedis.hgetAll(userKey));// 模拟缓存过期try {Thread.sleep(3601 * 1000); // 注意 Java 中的 sleep 方法接受的是毫秒} catch (InterruptedException e) {e.printStackTrace();}System.out.println(jedis.hgetAll(userKey)); // 这将显示一个空的 Map,因为缓存已经过期// 关闭连接jedis.close();}
}

将Redis用作消息中间件,实现队列和发布/订阅模式

  1. 队列:Redis 的列表数据结构非常适合用作队列。通过 LPUSHRPOP 命令,可以将消息推入队列并从队列中弹出消息。这种方式可以实现简单的任务队列,用于异步处理任务或消息传递。

  2. 发布/订阅模式:Redis 支持发布/订阅模式,可以通过 PUBLISH 命令发布消息,而订阅者可以通过 SUBSCRIBE 命令订阅指定的频道,从而接收发布者发送的消息。这种模式非常适合实现实时消息推送、事件通知等功能。

  3. 保证消息可靠性:在使用 Redis 作为消息中间件时,需要考虑消息的可靠性。可以通过持久化机制、ACK 确认机制等方式来确保消息的可靠性传递。

  4. 消息过期和重试机制:针对消息的过期处理和重试机制,可以在应用层面或者使用 Redis 提供的过期设置来处理。

  5. 扩展性和负载均衡:使用 Redis 集群或者主从复制机制,可以实现消息中间件的扩展和负载均衡,确保系统的稳定性和性能。

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;public class RedisPubSubExample {public static void main(String[] args) {// 启动订阅者线程Thread subscriberThread = new Thread(() -> {Jedis jedis = new Jedis("localhost", 6379);jedis.subscribe(new JedisPubSub() {@Overridepublic void onMessage(String channel, String message) {System.out.println("Received: " + message);}}, "channel");jedis.close();});subscriberThread.start();// 启动发布者线程Thread publisherThread = new Thread(() -> {Jedis jedis = new Jedis("localhost", 6379);try {while (true) {jedis.publish("channel", "some message");Thread.sleep(1000);}} catch (InterruptedException e) {e.printStackTrace();} finally {jedis.close();}});publisherThread.start();}
}

综上所述,Redis 作为消息中间件可以提供可靠的消息传递和发布/订阅功能,同时作为队列系统可以支持异步任务处理和消息传递,为实际应用提供了灵活而强大的功能支持。

六、性能优化和故障排除

  • 分析Redis的性能优化策略,包括内存管理和命令优化
  • 演示如何排除常见的Redis故障和性能问题

Redis 的性能优化通常涉及内存管理、命令优化、配置调整和故障排除。以下是一些关键策略和示例:

内存管理

使用合适的数据类型:选择正确的数据类型可以大幅节省内存。例如,使用哈希类型存储对象而不是字符串类型。

  1. 内存淘汰策略:当内存使用接近限制时,Redis 提供了多种淘汰策略,如 volatile-lru、allkeys-lru、volatile-ttl 等。根据你的应用场景选择合适的策略。

  2. 内存优化配置:使用 maxmemory 配置项来设置 Redis 最大内存使用量,超过这个限制时将触发淘汰策略。

命令优化

  1. 避免大键操作:大键操作可能会阻塞 Redis,使用 SCAN 命令代替 KEYS,使用 HSCAN、SSCAN、ZSCAN 来迭代大集合。

  2. 批量操作:使用 MGET、MSET 或 pipeline 来减少网络往返次数。

  3. Lua 脚本:使用 Lua 脚本可以将多个命令封装在服务器端执行,减少网络延迟。

配置调整

  1. 持久化策略:根据需要选择 RDB 快照、AOF 日志或两者结合。调整 save 配置和 appendfsync 选项以平衡性能和数据安全。

  2. 复制和分片:通过主从复制提高数据的可用性。使用 Redis 集群或分片来分散负载。

故障排除和性能问题

  1. 监控:使用 INFO 命令或 Redis 监控工具来跟踪性能指标。

  2. 慢查询日志:检查 SLOWLOG 获取执行缓慢的命令。

  3. 配置优化:调整 tcp-keepalive、timeout、tcp-backlog 等网络相关配置。

  4. 硬件升级:如果性能瓶颈是由硬件限制,可能需要升级 CPU、内存或使用更快的存储。

下面是一些 Java 代码示例,演示如何使用 Jedis 客户端来执行上述操作:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;public class RedisOptimizationExample {public static void main(String[] args) {Jedis jedis = new Jedis("localhost");// 使用 SCAN 命令代替 KEYSString cursor = "0";ScanParams scanParams = new ScanParams().count(100);do {ScanResult<String> scanResult = jedis.scan(cursor, scanParams);cursor = scanResult.getCursor();scanResult.getResult().forEach(key -> {// 处理每个键System.out.println(key);});} while (!cursor.equals("0"));// 检查慢查询日志System.out.println("Slowlog: " + jedis.slowlogGet());// 获取内存使用信息System.out.println("Memory Info: " + jedis.info("memory"));// 获取配置参数System.out.println("Config maxmemory: " + jedis.configGet("maxmemory"));// 设置内存淘汰策略为 volatile-lrujedis.configSet("maxmemory-policy", "volatile-lru");

故障排除

  1. 内存问题:如果 Redis 实例消耗内存过多,可以通过 INFO memory 命令查看内存使用详情。如果发现特定类型的键占用了过多内存,可能需要优化这些键的使用或数据结构。

  2. CPU 使用率高:高 CPU 使用率通常意味着 Redis 正在处理大量的请求或执行复杂的命令。可以通过 INFO CPU 查看 CPU 统计信息。如果 CPU 使用率持续高,可能需要优化命令或考虑增加更多的 Redis 实例进行负载均衡。

  3. 磁盘 I/O 问题:如果使用 AOF 持久化,磁盘 I/O 可能成为瓶颈。可以通过调整 appendfsync 配置项来优化。例如,设置为 everysec 可以平衡性能和数据安全。

  4. 网络瓶颈:如果 Redis 实例和客户端之间的网络延迟高,可以考虑将 Redis 实例移动到离客户端更近的位置,或者优化网络配置。

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;public class RedisTroubleshootingExample {public static void main(String[] args) {// 创建 JedisPool 来管理连接JedisPoolConfig poolConfig = new JedisPoolConfig();poolConfig.setMaxTotal(128); // 设置最大连接数JedisPool jedisPool = new JedisPool(poolConfig, "localhost");try (Jedis jedis = jedisPool.getResource()) {// 获取内存使用信息String memoryInfo = jedis.info("memory");System.out.println("Memory Info: " + memoryInfo);// 获取 CPU 使用信息String cpuInfo = jedis.info("cpu");System.out.println("CPU Info: " + cpuInfo);// 获取并设置慢查询日志的阈值String slowlogMaxLen = jedis.configGet("slowlog-max-len").get(1);System.out.println("Current slowlog-max-len: " + slowlogMaxLen);jedis.configSet("slowlog-max-len", "128");// 获取慢查询日志System.out.println("Slowlog: " + jedis.slowlogGet());// 检查网络延迟System.out.println("Ping: " + jedis.ping());}// 关闭连接池jedisPool.close();}
}

在这个示例中,我们使用了 JedisPool 来管理 Redis 连接,这是生产环境中推荐的做法,因为它可以重用连接,减少连接建立和销毁的开销。我们还展示了如何获取内存和 CPU 的使用信息,如何配置和检查慢查询日志,以及如何检查网络延迟。

请注意,这些代码示例仅用于演示如何使用 Jedis 客户端来获取 Redis 的性能信息和进行一些基本的配置。在实际的生产环境中,你可能需要结合监控工具和日志分析工具来进行更深入的性能分析和故障。

补充文档:

  1. GeekHour的一小时课程笔记 PDF
  2. 黑马新出的微服务课程-Redis面试篇:https://b11et3un53m.feishu.cn/wiki/Jck7w4GBSia4sukQn1vc9s3anMf

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/711999.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

书生·浦语大模型图文对话Demo搭建

前言 本节我们先来搭建几个Demo来感受一下书生浦语大模型 InternLM-Chat-7B 智能对话 Demo 我们将使用 InternStudio 中的 A100(1/4) 机器和 InternLM-Chat-7B 模型部署一个智能对话 Demo 环境准备 在 InternStudio 平台中选择 A100(1/4) 的配置&#xff0c;如下图所示镜像…

微店商品详情 API 支持哪些商品信息的获取?

微店&#xff08;Weidian&#xff09;并没有一个公开的、官方维护的API文档来供开发者使用。这意味着&#xff0c;如果你想要获取微店商品详情或其他相关信息&#xff0c;你通常需要通过微店官方提供的方式来实现&#xff0c;例如使用其开放平台、官方SDK或联系微店的技术支持获…

Spring常见面试题知识点总结(三)

7. Spring MVC&#xff1a; MVC架构的概念。 MVC&#xff08;Model-View-Controller&#xff09;是一种软件设计模式&#xff0c;旨在将应用程序分为三个主要组成部分&#xff0c;以实现更好的代码组织、可维护性和可扩展性。每个组件有着不同的职责&#xff0c;相互之间解耦…

11.Prometheus常见PromeQL表达式

平凡也就两个字: 懒和惰; 成功也就两个字: 苦和勤; 优秀也就两个字: 你和我。 跟着我从0学习JAVA、spring全家桶和linux运维等知识&#xff0c;带你从懵懂少年走向人生巅峰&#xff0c;迎娶白富美&#xff01; 关注微信公众号【 IT特靠谱 】&#xff0c;每天都会分享技术心得~ …

YOLO算法

YOLO介绍 YOLO&#xff0c;全称为You Only Look Once: Unified, Real-Time Object Detection&#xff0c;是一种实时目标检测算法。目标检测是计算机视觉领域的一个重要任务&#xff0c;它不仅需要识别图像中的物体类别&#xff0c;还需要确定它们的位置。与分类任务只关注对…

【矩阵】【方向】【素数】3044 出现频率最高的素数

作者推荐 动态规划的时间复杂度优化 本文涉及知识点 素数 矩阵 方向 LeetCode 3044 出现频率最高的素数 给你一个大小为 m x n 、下标从 0 开始的二维矩阵 mat 。在每个单元格&#xff0c;你可以按以下方式生成数字&#xff1a; 最多有 8 条路径可以选择&#xff1a;东&am…

安装 Ubuntu 22.04.3 和 docker

文章目录 一、安装 Ubuntu 22.04.31. 简介2. 下载地址3. 系统安装4. 系统配置 二、安装 Docker1. 安装 docker2. 安装 docker compose3. 配置 docker 一、安装 Ubuntu 22.04.3 1. 简介 Ubuntu 22.04.3 是Linux操作系统的一个版本。LTS 版本支持周期到2032年。 系统要求双核 C…

C++的模板template

一、什么是模板 C中的模板分为类模板和函数模板&#xff0c;并不是一个实际的类或函数&#xff0c;这指的是编译器不会自动为其生成具体的可执行代码。只有在具体执行时&#xff0c;编译器才帮助其实例化。 二、为什么引入模板 拿我们最常见的交换函数来举例子&#xff0c;如果…

代码随想录 二叉树第二周

目录 101.对称二叉树 100.相同的树 572.另一棵树的子树 104.二叉树的最大深度 559.N叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数 110.平衡二叉树 257.二叉树的所有路径 101.对称二叉树 101. 对称二叉树 已解答 简单 相关标签 相关企业 给你一…

《求生之路2》服务器如何选择合适的内存和CPU核心数,以避免丢包和延迟高?

根据求生之路2服务器的实际案例分析选择合适的内存和CPU核心数以避免丢包和延迟高的问题&#xff0c;首先需要考虑游戏的类型和对服务器配置的具体要求。《求生之路2》作为一款多人在线射击游戏&#xff0c;其服务器和网络优化对于玩家体验至关重要。 首先&#xff0c;考虑到游…

Java应用程序注册成Linux系统服务后,关闭Java应用程序打印系统日志

Java应用程序有自己的日志框架&#xff0c;有指定位置的日志文件&#xff0c;不需要在系统日志里记录&#xff0c;占用磁盘空间。 1.Linux系统文件目录 /etc/systemd/system/ 找到要修改的Java应用程序服务配置 比如bis-wz-80.service 2.设置不打印日志 StandardOutputnull S…

centos7 搭建 harbor 私有仓库

一、下载安装 1.1、harbor 可以直接从 github 上下载&#xff1a;Releases goharbor/harbor GitHub 这里选择 v2.10.0 的版本 wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz 1.2、解压 tar zxvf harbor-offlin…

L2 网络 Mint Blockchain 正式对外发布测试网

Mint Blockchain 是由 NFTScan Labs 发起的聚焦在 NFT 生态的 L2 网络&#xff0c;致力于促进 NFT 资产协议标准的创新和 NFT 在现实商业应用场景中的大规模采用。 Mint Blockchain 于 2024 年 2 月 28 号正式对外发布测试网&#xff0c;开始全面进入生态开发者测试开发阶段。 …

2403C++,C++11玩转无栈协程

原文 C11里也能玩无栈协程了? 答案是:可以! 事实上异网在很早时,C11里就可用无栈协程写异步代码了,只不过用起来不太方便,来看看C11里怎么用异网无栈协程写一个回音服务器的吧. #包含 <异网.h> #包含 <内存> #包含 <向量> #包含 <异网/产生.h> 用 …

c++异常机制(5)-- 继承与异常

我们在c异常机制(3)中自定义类型&#xff0c;我们将相应的异常封装成了类&#xff0c;在类中实现一些方法&#xff0c;对异常进行处理。其中每一个类都实现了print()方法。 我们使用throw抛出相应异常的虚拟对象&#xff0c;在catch参数中进行匹配&#xff0c;但是如果有很多异…

Springboot项目集成短信验证码(超简单)

操作流程 注册验证码平台创建验证码模版开始集成&#xff08;无需引入第三方库&#xff09; 注册并登陆中昱维信验证码平台 获取AppID和AppKey。 创建验证码模版 创建验证码模版&#xff0c;获取验证码模版id 开始集成 创建controller import org.springframework.web.bi…

MATLAB环境下基于随机游走拉普拉斯算子的快速谱聚类方法

古人有云&#xff0c;物以类聚&#xff0c;在面临信息爆炸问题的今天&#xff0c;对信息类别划分的价值日益显现&#xff0c;并逐步成为学者们的研究热点。分类和聚类是数据挖掘的重要工具&#xff0c;是实现事物类别划分的左右手&#xff0c;聚类又是分类一种特殊的方式。所谓…

CodeWhisperer安装教导--一步到位!以及本人使用Whisperer的初体验。

CodeWhisperer是亚马逊出品的一款基于机器学习的通用代码生成器&#xff0c;可实时提供代码建议。类似 Cursor 和Github AWS CodeWhisperer 亚马逊科技的CodeWhisperer是Amazon于2021年12月推出的一款代码补全工具&#xff0c;与GitHub Copilot类似。主要的功能有:代码补全注释…

猫毛过敏养猫人士的必备养猫好物-宠物空气净化器品牌分享

许多猫奴在与猫相处一段时间后突然对猫毛过敏&#xff0c;这真是令人难受。一些人认为对猫咪过敏是因为它们在空气中飘浮的毛发引起的&#xff0c;但实际上大部分人之所以过敏是因为对猫身上一种微小的蛋白质过敏。这种导致过敏的蛋白质附着在猫咪的一些皮屑上。我们都知道猫咪…

前端架构: 脚手架通用框架封装之入口文件开发(教程一)

脚手架入口文件开发 创建脚手架项目: abc-cli $ mkdir abc-cli && cd abc-cli 全局安装 lerna, $ npm i -g lerna 基于 lerna 完成项目初始化 $ lerna init 基于 lerna 创建脚手架 cli $ lerna create cli一路回车 好现在生成了一个 cli 的模板&#xff0c;目前需要…