【C#与Redis】--高级主题--Redis 管道

一、引言

1.1 概念介绍

Redis管道是一种用于优化多个命令执行的机制,允许客户端将多个命令一次性发送给服务器,然后一次性接收所有命令的返回结果。这种机制可以减少客户端与服务器之间的网络往返次数,从而提高性能。

1.2 作用
  1. 提高性能: 管道的主要作用是提高性能和吞吐量。通过将多个命令打包在一个请求中发送给服务器,可以减少网络延迟和通信开销,从而加速数据传输和处理。
  2. 减少网络往返次数: 在非管道模式下,每个命令都需要等待上一个命令的响应后才能发送下一个命令,而管道允许一次性发送多个命令,一次性获取多个命令的响应,减少了网络往返的次数。
  3. 原子性操作: 管道中的多个命令被视为一个原子操作,它们要么全部成功执行,要么全部失败,确保了一致性。
1.3 关键特点
  1. 批量执行: 管道允许客户端一次性发送多个命令,服务器批量执行这些命令。
  2. 原子性操作: 管道中的一系列命令被视为一个原子操作,要么全部执行成功,要么全部失败。
  3. 异步执行: 客户端可以在一次发送命令之后继续执行其他操作,而不必等待管道中的命令执行完成。
1.4 使用场景
  1. 批量数据操作: 适用于需要对大量数据进行批量读写操作的场景,如批量设置、批量获取等。
  2. 事务操作: 管道可以与Redis的事务结合使用,提供原子性的事务操作。
  3. 实时性要求不高的场景: 适用于实时性要求不高,但对吞吐量和性能要求较高的场景。
1.5 注意事项
  1. 不适用于所有场景: 管道并非适用于所有操作,某些命令或操作可能无法充分利用管道的优势。
  2. 错误处理: 在管道中,如果其中一个命令执行失败,可能会影响之后的命令执行,因此需要谨慎处理错误情况。
  3. 网络稳定性: 在网络不稳定的环境下,由于管道是一次性发送多个命令,可能会增加部分失败的风险,需要考虑网络的稳定性。

综合而言,Redis管道是一种有效的性能优化机制,但在使用时需要根据具体场景谨慎考虑,并充分理解其优势和限制。

二、Redis管道基础

2.1 管道原理

Redis管道的原理涉及到在客户端和服务器之间传输命令的方式、命令队列的处理以及异步执行的机制。以下是Redis管道的基本原理:

  1. 命令传输方式: 在非管道模式下,客户端发送一个命令到服务器后,需要等待服务器的响应,然后才能发送下一个命令。而在管道模式下,客户端可以一次性发送多个命令,而不必等待每个命令的响应。
  2. 命令队列的处理: 当客户端启用管道后,所有的命令都被放入一个队列中,而不是立即发送给服务器。这个队列保存了所有即将发送给服务器的命令。
  3. 一次性发送和接收: 在管道模式下,客户端可以通过一次性发送整个命令队列给服务器。服务器收到这个队列后,会一次性执行所有的命令,并将结果一次性返回给客户端。
  4. 异步执行机制: 在管道模式下,客户端可以在发送完命令后继续执行其他操作,而不必等待服务器的响应。服务器则异步地执行收到的命令队列,并将结果缓存在内存中,等待客户端主动去获取。
  5. 原子性操作: 在管道中的多个命令被视为一个原子操作,要么全部成功执行,要么全部失败。这确保了在多个命令执行的过程中的一致性。

Redis管道的原理是通过批量发送多个命令、异步执行、以及原子性保证,来提高命令执行的效率和性能。这种机制尤其适用于需要批量操作、事务处理、以及对实时性要求不高的场景,能够有效减少网络开销和提升系统性能。

2.2 管道与非管道操作的对比
  1. 单个命令执行
    管道与非管道操作在单个命令执行方面存在显著的对比。以下是管道和非管道操作在单个命令执行方面的对比:
    • 非管道操作:

      • 单个命令执行: 在非管道模式下,每个命令都需要等待上一个命令的响应后才能发送下一个命令。
      • 阻塞模式: 非管道模式下的执行是阻塞的,即客户端发送一个命令后需要等待服务器的响应,这期间无法执行其他操作。
      • 高延迟: 由于每个命令都需要等待服务器响应,可能导致整体操作的延迟较高,特别是在需要执行多个命令的情况下。
    • 管道操作:

      • 批量命令执行: 在管道模式下,客户端可以一次性发送多个命令,而不必等待每个命令的响应。
      • 异步执行: 客户端在发送完命令后可以继续执行其他操作,而不必等待服务器响应。服务器会异步执行收到的命令队列。
      • 降低延迟: 由于可以一次性发送多个命令,管道模式能够显著降低整体操作的延迟,特别是在需要执行多个命令的场景下。

选择使用管道操作还是非管道操作取决于具体的应用场景和性能需求。在需要处理大量命令、提高性能、降低延迟的情况下,管道操作是一个强大的工具。

  1. 管道操作的优势
    Redis管道操作带来了多方面的优势,尤其在处理大量命令和追求高性能的场景下,它成为了一个强大的工具。以下是一些管道操作的优势:
    • 批量操作: 管道允许客户端一次性发送多个命令到服务器,从而实现了批量操作。这对于需要对大量数据进行读写的场景非常有利,减少了单独发送每个命令的开销。
    • 降低网络延迟: 由于管道允许一次性发送多个命令并接收多个命令的响应,可以大大减少网络往返的次数,从而降低了网络延迟。这对于追求低延迟的应用场景非常重要。
    • 提高吞吐量: 管道允许多个命令的并行执行,从而提高了系统的吞吐量。通过减少客户端和服务器之间的等待时间,系统可以更有效地处理大量命令。
    • 异步执行: 在启用管道的情况下,客户端可以在发送完命令后继续执行其他操作,而不必等待服务器的响应。这种异步执行机制可以更好地利用客户端和服务器的资源。
    • 原子性保证: 管道中的多个命令被视为一个原子操作,要么全部成功执行,要么全部失败。这确保了在多个命令执行的过程中的一致性,适用于事务场景。
    • 减少CPU占用: 由于管道允许异步执行,并且一次性发送多个命令,可以减少服务器在处理大量命令时的CPU占用,提高系统的效率。
    • 适用于大规模数据处理: 在需要处理大规模数据的场景下,管道操作可以显著减少执行时间,提高系统的处理效率。

Redis管道操作在处理大量命令、降低延迟、提高吞吐量等方面提供了明显的优势,为高性能的数据处理提供了有效的解决方案。

三、Redis管道的使用

3.1 管道的启用、关闭以及批量添加执行命令

在C#中使用StackExchange.Redis库可以方便地与Redis建立连接并使用管道操作。在StackExchange.Redis库中,由于 Batch 类并没有提供显式的关闭(dispose)方法,我们通常使用 Execute 方法来执行管道中的命令并关闭管道。在执行 Execute 后,可以认为该批处理(管道)已经完成。以下是一个简单的示例代码,演示如何在C#中启用Redis管道:

using StackExchange.Redis;
using System;class Program
{static void Main(){// 连接到Redis服务器ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("your_redis_server_address");// 获取数据库IDatabase db = redis.GetDatabase();// 启用管道var batch = db.CreateBatch();// 添加多个命令到管道batch.StringSetAsync("key1", "value1");batch.StringSetAsync("key2", "value2");batch.StringGetAsync("key1");batch.StringGetAsync("key2");// 执行管道中的所有命令并获取结果var results = batch.Execute();// 处理结果foreach (var result in results){Console.WriteLine($"Result: {result}");}// 关闭连接redis.Close();}
}

在上述代码中,我们首先通过ConnectionMultiplexer.Connect方法连接到Redis服务器。然后,通过GetDatabase方法获取一个数据库实例。接着,使用CreateBatch方法创建一个批处理(管道)对象,将多个命令添加到该批处理中。最后,通过Execute方法执行管道中的所有命令,并获取结果。

四、Redis管道的性能优化

4.1 减少网络开销

Redis管道的性能优化主要体现在减少网络开销、提高吞吐量等方面。其中,减少网络开销是一个关键的优化点。以下是一些减少网络开销的性能优化策略:

  1. 一次性发送多个命令: Redis管道允许客户端一次性发送多个命令到服务器。通过批量发送命令,可以减少每个命令之间的网络往返次数,从而降低网络开销。
    var batch = db.CreateBatch();
    batch.StringSetAsync("key1", "value1");
    batch.StringSetAsync("key2", "value2");
    batch.StringGetAsync("key1");
    batch.StringGetAsync("key2");
    var results = batch.Execute();
    
  2. 异步执行: 在启用管道的情况下,客户端可以在发送完命令后继续执行其他操作,而不必等待服务器的响应。这样可以更好地利用网络带宽和降低整体等待时间。
    var batch = db.CreateBatch();
    batch.StringSetAsync("key1", "value1");
    batch.StringSetAsync("key2", "value2");
    batch.StringGetAsync("key1");
    batch.StringGetAsync("key2");
    var results = batch.Execute();
    
  3. 减少不必要的命令: 在使用管道时,避免发送不必要的命令。只发送实际需要执行的命令,以减少数据传输和服务器的处理负担。
  4. 合并命令: 在某些情况下,可以将多个操作合并成一个命令,从而减少需要执行的命令数量。例如,使用Redis的MSET命令一次性设置多个键值对。
  5. 使用Pipeline: StackExchange.Redis库中的multiplexer.GetDatabase().CreateBatch()创建的是一个常规的管道,而StackExchange.Redis还提供了multiplexer.GetDatabase().CreateBatch(DatabaseAvailableCallback.Eager)方法创建一个EagerPipe,它使用一种更为高效的方式执行管道中的命令,能够进一步减少网络开销。
    var batch = db.CreateBatch(DatabaseAvailableCallback.Eager);
    batch.StringSetAsync("key1", "value1");
    batch.StringSetAsync("key2", "value2");
    batch.StringGetAsync("key1");
    batch.StringGetAsync("key2");
    var results = batch.Execute();
    

通过采取这些性能优化策略,特别是减少网络开销,可以显著提高Redis管道操作的效率和性能。

4.2 提高吞吐量
  1. 并行执行的优势
    提高吞吐量是Redis管道操作的一个重要优势之一,而并行执行是实现这一优势的关键。以下是关于并行执行的优势以及提高吞吐量的相关策略:
  • 并行执行的优势:

    • 减少等待时间: 在非管道模式下,每个命令都需要等待上一个命令的响应后才能发送下一个命令。而在管道模式下,所有命令可以一次性发送给服务器,服务器也可以异步执行这些命令。这样就可以减少客户端和服务器之间的等待时间,提高了整体的响应速度。
    • 最大程度利用带宽: 并行执行允许多个命令同时在网络上传输,最大程度地利用了网络带宽。这对于需要大量读写操作的场景尤为重要,因为可以同时处理多个命令,而不是一个一个地等待。
  • 提高吞吐量的策略:

    • 批量操作: 利用管道一次性发送多个命令,可以减少网络往返次数,从而提高吞吐量。将多个操作合并到一个管道中,并以批处理的方式发送。
    var batch = db.CreateBatch();
    batch.StringSetAsync("key1", "value1");
    batch.StringSetAsync("key2", "value2");
    batch.StringGetAsync("key1");
    batch.StringGetAsync("key2");
    var results = batch.Execute();
    
    • 并行执行多个管道: 如果需要执行多个独立的管道,可以并行执行它们以提高吞吐量。这需要适当的线程管理和同步控制,确保并行执行的安全性。
    // 示例中并行执行两个独立的管道
    var batch1 = db.CreateBatch();
    batch1.StringSetAsync("key1", "value1");var batch2 = db.CreateBatch();
    batch2.StringSetAsync("key2", "value2");var results1 = batch1.Execute();
    var results2 = batch2.Execute();
    
    • 选择合适的数据结构和命令: 根据具体需求,选择合适的数据结构和命令。例如,使用Redis的HSETHMSET命令来批量设置哈希数据,而不是单独设置每个字段。

通过采取这些策略,可以更好地利用Redis管道的并行执行优势,从而提高系统的吞吐量,特别是在大规模数据处理的场景中。

  1. 优化管道中命令的顺序
    优化管道中命令的顺序可以在一定程度上提高性能,特别是在需要执行多个相关命令的情况下。以下是一些优化管道中命令顺序的策略:
    • 批量命令的顺序优化:
      • 相关命令的顺序: 如果有一系列相关的命令,可以优化它们的顺序以减少不必要的等待。例如,如果需要先设置一个值,然后获取这个值,可以将这两个命令放在一起。
    var batch = db.CreateBatch();
    batch.StringSetAsync("key1", "value1");
    batch.StringGetAsync("key1");
    var results = batch.Execute();
    
    • 减少依赖关系: 尽量减少命令之间的依赖关系。如果某个命令的执行不依赖于前一个命令的结果,可以将它们放在一起执行,减少等待时间。
    var batch = db.CreateBatch();
    batch.StringSetAsync("key1", "value1");
    batch.StringSetAsync("key2", "value2");
    var results = batch.Execute();
    
  • 降低等待时间的优化:

    • 异步执行的顺序: 在启用管道的情况下,客户端可以在发送完命令后继续执行其他操作。考虑到命令的异步执行,可以优化命令的顺序,尽量减少等待时间。
    var batch = db.CreateBatch();
    batch.StringSetAsync("key1", "value1");
    batch.StringGetAsync("key1");
    var results = batch.Execute();
    
  • 合并相关操作:

    • 使用事务操作: 如果一系列命令需要作为一个原子操作执行,可以使用Redis的事务(MULTI/EXEC)来合并这些相关操作,从而减少不必要的等待。
    var transaction = db.CreateTransaction();
    transaction.AddCondition(Condition.StringEqual("key1", "expectedValue"));
    transaction.StringSetAsync("key1", "newValue");
    transaction.StringGetAsync("key1");
    var results = transaction.Execute();
    
  • 利用Redis的原子性操作:

    • 使用原子性操作: Redis提供了一些原子性的操作,如INCRDECRHINCRBY等,可以考虑将一些相关的操作组合在一起,以减少管道中命令的数量。
    var batch = db.CreateBatch();
    batch.StringIncrementAsync("counter");
    batch.StringSetAsync("key1", "value1");
    var results = batch.Execute();
    

通过综合考虑这些优化策略,可以在一定程度上改善Redis管道操作的性能,特别是在需要执行大量相关命令的场景中。优化命令的顺序和组织方式,可以更有效地利用管道的性能优势。

五、使用案例

Redis管道在以下场景中可以发挥重要作用,提高性能和效率:

  1. 大规模数据导入/导出: 当需要从外部数据源导入大量数据到Redis或将Redis中的数据导出到外部存储时,使用管道可以显著提高导入/导出的速度。通过一次性发送多个数据插入或读取命令,减少了网络往返次数,提高了数据传输效率。
  2. 批量写入或更新操作: 在需要进行大规模批量写入或更新操作的场景中,例如批量设置用户状态、记录日志等,管道可以用于一次性提交多个命令,提高写入操作的吞吐量。
    var batch = db.CreateBatch();
    for (int i = 0; i < 1000; i++)
    {batch.StringSetAsync($"user:{i}:status", "online");
    }
    var results = batch.Execute();
    
  3. 实时统计和计算: 在需要进行实时统计和计算的场景中,例如计数器的增加、减少等操作,可以使用管道来一次性提交多个计算命令,减少了每个计算操作的网络开销。
    var batch = db.CreateBatch();
    batch.StringIncrementAsync("total_users");
    batch.StringIncrementAsync("active_users");
    batch.StringIncrementAsync("page_views");
    var results = batch.Execute();
    
  4. 事务操作: Redis的事务(MULTI/EXEC)结合管道可以用于执行一系列原子性的命令,确保它们要么全部执行成功,要么全部失败。这对于需要保持一致性的操作场景非常有用。
    var transaction = db.CreateTransaction();
    transaction.StringSetAsync("key1", "value1");
    transaction.StringSetAsync("key2", "value2");
    transaction.StringGetAsync("key1");
    transaction.StringGetAsync("key2");
    var results = transaction.Execute();
    
  5. 缓存预热: 在系统启动时,可以使用管道一次性将缓存中需要的数据进行预热,减少了系统启动时的冷启动时间。
    var batch = db.CreateBatch();
    foreach (var item in preloadData)
    {batch.StringSetAsync(item.Key, item.Value);
    }
    var results = batch.Execute();
    

Redis管道在需要处理大量相关命令、提高性能、降低延迟的场景中都能发挥重要作用。使用管道能够有效地减少网络开销,提高系统的吞吐量,是Redis高效利用的一种重要手段。

六、注意事项和限制

在使用Redis管道时,有一些注意事项和限制需要考虑,以确保系统的稳定性和正确性。以下是一些常见的注意事项和限制:

  1. 原子性保证: 尽管管道中的一系列命令被视为一个原子操作,但在执行期间仍可能发生错误。在错误发生时,可能会导致一部分命令执行成功,而一部分命令执行失败。因此,需要在使用管道时考虑错误处理机制。
  2. 网络稳定性: 在网络不稳定的环境下,由于管道是一次性发送多个命令,可能会增加部分失败的风险。需要谨慎处理网络波动、连接断开等情况,以保证系统的可靠性。
  3. 不适用于所有场景: 管道并非适用于所有操作。例如,一些命令需要等待上一个命令的结果才能执行,这样的操作无法充分利用管道的优势。因此,在选择使用管道时,需要根据具体场景进行评估。
  4. 事务与管道: 在管道中使用事务(MULTI/EXEC)时,需要注意事务的原子性在Redis中是针对单个连接的。如果一个连接在执行事务的同时又执行了其他命令,可能会破坏事务的原子性。
  5. 管道与订阅/发布: 管道和订阅/发布(Pub/Sub)机制之间可能存在一些不兼容。在同一连接中使用管道和订阅/发布时,可能会出现一些问题,因此需要仔细考虑如何组织代码。
  6. 管道中的大数据量: 当管道中包含大量数据操作时,需要注意Redis服务器的内存和网络带宽。过大的管道可能会导致服务器性能下降或网络拥塞。
  7. 不支持所有命令: 并非所有Redis命令都能在管道中使用。一些命令,如WATCHMULTIDISCARD等,在管道中并不被支持。
  8. 客户端实现的差异: 不同的Redis客户端实现对管道的支持和实现方式可能有一些差异。在使用特定客户端库时,需要查阅相关文档了解其具体实现细节。

七、总结

Redis管道是一种优化性能的机制,通过批量执行多个命令、异步操作和原子性保证,提高了系统吞吐量和降低延迟。在C#中使用StackExchange.Redis库,可以通过CreateBatch创建管道,一次性发送多个命令。优化管道中命令的顺序、考虑网络稳定性、注意事务与管道的兼容性等是使用管道时的注意事项。管道的适用场景包括大规模数据操作、批量写入、实时统计和计算、缓存预热等。综合而言,Redis管道是提升性能、降低延迟的强大工具,但在使用时需谨慎考虑其注意事项和限制。

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

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

相关文章

java 对数转换log_a {c}

1、换底公式 l o g a c l o g x c l o g x a log_a c \frac{log_x c}{log_x a} loga​clogx​alogx​c​ 2、推理过程 有&#xff1a; a b c &#xff0c;证明 l o g a c l o g x c l o g x a 取对数 ( l o g x ) &#xff1a; l o g x a b l o g x c l o g x a b b ∗ …

鸿蒙HarmonyOS-图表应用

简介 随着移动应用的不断发展&#xff0c;数据可视化成为提高用户体验和数据交流的重要手段之一。在HarmonyOS应用开发中&#xff0c;一个强大而灵活的图表库是实现这一目标的关键。而MPChart就是这样一款图表库&#xff0c;它为开发者提供了丰富的功能和灵活性&#xff0c;使得…

【持续更新ing】uniapp+springboot实现个人备忘录系统【前后端分离】

目录 &#xff08;1&#xff09;项目可行性分析 &#xff08;2&#xff09;需求描述 &#xff08;3&#xff09;界面原型 &#xff08;4&#xff09;数据库设计 &#xff08;5&#xff09;后端工程 接下来我们使用uniappspringboot实现一个简单的前后端分离的小项目----个…

Spark作业的调度与执行流程

Apache Spark是一个分布式计算框架&#xff0c;用于处理大规模数据。了解Spark作业的调度与执行流程是构建高效分布式应用程序的关键。本文将深入探讨Spark作业的组成部分、调度过程以及执行流程&#xff0c;并提供丰富的示例代码来帮助大家更好地理解这些概念。 Spark作业的组…

第09章:随堂复习与企业真题(异常处理)

来源&#xff1a;尚硅谷Java零基础全套视频教程(宋红康2023版&#xff0c;java入门自学必备) 基本都是宋老师发的资料里面的内容&#xff0c;只不过补充几个资料里没直接给出答案的问题的答案。 不想安装markdown笔记的app所以干脆在这里发一遍。 第09章&#xff1a;随堂复习…

[Angular] 笔记 16:模板驱动表单 - 选择框与选项

油管视频&#xff1a; Select & Option (Template Driven Forms) Select & Option 在 pokemon.ts 中新增 interface: export interface Pokemon {id: number;name: string;type: string;isCool: boolean;isStylish: boolean;acceptTerms: boolean; }// new interface…

前端图片适配不同屏幕方案

预备知识&#xff1a; 设备独立像素,以下图的iphone12 Pro为例&#xff0c;390*844表示的就是设备独立像素&#xff08;DIP&#xff09;,也可以理解为CSS像素 物理像素&#xff08;设备像素&#xff09;&#xff0c;就是屏幕的分辨率&#xff0c;显示屏就是由一个个物理像素…

QT/C++ 远程数据采集上位机+服务器

一、项目介绍&#xff1a; 远程数据采集与传输 课题要求:编写个基于TCP的网络数据获取与传输的应用程序; 该程序具备以下功能: 1)本地端程序够通过串口与下位机(单片机)进行通信&#xff0c;实现数据采集任务 2)本地端程序能将所获取下位机数据进行保存(如csv文本格式等); 3…

初识隧道代理HTTP:理解基础概念的重要性

嗨&#xff0c;小伙伴们&#xff01;如果你对网络世界充满好奇&#xff0c;那么这篇文章就是为你准备的。我们将一起踏上一段奇妙的旅程&#xff0c;探索一个叫做“隧道代理HTTP”的新领域。但在这之前&#xff0c;我们需要先穿上“基础概念”的防护服&#xff0c;以免被这个复…

axios配置代理

ChatGPT&#xff08;3.5/4.0&#xff09;国内镜像&#xff1a;https://www.atalk-ai.com/ 在Node.js中&#xff0c;你可以使用axios库来发送HTTP请求&#xff0c;并且可以配置它来使用代理服务器。以下是如何配置axios以通过位于127.0.0.1:15236的代理服务器发送请求的例子&am…

MR实战:实现数据去重

文章目录 一、实战概述二、提出任务三、完成任务&#xff08;一&#xff09;准备数据文件1、在虚拟机上创建文本文件2、上传文件到HDFS指定目录 &#xff08;二&#xff09;实现步骤1、Map阶段实现&#xff08;1&#xff09;创建Maven项目&#xff08;2&#xff09;添加相关依赖…

一语道破爬虫,来揭开爬虫面纱

目录 一、爬虫&#xff08;网络蜘蛛(Spider)&#xff09; 1.1、是什么&#xff1a; 1.2、学习的原因 1.3、用在地方&#xff1a; 1.4、是否合法&#xff1a; 1.5、后果 案例&#xff1a; 二、应用领域 三、Robots协议 四、抓包 4.1、浏览器抓包 4.2、抓包工具 常见…

从0到1浅析Redis服务器反弹Shell那些事

文章目录 前言Redis服务1.1 特点与应用1.2 安装与使用1.3 语法和配置1.4 未授权访问 反弹Shell2.1 Web服务写入Webshell2.2 Linux定时任务反弹shell2.3 /etc/profile.d->反弹shell2.4 写入ssh公钥登录服务器2.5 利用Redis主从复制RCE2.6 SSRF漏洞组合拳->RCE 总结 前言 …

2023年终-顺势而为

疫情以来&#xff0c;越来越感觉到顺势的重要性&#xff0c;就像一个人走路一样&#xff0c;如果方向错了&#xff0c;会绕很多弯才能到达终点。 雷军说&#xff0c;站在风口上猪都能飞起来。 很多人明白这个道理&#xff0c;但是去付出实践的人不多。第一&#xff0c;不愿意进…

stm32中的i2c协议

stm32中I2C 文章目录 stm32中I2CI2C 协议简介I2C物理层协议层I2C基本读写过程 **通讯的起始和停止信号****数据有效性****地址及数据方向****响应** STM32的I2C特性及架构**STM32** **的** I2C外设简介STM32 的 I 2C 架构剖析通讯引脚 通讯过程主发送器主接收器 I2C初始化结构体…

【Linux】指令(本人使用比较少的)——笔记(持续更新)

文章目录 ps -axj&#xff1a;查看进程ps -aL&#xff1a;查看线程echo $?&#xff1a;查看最近程序的退出码jobs&#xff1a;查看后台运行的线程组fd 任务号&#xff1a;将后台任务提到前台bg 任务号&#xff1a;将暂停的后台程序重启netstat -nltp&#xff1a;查看服务及监听…

Unity Meta Quest 一体机开发(十二):【手势追踪】Poke 交互 - 用手指点击由 3D 物体制作的 UI 按钮

文章目录 &#x1f4d5;教程说明&#x1f4d5;给玩家配置 HandPokeInteractor&#x1f4d5;用 3D 物体制作可以被点击的 UI 按钮⭐搭建物体层级⭐给物体添加脚本⭐为脚本变量赋值 &#x1f4d5;模仿官方样例按钮的样式&#x1f4d5;在按钮上添加文字&#x1f4d5;修改按钮图片 …

Unity应该如何学

Unity是目前最主流的游戏开发引擎&#xff0c;AppStore里面排名前列的游戏绝大部分都是采用Unity引擎来开发的&#xff0c;所以Unity引擎的前景也是非常好的&#xff0c;同时很多AR,VR也是基于Unity的&#xff0c;所以对于做游戏而言Unity引擎是非常值得学习的。如何学习Unity呢…

Nginx 403 Forbidden错误处理

当出现 Nginx 403 Forbidden 错误时&#xff0c;有几种可能的原因&#xff1a; 1. 权限问题 文件或目录权限不正确&#xff1a; 使用 chown -R nginx:nginx /dist/ 更改了目录的所有权和权限&#xff0c;但是可能存在子文件或子目录的权限问题。检查所有文件和子目录确保它们…