分布式系统中常用的缓存方案

news2024/11/24 22:29:52

1. 引言

随着互联网应用的发展和规模的不断扩大,分布式系统中的缓存成为了提升性能和扩展性的重要手段之一。本文将介绍几种在分布式系统中常用的缓存方案,包括分布式内存缓存、分布式键值存储、分布式对象存储和缓存网关等。

1.1 缓存在分布式系统中的重要性

在分布式系统中,缓存起着至关重要的作用。随着互联网应用的不断发展和用户数量的增加,分布式系统面临着诸多挑战,包括高并发访问、大数据量处理和系统性能优化等。缓存作为一种提高系统性能和可伸缩性的重要手段,在分布式系统中发挥着重要作用,具有以下几个方面的重要性:

  • 提高访问速度: 在分布式系统中,数据存储往往分布在不同的节点和数据中心中,网络延迟和数据传输时间成为影响系统性能的关键因素。通过将数据缓存到靠近用户的位置,可以大大减少数据传输时间,提高用户访问速度。

  • 降低数据库负载: 分布式系统中的数据库往往面临着高并发读写请求,而数据库的读写操作是相对较慢的,容易成为系统的瓶颈。通过将热点数据或频繁访问的数据缓存到内存中,可以减少对数据库的读写请求,降低数据库负载,提高系统的并发处理能力。

  • 提高系统可用性: 缓存可以将数据复制到多个节点中,实现数据的备份和冗余存储,当某个节点发生故障或网络故障时,可以自动切换到其他节点,提高系统的可用性和容错性。

  • 减少外部依赖: 分布式系统中往往依赖于外部服务或第三方接口,如支付服务、地图服务等。通过缓存外部接口返回的数据,可以减少对外部服务的依赖,提高系统的稳定性和可靠性。

1.2 缓存方案的选择对系统性能的影响

在设计分布式系统时,选择合适的缓存方案对系统的性能和可伸缩性有着重要的影响。不同的缓存方案具有不同的特点和适用场景,正确选择缓存方案可以有效提高系统的性能,并且降低系统的复杂度和维护成本。

1.2.1 性能影响
  • 读写速度: 不同的缓存方案对读写速度有着不同的影响。本地缓存通常具有较快的读写速度,适用于频繁读取的数据;而分布式缓存虽然具有分布式的优势,但通常会牺牲一定的读写速度来实现数据的分布式存储和高可用性。

  • 数据一致性: 在选择缓存方案时,需要考虑数据一致性的问题。本地缓存通常不具备数据一致性保证,而分布式缓存可以通过一致性哈希算法等方式来保证数据一致性,但可能会牺牲一定的性能。

1.2.2 可伸缩性影响
  • 水平扩展: 不同的缓存方案对系统的水平扩展能力有着不同的影响。分布式缓存通常具有较好的水平扩展能力,可以通过增加节点来扩展系统的处理能力;而本地缓存通常不具备水平扩展能力,需要在单节点上处理所有的请求。

  • 节点故障容错: 在分布式环境中,节点故障是常态,选择合适的缓存方案可以降低节点故障对系统的影响。分布式缓存通常具有较好的节点故障容错能力,可以通过复制数据和备份节点来提高系统的可用性。

1.2.3 维护成本影响
  • 部署和管理: 不同的缓存方案对系统的部署和管理成本有着不同的影响。本地缓存通常具有较低的部署和管理成本,适用于小规模系统;而分布式缓存通常需要较多的节点和复杂的部署和管理工作,适用于大规模系统。

2. 缓存方案概述

在设计分布式系统时,选择合适的缓存方案对系统的性能和可伸缩性至关重要。以下是常见的几种缓存方案的概述:

常用的缓存架构

2.1 本地缓存

本地缓存是指将数据缓存在应用程序的本地内存中,以减少对后端数据存储系统的访问。本地缓存通常具有快速读取和写入的特点,适用于频繁访问的数据和对数据一致性要求不高的场景。常见的本地缓存包括内存缓存(如Caffeine、Guava Cache)和文件缓存(如Ehcache)等。

2.2 分布式缓存

分布式缓存是指将数据缓存在分布式环境中的多个节点上,以提高数据访问的速度和可伸缩性。分布式缓存通常具有数据分片、负载均衡和高可用性的特点,适用于大规模分布式系统和高并发访问的场景。常见的分布式缓存包括Redis、Memcached、Hazelcast和Apache Ignite等。

2.3 内存数据库

内存数据库是指将数据存储在内存中,以提高数据访问的速度和响应性能。内存数据库通常具有快速的读写能力、高并发访问和数据持久化的特点,适用于对数据一致性要求较高的场景。常见的内存数据库包括Apache Geode、Aerospike和VoltDB等。

2.4 缓存网关

缓存网关是指将缓存部署在反向代理服务器或负载均衡器上,以提高静态资源的访问速度和可用性。缓存网关通常具有缓存内容的动态更新、请求缓存和缓存失效策略等特点,适用于静态资源访问频繁的场景。常见的缓存网关包括Varnish、Squid和NGINX等。

本地缓存是将数据缓存在应用程序的本地内存中,以减少对后端数据存储系统的访问。在分布式系统中,本地缓存通常位于每个应用程序实例的内存中,可以提高数据访问速度和减轻后端存储系统的负载。

3.1 特点与优势

  • 快速读写: 本地缓存直接存储在应用程序的内存中,读写速度快,响应时间低。
  • 降低后端负载: 本地缓存可以减少对后端数据存储系统的访问,降低后端系统的负载压力。
  • 易于实现和管理: 本地缓存通常易于实现和管理,无需额外的部署和配置。
  • 适用于小规模系统: 对于小规模系统或者对数据一致性要求不高的场景,本地缓存是一种简单有效的解决方案。

3.2 适用场景

本地缓存适用于以下场景:

  • 频繁读取的数据: 对于频繁读取的数据,可以将其缓存到本地内存中,提高数据访问速度。
  • 临时数据: 对于临时性的数据,如用户登录信息、临时计算结果等,可以缓存在本地内存中,减少对后端存储系统的访问。
  • 数据一致性要求不高的场景: 对于对数据一致性要求不高的场景,如页面静态数据、临时计算结果等,可以使用本地缓存。

3.3 使用示例与实践

在一个电子商务系统中,需要缓存商品信息,并且希望能够在缓存中设置过期时间,以保证缓存数据的及时性和一致性。以下是一个使用本地缓存(Guava Cache)的示例:

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import java.util.concurrent.TimeUnit;

public class ProductCacheExample {

    // 创建本地缓存实例
    private static Cache<Long, Product> productCache = CacheBuilder.newBuilder()
            .maximumSize(1000) // 设置最大缓存数量
            .expireAfterWrite(30, TimeUnit.MINUTES) // 设置缓存过期时间
            .build();

    // 模拟从数据库或其他数据源中加载商品信息
    private static Product loadProductFromDatabase(long productId) {
        // 这里假设从数据库中加载商品信息
        // 实际应用中可以根据业务需求进行具体实现
        return new Product(productId, "Product " + productId, 100.0);
    }

    // 根据商品ID获取商品信息(先从缓存中获取,如果缓存中不存在则从数据库中加载)
    public static Product getProductById(long productId) {
        try {
            // 尝试从缓存中获取商品信息
            Product product = productCache.get(productId, () -> loadProductFromDatabase(productId));
            return product;
        } catch (Exception e) {
            e.printStackTrace();
            // 缓存中不存在商品信息,从数据库中加载
            return loadProductFromDatabase(productId);
        }
    }

    public static void main(String[] args) {
        // 模拟获取商品信息
        long productId = 12345L;
        Product product = getProductById(productId);
        System.out.println("Product Name: " + product.getName());
    }

    // 商品实体类
    static class Product {
        private long id;
        private String name;
        private double price;

        public Product(long id, String name, double price) {
            this.id = id;
            this.name = name;
            this.price = price;
        }

        public long getId() {
            return id;
        }

        public String getName() {
            return name;
        }

        public double getPrice() {
            return price;
        }
    }
}

实践建议:

  • 根据业务需求和数据特性选择合适的本地缓存库,如Caffeine、Guava Cache等。
  • 设定合适的缓存大小、过期策略和缓存淘汰策略,以平衡内存使用和缓存命中率。
  • 对于频繁更新的数据,考虑使用缓存更新策略,如定时刷新缓存、异步更新缓存等,以保持缓存数据的及时性和一致性。
  • 监控和调优本地缓存的使用情况,及时发现并解决缓存使用过程中的性能问题和内存泄漏问题。

在分布式系统中,缓存是一种重要的数据存储和访问方式,用于提高系统性能和可扩展性。本节将介绍分布式缓存的特点与优势,常见的分布式缓存方案,以及一些使用示例与实践。

4.1 特点与优势

分布式缓存具有以下特点与优势:

  • 高性能: 缓存数据存储在内存中,读写速度快,能够有效降低数据访问的延迟。
  • 可扩展性: 分布式缓存可以水平扩展,通过添加更多的节点来增加存储容量和吞吐量。
  • 高可用性: 分布式缓存通常具有复制和故障转移机制,能够保证数据的可靠性和服务的可用性。
  • 降低数据库负载: 缓存可以减轻数据库的负载,提高数据库的性能和吞吐量。
  • 缓解流量峰值: 缓存可以缓解系统的流量峰值,减少对后端服务的压力。

4.2 常见的分布式缓存方案

常见的分布式缓存方案包括:

  • Redis: Redis 是一个开源的内存数据结构存储,支持多种数据结构(如字符串、列表、哈希表等),并提供持久化功能。Redis 通过主从复制和分片技术实现数据的分布式存储和高可用性。

  • Memcached: Memcached 是一个高性能的分布式内存对象缓存系统,主要用于缓存数据和减轻数据库负载。Memcached 基于内存存储,支持键值对的存储,并提供简单的 API 接口。

  • Hazelcast: Hazelcast 是一个开源的分布式内存数据网格,提供了分布式数据结构和集群管理功能,可以用于缓存、数据存储和分布式计算。

  • Apache Ignite: Apache Ignite 是一个内存中数据网格平台,提供了分布式缓存、分布式计算和分布式存储等功能,支持 SQL 查询和事务处理。

4.3 使用示例与实践

Redis 实现分布式缓存的示例:

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class RedisCacheExample {
    private static final String REDIS_HOST = "localhost";
    private static final int REDIS_PORT = 6379;

    public static void main(String[] args) {
        // 创建 Redis 连接池配置
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(100); // 最大连接数
        poolConfig.setMaxIdle(50); // 最大空闲连接数
        poolConfig.setMinIdle(10); // 最小空闲连接数

        // 创建 Redis 连接池
        try (JedisPool jedisPool = new JedisPool(poolConfig, REDIS_HOST, REDIS_PORT)) {
            // 从连接池获取 Jedis 实例
            try (Jedis jedis = jedisPool.getResource()) {
                // 设置缓存数据
                jedis.set("key", "value");

                // 获取缓存数据
                String value = jedis.get("key");
                System.out.println("缓存数据:" + value);
            }
        }
    }
}

5. 缓存网关

缓存网关是位于客户端和后端数据源之间的缓存层,用于加速数据访问和减轻后端负载。本节将介绍缓存网关的特点与优势,常见的缓存网关方案,以及使用示例与实践。

5.1 特点与优势

缓存网关通常具有以下特点与优势:

  • 提高性能与加速访问: 缓存网关可以缓存静态内容和动态内容的副本,提高数据访问的速度,加速网站的响应时间。
  • 减轻后端负载: 缓存网关可以将请求拦截并直接返回缓存中的数据,从而减轻后端服务器的负载,提高系统的性能和可扩展性。
  • 提高系统可用性: 缓存网关具有缓存失效、数据更新等功能,能够保证数据的一致性和系统的可用性。
  • 灵活的配置选项: 缓存网关通常提供了灵活的配置选项,可以根据业务需求进行缓存策略、缓存时间等参数的调整。

5.2 常见的缓存网关方案

常见的缓存网关方案包括:

  • Varnish: Varnish 是一个高性能的 HTTP 缓存代理,主要用于加速 Web 服务的访问速度。它通过缓存静态内容和动态内容的副本来减轻后端服务器的负载,提高网站的性能和可扩展性。

  • NGINX: NGINX 是一个轻量级的 Web 服务器和反向代理服务器,常用于负载均衡和缓存加速。它提供了灵活的配置选项和高性能的缓存功能,可以缓存静态内容和动态内容的副本,提高数据访问的速度。

5.3 使用示例与实践

使用 NGINX 缓存网关的示例配置:

# 定义一个名为 cache 的缓存路径和配置
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cache:10m max_size=10g inactive=60m;

# 定义一个名为 backend 的后端服务器
upstream backend {
    server localhost:8080;
}

# 定义一个名为 cache_proxy 的服务器
server {
    listen 80;
    server_name example.com;

    # 配置缓存规则
    location / {
        proxy_pass http://backend;
        proxy_cache cache;
        proxy_cache_valid 200 304 10m;
        proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
        proxy_cache_bypass $http_cache_control;
        add_header X-Cache $upstream_cache_status;
    }
}

6. 总结

缓存方案在提升系统性能、减轻后端负载以及改善用户体验方面发挥着重要作用。不同的缓存方案具有各自的优点和缺点,需要根据具体的业务需求和场景来选择合适的方案。

内存数据库提供了高性能的数据存储和丰富的数据结构支持,适用于对读写速度要求高的场景;

分布式缓存具有良好的可扩展性和高可用性,适用于大规模数据存储和高并发访问的场景;

缓存网关能够减轻后端负载、提高数据访问速度,适用于缓存静态内容和动态内容的副本,但在动态数据更新频繁的场景效果有限。

下面是缓存方案对比

缓存方案优点缺点
内存数据库

- 高性能:数据存储在内存中,读写速度快。

- 丰富的数据结构支持:支持多种数据结构,如字符串、列表、哈希表等。

- 持久化功能:支持数据的持久化到磁盘,确保数据不丢失。

- 成本较高:存储成本较高,需要足够的内存资源。

- 容量限制:受限于单机内存容量,无法存储大规模数据。

- 需要备份和恢复机制:一旦服务器宕机,数据可能会丢失,需要定期备份和恢复。

分布式缓存

- 可扩展性:可以水平扩展,通过添加更多的节点来增加存储容量和吞吐量。

- 高可用性:通过主从复制和分片技术实现数据的分布式存储和高可用性。

- 低延迟:部署在集群中,能够实现低延迟的数据访问。

- 配置和管理复杂:需要考虑分片、复制、负载均衡等问题,部署和维护成本较高。

- 数据一致性:分布式环境下,数据一致性可能会受到影响,需要考虑数据同步和一致性问题。

缓存网关

- 减轻后端负载:将请求拦截并直接返回缓存中的数据,减轻后端服务器的负载。

- 提高性能:缓存静态内容和动态内容的副本,提高数据访问的速度。

- 灵活配置:根据业务需求进行灵活的缓存策略配置。

- 不适用于动态数据:适用于缓存静态内容和动态内容的副本,对于动态数据更新频繁的场景效果有限。

- 配置复杂:需要根据具体的业务需求进行灵活的缓存策略配置,配置复杂度较高。


更多文章

架构设计:生产消费模型-CSDN博客

RabbitMQ入门实战-CSDN博客

presto/trino 入门介绍实战_presto和trino怎么选-CSDN博客

MongoDB入门介绍与实战-CSDN博客

Netty入门与实战教程_netty教程-CSDN博客

Nacos入门介绍与使用_怎么找到nacos的控制台-CSDN博客

ElasticSearch入门介绍和实战-CSDN博客

JMM内存屏障和逃逸分析详解-CSDN博客

分布式任务调度:XXL-Job入门介绍实战-CSDN博客

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

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

相关文章

FEP容量瓶多应用于制药光电光伏行业

常用规格&#xff1a;25ml、50ml、100ml、250mlFEP容量瓶也叫特氟龙容量瓶&#xff0c;容量瓶是为配制一定物质的量浓度的溶液用的精确定容器皿&#xff0c;常和移液管配合使用。广泛用于ICP-MS、ICP-OES等痕量分析以及同位素分析等高端实验。地质、电子化学品、半导体分析测试…

挑战杯 基于深度学习的动物识别 - 卷积神经网络 机器视觉 图像识别

文章目录 0 前言1 背景2 算法原理2.1 动物识别方法概况2.2 常用的网络模型2.2.1 B-CNN2.2.2 SSD 3 SSD动物目标检测流程4 实现效果5 部分相关代码5.1 数据预处理5.2 构建卷积神经网络5.3 tensorflow计算图可视化5.4 网络模型训练5.5 对猫狗图像进行2分类 6 最后 0 前言 &#…

安防摄像头(IPC)的步进马达及IR-CUT驱动国产芯片——D6212

应用领域 安防摄像头&#xff08;IPC&#xff09;的步进马达及IR-CUT驱动。 02 功能介绍 D6212内置8路带有续流二极管的达林顿驱动管阵列和一个H桥驱动&#xff0c;单芯片即可实现2个步进电机和一个IR-CUT的直接驱动&#xff0c;使得电路应用非常简单。单个达林顿管在输入电…

android开发教程百度网盘,高并发系统基础篇

展望未来 操作系统 移动操作系统的演变过程&#xff0c;从按键交互的塞班功能机到触摸屏交互的Android/IOS智能机&#xff0c;从小屏幕手机到全面屏、刘海屏、水滴屏。任何系统无非干两件事&#xff1a;输入和输出&#xff0c;接收到外部输入信号后经过操作系统处理后输出信息…

如何减少AI中的偏见问题:八种方法避免AI偏见渗入模型

克服与避免 AI 偏见的八大方法 AI 中的算法偏见是一个普遍存在的问题&#xff0c;它虽然不可能完全消除&#xff0c;但却可以通过科学的方法积极地防止这种偏见。我们将在本文中围绕如何应对AI中的偏见问题展开深入的讨论。 您可能会回想起新闻中报道的一些存在偏见的算法示例…

深入理解RAM与ROM:计算机存储技术的核心

深入理解RAM与ROM&#xff1a;计算机存储技术的核心 在计算机科学领域&#xff0c;理解各种存储技术对于开发和维护高效、可靠的系统至关重要。本文旨在深入探讨两种基础且关键的存储形式&#xff1a;随机存取存储器&#xff08;RAM&#xff09;和只读存储器&#xff08;ROM&am…

每日一练:LeeCode-面试题 02.07. 链表相交 【链表+迭代】 LeeCode-142. 环形链表 II【链表+集合】

每日一练&#xff1a;LeeCode-面试题 02.07. 链表相交 【链表迭代】 LeeCode-142. 环形链表 II【链表集合】 LeeCode-面试题 02.07. 链表相交思路 LeeCode-142. 环形链表 II思路set集合方法 本文是力扣 每日一练&#xff1a;每日一练&#xff1a;LeeCode-面试题 02.07. 链表相交…

全自动气象站的工作原理

TH-CQX5全自动气象站是一款野外高精度监测气象数据的环境气象站设备。它结合了先进的传感器技术、自动化控制系统和远程通信技术&#xff0c;能够提供准确、实时的气象数据&#xff0c;为环境保护、气象研究、农业生产等领域提供重要的数据支持。 高精度传感器&#xff1a;全自…

PSINS工具箱笔记——函数定义

绘图函数&#xff1a; 时间进度条&#xff1a; timebar&#xff08;用起来简单&#xff09; 姿态转换&#xff1a; 欧拉角、姿态矩阵、等效旋转矩阵、姿态四元数、运载火箭使用的欧拉角之间的转换。 轨迹生成&#xff1a; seg trjsegment(seg, segtype, lasting, w, a, var…

BUUCTF-Misc-百里挑一

题目链接&#xff1a;BUUCTF在线评测 (buuoj.cn) 下载附件打开是一个流量包文件&#xff1a; 全是在传图片时候的流量&#xff0c;先把图片保存出来文件–>导出对象–>HTTP–>保存到一个文件夹 然后使用kali下的exiftool找到了一半flag exiftool *|grep flag 另外一半…

【C语言】编程题专项练习+答案

目录 1.删除有序数组中重复的数 2.用除二取余的方法&#xff0c;把任意一个十进制正数的二进制序列输出&#xff08;不考虑溢出&#xff09; 2.1如果是把任意一个十进制整数的二进制序列输出呢&#xff1f; 3.输出一个六行六列的整形矩阵&#xff0c;并输出其转置矩阵。矩阵…

保修期内经营者收取维修费用应遵循正当程序原则

↑↑↑“上海高院”头条号为您讲述精彩的法律科普内容 上海市第一中级人民法院在履行司法审判职能的同时&#xff0c;始终高度重视高质量案件工作&#xff0c;总结司法审判经验&#xff0c;努力提高司法审判质量。 在2020年全国法院系统优秀案例分析评选活动中&#xff0c;上海…

伟大音乐家的伟大不朽作品,贝多芬一生的音乐作品全集

一、音乐描述 贝多芬一生创作题材广泛&#xff0c;重要作品包括9部交响曲、1部歌剧、32首钢琴奏鸣曲、5首钢琴协奏曲、多首管弦乐序曲及小提琴、大提琴奏鸣曲等。因为其对古典音乐的重大贡献&#xff0c;以及对奏鸣曲式和交响曲套曲结构的发展和创新&#xff0c;而被后世尊称为…

【Flutter 面试题】main()和runApp()函数在Flutter的作用分别是什么?有什么关系吗?

【Flutter 面试题】main()和runApp()函数在Flutter的作用分别是什么&#xff1f;有什么关系吗&#xff1f; 文章目录 写在前面解答补充说明 写在前面 关于我 &#xff0c;小雨青年 &#x1f449; CSDN博客专家&#xff0c;GitChat专栏作者&#xff0c;阿里云社区专家博主&…

STM32CubeMX学习笔记11 ---RTC实时时钟

1、RTC实时时钟简介 STM32的实时时钟RTC是一个独立的定时器&#xff0c;RTC模块拥有一组连续计数的计数器&#xff0c;在相应软件配置下&#xff0c;可提供时钟日历的功能&#xff0c;修改计数器的值可以重新设置系统当前的时间和日期 RTC模块和时钟配置系统&#xff08;RCC_B…

Python-Numpy-计算矩阵相乘

向量化矩阵计算公式&#xff1a; """ Title: matrix_calculating Time: 2024/3/6 Author: Michael Jie """import numpy as npw np.array([[1, 2]]) x np.array([[1, 1], [2, 3], [4, 5]]) b 1# w * x b print(w * x b) """…

msvcp120.dll丢失的解决方法,教你快速解决msvcp120.dll问题

msvcp120.dll是一个在Windows操作系统中至关重要的系统文件&#xff0c;它属于Microsoft Visual C Redistributable Package的一部分。这个动态链接库文件&#xff08;DLL&#xff09;包含了运行某些应用程序所必需的C运行时库函数。当某个程序在运行过程中需要调用这些预先编译…

限流算法(固定窗口、滑动窗口、漏桶算法、令牌桶算法)

固定窗口算法 计数器算法是使用计数器在周期内累加访问次数&#xff0c;当达到设定的限流值时&#xff0c;触发限流策略。下一个 周期开始时&#xff0c;进行清零&#xff0c;重新计数。 如下图所示&#xff0c;每个三秒的时间区间内&#xff0c;限定访问次数150次&#xff0c…

兰州做手机网站建设的8个注意点分享给大家

随着移动网络的日益发达&#xff0c;兰州移动网站建设已经成为移动互联网的热点&#xff0c;但很多用户对兰州移动网站制作仍然知之甚少。 今天小编总结了兰州手机网站建设的8个技巧&#xff0c;请关注&#xff0c;分享给大家。 1.根据用户需求分析网站 在兰州建设手机网站时…

FEP样品瓶透明聚四氟乙烯取样瓶

一、产品介绍 FEP试剂瓶&#xff0c;也叫FEP取样瓶、特氟龙样品瓶等&#xff0c;主要用于痕量分析、同位素检测&#xff0c;ICP-MS/OES/AAS分析等高端实验。本底值低&#xff0c;金属元素铅、铀含量小于0.01ppb,无溶出与析出。 常用尺寸&#xff08;ml&#xff09;&#xff1…