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

【️什么是分布式系统的一致性 ?】

在这里插入图片描述

😊引言

🎖️本篇博文约8000字,阅读大约30分钟,亲爱的读者,如果本博文对您有帮助,欢迎点赞关注!😊😊😊

🖥️什么是分布式系统的一致性 ?

  • ✅分布式系统的一致性
    • ✅线性一致性 & 顺序一致性
    • ✅顺序一致性 & 最终一致性

✅分布式系统的一致性


所谓一致性,是指数据在多个副本之间是否能够保持一致的特性,再聊一致性的时间,其实要搞清楚一致性模型。
分布式系统中的一致性模型是一组管理分布式系统行为的规则。它决定了在分布式系统中如何访问和更新数据,以及如何将这些更新提供给客户端。面对网络延迟和局部故障等分布式计算难题,分布式系统的一致性模型对保证系统的一致性和可靠性起着关键作用。在分布式系统中有多种一致性模型可用,每个模型都有其优点和缺点,选择模型取决于系统的具体要求。

大的分类上面,主要有三种,分别是强一致性弱一致性最终一致性

  • 强一致性(Strong Consistency)
         在强一致性模型下,系统保证每个读操作都将返回最近的写操作的结果,即任何时间点,客户端都将看到相同的数据视图。这包括线性一致性(Linearizability) 、顺序一致性(Sequential Consistency) 和严格可串行性 (Strict Serializability) 等子模型。强 致性模型通常牺牲了可用性来实现数据一致性。

  • 弱一致性(Weak Consistency)
         弱一致性模型放宽了一致性保证,它允许在不同节点之间的数据访问之间存在一定程度的不一致性,以换取更高的性能和可用性。这包括因果致性(Causal Consistency)会话一致性(Session Consistency) 和单调一致性(Monotonic Consistency) 等子模型。弱一致性模型常更注重可用性,允许一定程度的数据不一致性。

  • 最终一致性(Eventual Consistency)
         最终一致性模型是一种最大程度放宽了一致性要求的模型。它允许在系统发生分区或网络故障后,经过一段时间,系统将最终达到一致状态。这个模型在某些情况下提供了很高的可用性,但在一段时间内可能会出现数据不一致的情况。

我们看下代码巩固一下我们理论:

⛳第一个:先看一个分布式系统一致性的简单Demo

import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.TimeUnit;  /**
*	@author 昕宝爸爸爱编程
*	分布式系统一致性的简单Demo
*/  
public class DistributedConsistencyExample {  private static final int NUM_OF_NODES = 3; // 假设有3个节点  private static final int MAX_TIME = 5; // 最大等待时间为5秒  public static void main(String[] args) throws InterruptedException {  ExecutorService executorService = Executors.newFixedThreadPool(NUM_OF_NODES);  for (int i = 0; i < NUM_OF_NODES; i++) {  executorService.execute(new Node(i));  }  executorService.shutdown();  executorService.awaitTermination(MAX_TIME, TimeUnit.SECONDS);  }  static class Node implements Runnable {  private int id;  public Node(int id) {  this.id = id;  }  @Override  public void run() {  try {  // 执行任务,这里只是简单地打印节点ID  System.out.println("节点" + id + "正在执行任务...");  Thread.sleep(1000); // 模拟任务执行时间  } catch (InterruptedException e) {  e.printStackTrace();  }  }  }  
}

可以看到,我创建了一个包含3个节点的分布式系统。每个节点都是一个线程,它们在启动后开始执行任务。这里我们只是简单地打印节点ID,并模拟任务执行时间。

⛳第二个:增加分布式锁和事务处理来实现一致性

这一个就相对上面一段代码来讲,增加了些复杂度,使用了分布式锁和事务处理来实现一致性:

import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.TimeUnit;  
import java.util.concurrent.locks.Lock;  
import java.util.concurrent.locks.ReentrantLock;  
/**
* @author 昕宝爸爸爱编程
* 增加分布式锁和事务处理来实现一致性
*/
public class DistributedConsistencyExample {  private static final int NUM_OF_NODES = 3; // 假设有3个节点  private static final int MAX_TIME = 5; // 最大等待时间为5秒  private static final Lock lock = new ReentrantLock(); // 分布式锁  public static void main(String[] args) throws InterruptedException {  ExecutorService executorService = Executors.newFixedThreadPool(NUM_OF_NODES);  for (int i = 0; i < NUM_OF_NODES; i++) {  executorService.execute(new Node(i));  }  executorService.shutdown();  executorService.awaitTermination(MAX_TIME, TimeUnit.SECONDS);  }  static class Node implements Runnable {  private int id;  public Node(int id) {  this.id = id;  }  @Override  public void run() {  try {  // 执行任务,这里模拟一个需要加锁的操作  lock.lock(); // 加锁  try {  // 执行任务逻辑,这里只是简单地打印节点ID和加锁情况  System.out.println("节点" + id + "正在执行任务...");  System.out.println("节点" + id + "获取了锁...");  Thread.sleep(1000); // 模拟任务执行时间  } finally {  lock.unlock(); // 释放锁  }  } catch (InterruptedException e) {  e.printStackTrace();  }  }  }  
}

我们使用了ReentrantLock来实现分布式锁。当一个节点获取了锁之后,其他节点必须等待该节点释放锁后才能执行任务。这样可以保证同一时刻只有一个节点可以执行任务,从而实现了分布式系统的一致性。同时,我们还使用了事务处理的方式,确保任务的原子性和一致性。在执行任务时,我们首先获取锁,然后执行任务逻辑,最后释放锁。这样可以保证在任务执行过程中不会被其他节点干扰,从而保证了数据的一致性。

⛳第三个:增加使用了分布式锁、事务处理和消息队列来实现一致性保证

import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.TimeUnit;  
import java.util.concurrent.locks.Lock;  
import java.util.concurrent.locks.ReentrantLock;  /**
* @author 昕宝爸爸爱编程
*/  
public class DistributedConsistencyExample {  private static final int NUM_OF_NODES = 3; // 假设有3个节点  private static final int MAX_TIME = 5; // 最大等待时间为5秒  private static final Lock lock = new ReentrantLock(); // 分布式锁  private static final String QUEUE_NAME = "distributed-queue"; // 消息队列名称  public static void main(String[] args) throws InterruptedException {  ExecutorService executorService = Executors.newFixedThreadPool(NUM_OF_NODES);  for (int i = 0; i < NUM_OF_NODES; i++) {  executorService.execute(new Node(i));  }  executorService.shutdown();  executorService.awaitTermination(MAX_TIME, TimeUnit.SECONDS);  }  static class Node implements Runnable {  private int id;  public Node(int id) {  this.id = id;  }  @Override  public void run() {  try {  // 执行任务,这里模拟一个需要加锁和消息队列的操作  lock.lock(); // 加锁  try {  // 发送消息到消息队列  String message = "节点" + id + "正在执行任务...";  System.out.println(message);  // 模拟发送消息到消息队列的时间  Thread.sleep(1000);   } finally {  lock.unlock(); // 释放锁  }  } catch (InterruptedException e) {  e.printStackTrace();  }  }  }  
}

可以看到,我使用了ReentrantLock来实现分布式锁。当一个节点获取了锁之后,其他节点必须等待该节点释放锁后才能执行任务。这样可以保证同一时刻只有一个节点可以执行任务,从而实现了分布式系统的一致性。同时,我们还使用了消息队列来协调节点之间的通信。在执行任务时,我们首先获取锁,然后发送消息到消息队列,最后释放锁。这样可以保证在任务执行过程中不会被其他节点干扰,从而保证了数据的一致性。同时,通过消息队列的传递机制,可以确保消息的可靠性和顺序性,进一步保证了分布式系统的一致性。

✅线性一致性 & 顺序一致性

线性一致性(Linearizability) 和顺序 致性(Sequential Consistency) 是两种强 致性模型。

线性一致性是一种最强的一致性模型,它强调在分布式系统中的任何时间点,读操作都应该返回最近的写操作的结果。

顺序一致性也是一种强一致性模型,但相对于线性一致性而言,它放宽了一些限制。在顺序一致性模型中,系统维护一个全局的操作顺序,以确保每个客户端看到的操作顺序都是一致的。

与线性一致性不同,顺序一致性不强调实时性,只要操作的顺序是一致的,就可以接受一些延迟

他们的主要区别在于强调实时性。线性一致性要求操作在实际时间上的顺序保持一致,而顺序一致性只要求操作的顺序是一致的,但不一定要求操作的实际时间顺序。

⛳同样的我们结合代码来看一看。

1、⛳线性一致性代码展示:

import java.util.concurrent.atomic.AtomicInteger;  /**
* @author 昕宝爸爸爱编程
*/  
public class LinearConsistencyExample {  private static final AtomicInteger counter = new AtomicInteger(0);  public static void main(String[] args) throws InterruptedException {  Thread thread1 = new Thread(() -> {  counter.incrementAndGet();  System.out.println("Thread 1 incremented counter to: " + counter.get());  });  Thread thread2 = new Thread(() -> {  counter.incrementAndGet();  System.out.println("Thread 2 incremented counter to: " + counter.get());  });  thread1.start();  thread2.start();  thread1.join();  thread2.join();  }  
}

用到了AtomicInteger类,该类提供了原子性的操作来保证线性一致性。两个线程同时递增计数器,并打印计数器的值。由于AtomicInteger的递增操作是原子的,因此可以保证两个线程之间的操作是线性一致的。无论线程的执行顺序如何,最终打印的值都是递增的。

2、⛳顺序一致性代码展示:

import java.util.concurrent.*;  /**
* @author 昕宝爸爸爱编程
*/ 
public class SequentialConsistencyExample {  private static final int NUM_OF_THREADS = 3;  private static final ExecutorService executorService = Executors.newFixedThreadPool(NUM_OF_THREADS);  private static final Semaphore semaphore = new Semaphore(1); // 用于实现互斥的信号量  private static int sharedData = 0; // 共享数据  public static void main(String[] args) throws InterruptedException {  for (int i = 0; i < NUM_OF_THREADS; i++) {  executorService.execute(() -> {  try {  semaphore.acquire(); // 获取信号量,实现互斥访问  sharedData++; // 更新共享数据  System.out.println("Thread " + Thread.currentThread().getId() + " updated shared data to: " + sharedData);  } catch (InterruptedException e) {  e.printStackTrace();  } finally {  semaphore.release(); // 释放信号量,允许其他线程访问  }  });  }  executorService.shutdown();  executorService.awaitTermination(1, TimeUnit.HOURS); // 等待所有任务执行完毕  }  
}

使用Semaphore类来实现互斥访问共享数据,以保证顺序一致性。多个线程通过获取信号量来访问共享数据,并在更新共享数据后释放信号量。

由于只有一个线程可以同时访问共享数据,因此可以保证线程之间的操作是按照它们启动的顺序执行的。无论线程的执行顺序如何,最终打印的值都是递增的。

所有线程看到的数据依照他们操作执行的顺序而变化。

✅顺序一致性 & 最终一致性

先看一下最终一致性的代码:

import java.util.concurrent.CopyOnWriteArrayList;  
import java.util.concurrent.atomic.AtomicReference;  /**
* @author 昕宝爸爸爱编程
*/ 
public class EventualConsistencyExample {  private static final CopyOnWriteArrayList<String> eventLog = new CopyOnWriteArrayList<>();  private static final AtomicReference<String> latestEvent = new AtomicReference<>();  public static void main(String[] args) {  Thread writerThread = new Thread(() -> {  for (int i = 0; i < 10; i++) {  eventLog.add("Event " + i);  latestEvent.set("Event " + i);  try {  Thread.sleep(1000); // 模拟异步操作,延迟1秒  } catch (InterruptedException e) {  e.printStackTrace();  }  }  });  Thread readerThread = new Thread(() -> {  while (true) {  String latestEvent = latestEvent.get();  if (latestEvent != null) {  System.out.println("Reader read event: " + latestEvent);  } else {  System.out.println("Reader read event: null (no event available)");  }  try {  Thread.sleep(500); // 模拟异步操作,延迟0.5秒  } catch (InterruptedException e) {  e.printStackTrace();  }  }  });  writerThread.start();  readerThread.start();  }  
}

CopyOnWriteArrayList和AtomicReference来模拟最终一致性的场景。eventLog是一个线程安全的列表,用于存储事件日志。latestEvent是一个原子引用,用于存储最新的事件。

在主线程中,我们创建了一个写线程和一个读线程。写线程将模拟写入事件到eventLog中,并将最新的事件存储到latestEvent中。读线程将不断读取latestEvent中的最新事件,并打印出来。由于写线程和读线程是异步执行的,因此它们之间的操作可能会存在一定的延迟。但是,由于使用了线程安全的列表和原子引用,最终一致性得到了保证。无论何时读取latestEvent,都总是能够获得最新的事件,或者在读取时事件还未发生而返回null。这正是最终一致性的特点:在没有更新数据的一段时间里,系统将通过广播保证副本之间的数据一致性。

很多人看完线性一致性和顺序一致性的区别之后,会容易懵,看上去顺序一致性和我们理解的最终一致性有点像?

💡那么他们的区别是啥呢?

在时间上,虽然顺序一致性和最终一致性都不强要求实时性,但是最终一致性的时间放的会更宽。并且最终一致性其实并不强调顺序,他只需要保证最终的结果一致就行了,而顺序一致性要求操作顺序必须一致。

并且,顺序一致性还是一种强一致性,比如在Zookeeper中,其实就是通过ZAB算法来保证的顺序一致性,即各人节点之间的写入顺序要求一致。并且要半数以上的节点写入成功才算成功。所以,顺序一致性的典型应用场景就是数据库管理系统以及分布式系统。

而最终一致性通常适用于互联网三高架构的业务开发,如电商网站,社交媒体网站等.

相关文章:

【️什么是分布式系统的一致性 ?】

&#x1f60a;引言 &#x1f396;️本篇博文约8000字&#xff0c;阅读大约30分钟&#xff0c;亲爱的读者&#xff0c;如果本博文对您有帮助&#xff0c;欢迎点赞关注&#xff01;&#x1f60a;&#x1f60a;&#x1f60a; &#x1f5a5;️什么是分布式系统的一致性 &#xff1f…...

鸿蒙ArkTS Web组件加载空白的问题原因及解决方案

问题症状 初学鸿蒙开发&#xff0c;按照官方文档Web组件文档《使用Web组件加载页面》示例中的代码照抄运行后显示空白&#xff0c;纠结之余多方搜索后扔无解决方法。 运行代码 import web_webview from ohos.web.webviewEntry Component struct Index {controller: web_webv…...

【Java】网络编程-UDP回响服务器客户端简单代码编写

这一篇文章我们将讲述网络编程中UDP服务器客户端的编程代码 1、前置知识 UDP协议全称是用户数据报协议&#xff0c;在网络中它与TCP协议一样用于处理数据包&#xff0c;是一种无连接的协议。 UDP的特点有&#xff1a;无连接、尽最大努力交付、面向报文、没有拥塞控制 本文讲…...

【设计模式】之工厂模式

工厂模式 1.介绍 工厂模式&#xff08;创建型模式&#xff09;&#xff0c;是我们最常用的实例化对象模式&#xff0c;是用工厂方法代替new操作的一种模式&#xff1b;在工厂模式中&#xff0c;我们在创建对象时不会对客户端暴露创建逻辑&#xff0c;并且是通过使用一个共同的…...

70.爬楼梯

题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 注意&#xff1a; 给定 n 是一个正整数。 示例 1: 输入&#xff1a; 2 输出&#xff1a; 2 解释&#xff1a; 有两种方法可以爬到楼顶…...

【论文解读】ICLR 2024高分作:ViT需要寄存器

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://arxiv.org/abs/2309.16588 摘要&#xff1a; Transformer最近已成为学习视觉表示的强大工具。在本文中&#xff0c;我们识别并表征监督和自监督 ViT 网络的特征图中的伪影。这些…...

【Redis】AOF 基础

因为 Redis AOF 的实现有些绕, 就分成 2 篇进行分析, 本篇主要是介绍一下 AOF 的一些特性和依赖的其他函数的逻辑,为下一篇 (Redis AOF 源码) 源码分析做一些铺垫。 AOF 全称: Append Only File, 是 Redis 提供了一种数据保存模式, Redis 默认不开启。 AOF 采用日志的形式来记…...

C语言—每日选择题—Day50

一天一天的更新&#xff0c;也是达到50天了&#xff0c;精选的题有250道&#xff0c;博主累计做了不下500道选择题&#xff0c;最喜欢的题型就是指针和数组之间的计算呀&#xff0c;不知道关注我的小伙伴是不是一直在坚持呢&#xff1f;文末有投票&#xff0c;大家可以投票让博…...

[C/C++]——内存管理

学习C/C的内存管理 前言&#xff1a;一、C/C的内存分布二、C语言中动态内存管理方式三、C中动态内存管理方式3.1、new/delete操作符3.1.2、new/delete操作内置类型3.1.3、new/delete操作自定义类型 3.2、认识operator new和operator delete函数3.3、了解new和delete的实现原理3…...

PDF文件的限制编辑,如何设置?

想要给PDF文件设置一个密码防止他人对文件进行编辑&#xff0c;那么我们可以对PDF文件设置限制编辑&#xff0c;设置方法很简单&#xff0c;我们在PDF编辑器中点击文件 – 属性 – 安全&#xff0c;在权限下拉框中选中【密码保护】 然后在密码保护界面中&#xff0c;我们勾选【…...

Linux 中使用 docker 安装 Elasticsearch 及 Kibana

Linux 中使用 docker 安装 Elasticsearch 及 Kibana 安装 Elasticsearch 和 Kibana安装分词插件 ik_smart 安装 Elasticsearch 和 Kibana 查看当前运行的镜像及本地已经下载的镜像&#xff0c;确认之前没有安装过 ES 和 Kibana 镜像 docker ps docker images从远程镜像仓库拉…...

在Flutter中使用PhotoViewGallery指南

介绍 Flutter中的PhotoViewGallery是一个功能强大的插件&#xff0c;用于在应用中展示可缩放的图片。无论是构建图像浏览器、相册应用&#xff0c;还是需要在应用中查看大图的场景&#xff0c;PhotoViewGallery都是一个不错的选择。 添加依赖 首先&#xff0c;需要在pubspec…...

c语言中的static静态(1)static修饰局部变量

#include<stdio.h> void test() {static int i 1;i;printf("%d ", i); } int main() {int j 0;while (j < 5){test();j j 1;}return 0; } 在上面的代码中&#xff0c;static修饰局部变量。 当用static定义一个局部变量后&#xff0c;这时局部变量就是…...

生信算法4 - 获取overlap序列索引和序列的算法

生信序列基本操作算法 建议在Jupyter实践&#xff0c;python版本3.9 1. 获取overlap序列索引和序列的算法实现 # min_length 最小overlap碱基数量3个 def getOverlapIndexAndSequence(a, b, min_length3):""" Return length of longest suffix of a matching…...

springboot 学习网站

Spring Boot 系列教程https://www.docs4dev.com/ Spring Boot 教程汇总 http://www.springboot.wiki/ Spring Cloud 微服务教程 http://www.springboot.wiki/ 1、自定义banner   https://www.cnblogs.com/cc11001100/p/7456145.html 2、事件和监听器   https://blog.csd…...

论文笔记:A review on multi-label learning

一、介绍 传统的监督学习是单标签学习&#xff0c;但是现实中一个实例可能对应多个标签。这篇文章介绍了多标签分类的定义和评价指标、多标签学习的算法还有其他相关的任务。 二、问题相关定义 2.1 多标签学习任务 假设 X R d X R^d XRd&#xff0c;表示d维的输入空间&am…...

接口文档 YAPI介绍

YAPI介绍 YAPI使用流程...

LeetCode 300最长递增子序列 674最长连续递增序列 718最长重复子数组 | 代码随想录25期训练营day52

动态规划算法10 LeetCode 300 最长递增子序列 2023.12.15 题目链接代码随想录讲解[链接] int lengthOfLIS(vector<int>& nums) {//创建变量result存储最终答案,设默认值为1int result 1;//1确定dp数组&#xff0c;dp[i]表示以nums[i]为结尾的子数组的最长长度ve…...

Improving IP Geolocation with Target-Centric IP Graph (Student Abstract)

ABSTRACT 准确的IP地理定位对于位置感知的应用程序是必不可少的。虽然基于以路由器为中心(router-centric )的IP图的最新进展被认为是前沿的,但一个挑战仍然存在:稀疏IP图的流行(14.24%,少于10个节点,9.73%孤立)限制了图的学习。为了缓解这个问题,我们将目标主机(ta…...

华为技面三轮面试题

1. 最长回文子串 -- 中心扩散法 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。 如果字符串的反序与原始字符串相同&#xff0c;则该字符串称为回文字符串。 示例 1&#xff1a; 输入&#xff1a;s "babad" 输出&#xff1a;"bab" 解释&…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用

一、方案背景​ 在现代生产与生活场景中&#xff0c;如工厂高危作业区、医院手术室、公共场景等&#xff0c;人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式&#xff0c;存在效率低、覆盖面不足、判断主观性强等问题&#xff0c;难以满足对人员打手机行为精…...

Unity VR/MR开发-VR开发与传统3D开发的差异

视频讲解链接&#xff1a;【XR马斯维】VR/MR开发与传统3D开发的差异【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...