mongodb副本集部署及springboot集成

news2025/1/9 14:18:35

一、mongodb应用安装

1、官网下载mongodb的社区版

https://www.mongodb.com/try/download/community

2、离线安装

将下载好的mongodb安装包上传至服务器指定目录病解压

(1)配置环境变量
export MONGO_HOME=/home/master/mongodb/mongo
export PATH=$MONGO_HOME/bin:$MONGO_HOME/sbin:$PATH

(2)测试环境

 mongo  --version

二、mongodb副本集部署

官方操作文档https://www.mongodb.com/docs/manual/

MongoDB中的副本集(Replica Set)是一组维护相同数据集的mongod服务。 副本集可提供冗余和高可用性,副本集能够自动故障恢复功能的主从集群。通俗的讲就是用多台机器进行同一数据的异步同步,从而使多台机器拥有同一数据的多个副本,并且当主库当掉时在不需要用户干预的情况下自动切换其他备份服务器做主库。而且还可以利用副本服务器做只读服务器,实现读写分离,提高负载。

    • mongodb副本集类型、角色

副本集有两种类型三种角色

(1)两种类型:

主节点(Primary)类型:数据操作的主要连接点,可读写;

从节点(Secondaries)类型:数据冗余备份节点,可以读或选举。

(2)三种角色:

主要成员(Primary)主要接收所有写操作。就是主节点。

副本成员(Replicate)从主节点通过复制操作以维护相同的数据集,即备份数据,不可写操 作,但可以读操作(但需要配置)。是默认的一种从节点类型。

仲裁者(Arbiter):不保留任何数据的副本,只具有投票选举作用,是非必要节点。当然也可以

将仲裁服务器维护为副本集的一部分,即副本成员同时也可以是仲裁者。也是一种从节点类型。

2、副本集架构图

(1)冗余

复制提供冗余并提高数据可用性。 通过在不同数据库服务器上提供多个数据副本,复制可提供一定级别的容错功能,以防止丢失单个数据库服务器。在某些情况下,复制可以提供增加的读取性能,因为客户端可以将读取操作发送到不同的服务上, 在不同数据中心维护数据副本可以增加分布式应用程序的数据位置和可用性。 您还可以为专用目的维护其他副本,例如灾难恢复,报告或备份。

(2)复制

副本集是一组维护相同数据集的mongod实例。 副本集包含多个数据承载节点和可选的一个仲裁节点。在承载数据的节点中,一个且仅一个成员被视为主节点,而其他节点被视为次要(从)节点。主节点接收所有写操作。 副本集只能有一个主要能够确认具有{w:“most”}写入关注的写入; 虽然在某些情况下,另一个mongod实例可能暂时认为自己也是主要的。主要记录其操作日志中的数据集的所有更改即oplog。辅助(副本)节点复制主节点的oplog并将操作应用于其数据集,以使辅助节点的数据集反映主节点的数据集。 如果主要人员不在,则符合条件的中学将举行选举以选出新的主要人员。

(3)主节点选举

主从集群整个集群会选出一个“主节点”,当其挂掉后,又在剩下的从节点中选中其他节点为“主节点”,副本集总有一个活跃点(主、primary)和一个或多个备份节点(从、secondary)。

当主节点不与集合的其他成员通信时 对于超过配置的electionTimeoutMillis周期(默认为 10 秒),符合条件的辅助调用 选举提名自己为新的初选。群集尝试 完成新主节点的选举并恢复正常操作。副本集无法处理写入操作 直到选举成功完成。副本集可以继续 提供读取查询(如果此类查询配置为在辅助数据库上运行而 主服务器处于脱机状态。集群选择新主数据库之前的中位数时间不应 通常超过 12 秒(假设默认值)replica configuration settings.这包括所需的时间 将主数据库标记为不能利用的和 调用并完成选举. 您可以通过修改settings.electionTimeoutMillis复制配置 选择。网络延迟等因素可能会延长所需的时间 要完成副本集选举,这反过来又会影响数量 您的集群可以在没有主集群的情况下运行。这些因素是 取决于您的特定群集体系结构。降低electionTimeoutMillis默认复制配置选项(10 秒) 可以更快地检测主故障。

3、副本集配置部署

在一台机器上模拟3个节点 :

192.168.81.200:27017 (Primary

192.168.81.200:28017 (Secondary

192.168.81.200:29017 (Arbiter

(1)3个节点配置文件

主节点:192.168.81.200:27017配置

# mongod.conf
storage:
  dbPath: /home/master/mongodb/s1/data
  journal:
    enabled: true
# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /home/master/mongodb/s1/log/mongod.log
processManagement:
  timeZoneInfo: /usr/share/zoneinfo
  fork: true
  pidFilePath: /home/master/mongodb/s1/log/mongodb.pid
# network interfaces
net:
  port: 27017
  bindIp: 0.0.0.0
#security:
replication:
  #副本集名称
  replSetName: wmyrs
#sharding:

从节点:192.168.81.200:28017配置

# mongod.conf
storage:
  dbPath: /home/master/mongodb/s2/data
  journal:
    enabled: true
# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /home/master/mongodb/s2/log/mongod.log
processManagement:
  timeZoneInfo: /usr/share/zoneinfo
  fork: true
  pidFilePath: /home/master/mongodb/s2/log/mongodb.pid
# network interfaces
net:
  port: 28017
  bindIp: 0.0.0.0
#security:
replication:
  #副本集名称
  replSetName: wmyrs
#sharding:

仲裁节点:192.168.81.200:29017配置

# mongod.conf
storage:
  dbPath: /home/master/mongodb/s3/data
  journal:
    enabled: true
# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /home/master/mongodb/s3/log/mongod.log
processManagement:
  timeZoneInfo: /usr/share/zoneinfo
  fork: true
  pidFilePath: /home/master/mongodb/s3/log/mongodb.pid
# network interfaces
net:
  port: 29017
  bindIp: 0.0.0.0
#security:
replication:
  #副本集名称
  replSetName: wmyrs
#sharding:
(2)副本集实例启动脚本
#!/bin/bash
dir=/home/master/mongodb
ports=(27017 28017 29017)
subDir=("s1" "s2" "s3")
function sotpAndStart(){
   pidStr=`netstat -tulnp | grep  $1 | awk '{print $7}'`
   arr1=(${pidStr//\/})
   arr1_0=${arr1[0]}
   arr2=(${arr1_0//$appName/})
 
   pid=${arr2[0]}
   echo  "正在运行$appNmae port:$1 pid:$pid"
   
   if [[ -z $pid ]]; then
      echo "port:$1 $appName 实例挂起"
   else
      echo "port:$1 $appName 关闭实例"
      kill  $pid
   fi

   rm -f  $2/data/mongod.lock
   nohup  $appName  --config   $2/my.conf  >> $2/log/start.log 2>&1 &
   netstat  -tulnp | grep  $1
 
   echo "mongod...$1启动成功"
}

function start(){
   for((i=0;i<3;i++));do
     stopAndStart ${ports[i]}  $dir/${subDir[i]}
   done;
}

start

查看运行状态

ps  -ef  |  grep  mongod
(3)副本集节点设置

客户端连接mongo服务

nongo  --host  192.168.81.200 --port 27017

初始化副本集

rs.initiate()

设置主节点

rs.conf()
wmyrs:SECONDARY> rs.conf()
{
     "_id" : "wmyrs",
     "version" : 1,
     "term" : 1,
     "members" : [
        {
                "_id" : 0,
                "host" : "master:27017",
                "arbiterOnly" : false,
                "buildIndexes" : true,
                "hidden" : false,
                "priority" : 1,
                "tags" : {

                },
                "secondaryDelaySecs" : NumberLong(0),
                "votes" : 1
        }
     ],
     "protocolVersion" : NumberLong(1),
     "writeConcernMajorityJournalDefault" : true,
     "settings" : {
        "chainingAllowed" : true,
        "heartbeatIntervalMillis" : 2000,
        "heartbeatTimeoutSecs" : 10,
        "electionTimeoutMillis" : 10000,
        "catchUpTimeoutMillis" : -1,
        "catchUpTakeoverDelayMillis" : 30000,
        "getLastErrorModes" : {

        },
        "getLastErrorDefaults" : {
                "w" : 1,
                "wtimeout" : 0
        },
        "replicaSetId" : ObjectId("63db7ee718a2e77c350605f4")
     }
}

添加从节点

rs.add("192.168.81.200:28017")
{
     "ok" : 1,
     "$clusterTime" : {
        "clusterTime" : Timestamp(1675329599, 1),
        "signature" : {
                "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                "keyId" : NumberLong(0)
        }
     },
     "operationTime" : Timestamp(1675329599, 1)
}

添加仲裁节点

rs.addArb("192.168.81.200:29017")
{
     "ok" : 1,
     "$clusterTime" : {
        "clusterTime" : Timestamp(1675330868, 1),
        "signature" : {
                "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                "keyId" : NumberLong(0)
        }
     },
     "operationTime" : Timestamp(1675330868, 1)
}

如果添加仲裁节点失败,在主节点执行以下命令

{
     "ok" : 1,
     "$clusterTime" : {
        "clusterTime" : Timestamp(1675330868, 1),
        "signature" : {
                "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                "keyId" : NumberLong(0)
        }
     },
     "operationTime" : Timestamp(1675330868, 1)
}

查看副本集状态

rs.status()
{
     "set" : "wmyrs",
     "date" : ISODate("2023-02-02T09:43:31.565Z"),
     "myState" : 1,
     "term" : NumberLong(1),
     "syncSourceHost" : "",
     "syncSourceId" : -1,
     "heartbeatIntervalMillis" : NumberLong(2000),
     "majorityVoteCount" : 2,
     "writeMajorityCount" : 2,
     "votingMembersCount" : 3,
     "writableVotingMembersCount" : 2,
     "optimes" : {
        "lastCommittedOpTime" : {
                "ts" : Timestamp(1675331005, 1),
                "t" : NumberLong(1)
        },
        "lastCommittedWallTime" : ISODate("2023-02-02T09:43:25.880Z"),
        "readConcernMajorityOpTime" : {
                "ts" : Timestamp(1675331005, 1),
                "t" : NumberLong(1)
        },
        "appliedOpTime" : {
                "ts" : Timestamp(1675331005, 1),
                "t" : NumberLong(1)
        },
        "durableOpTime" : {
                "ts" : Timestamp(1675331005, 1),
                "t" : NumberLong(1)
        },
        "lastAppliedWallTime" : ISODate("2023-02-02T09:43:25.880Z"),
        "lastDurableWallTime" : ISODate("2023-02-02T09:43:25.880Z")
     },
     "lastStableRecoveryTimestamp" : Timestamp(1675330985, 1),
     "electionCandidateMetrics" : {
        "lastElectionReason" : "electionTimeout",
        "lastElectionDate" : ISODate("2023-02-02T09:14:15.686Z"),
        "electionTerm" : NumberLong(1),
        "lastCommittedOpTimeAtElection" : {
                "ts" : Timestamp(1675329255, 1),
                "t" : NumberLong(-1)
        },
        "lastSeenOpTimeAtElection" : {
                "ts" : Timestamp(1675329255, 1),
                "t" : NumberLong(-1)
        },
        "numVotesNeeded" : 1,
        "priorityAtElection" : 1,
        "electionTimeoutMillis" : NumberLong(10000),
        "newTermStartDate" : ISODate("2023-02-02T09:14:15.709Z"),
        "wMajorityWriteAvailabilityDate" : ISODate("2023-02-02T09:14:15.720Z")
     },
     "members" : [
        {
                "_id" : 0,
                "name" : "master:27017",
                "health" : 1,
                "state" : 1,
                "stateStr" : "PRIMARY",
                "uptime" : 12641,
                "optime" : {
                        "ts" : Timestamp(1675331005, 1),
                        "t" : NumberLong(1)
                },
                "optimeDate" : ISODate("2023-02-02T09:43:25Z"),
                "lastAppliedWallTime" : ISODate("2023-02-02T09:43:25.880Z"),
                "lastDurableWallTime" : ISODate("2023-02-02T09:43:25.880Z"),
                "syncSourceHost" : "",
                "syncSourceId" : -1,
                "infoMessage" : "",
                "electionTime" : Timestamp(1675329255, 2),
                "electionDate" : ISODate("2023-02-02T09:14:15Z"),
                "configVersion" : 4,
                "configTerm" : 1,
                "self" : true,
                "lastHeartbeatMessage" : ""
        },
        {
                "_id" : 1,
                "name" : "192.168.81.200:28017",
                "health" : 1,
                "state" : 2,
                "stateStr" : "SECONDARY",
                "uptime" : 1412,
                "optime" : {
                        "ts" : Timestamp(1675331005, 1),
                        "t" : NumberLong(1)
                },
                "optimeDurable" : {
                        "ts" : Timestamp(1675331005, 1),
                        "t" : NumberLong(1)
                },
                "optimeDate" : ISODate("2023-02-02T09:43:25Z"),
                "optimeDurableDate" : ISODate("2023-02-02T09:43:25Z"),
                "lastAppliedWallTime" : ISODate("2023-02-02T09:43:25.880Z"),
                "lastDurableWallTime" : ISODate("2023-02-02T09:43:25.880Z"),
                "lastHeartbeat" : ISODate("2023-02-02T09:43:30.904Z"),
                "lastHeartbeatRecv" : ISODate("2023-02-02T09:43:30.921Z"),
                "pingMs" : NumberLong(0),
                "lastHeartbeatMessage" : "",
                "syncSourceHost" : "master:27017",
                "syncSourceId" : 0,
                "infoMessage" : "",
                "configVersion" : 4,
                "configTerm" : 1
        },
        {
                "_id" : 2,
                "name" : "192.168.81.200:29017",
                "health" : 1,
                "state" : 7,
                "stateStr" : "ARBITER",
                "uptime" : 142,
                "lastHeartbeat" : ISODate("2023-02-02T09:43:30.904Z"),
                "lastHeartbeatRecv" : ISODate("2023-02-02T09:43:30.932Z"),
                "pingMs" : NumberLong(0),
                "lastHeartbeatMessage" : "",
                "syncSourceHost" : "",
                "syncSourceId" : -1,
                "infoMessage" : "",
                "configVersion" : 4,
                "configTerm" : 1
        }
     ],
     "ok" : 1,
     "$clusterTime" : {
        "clusterTime" : Timestamp(1675331005, 1),
        "signature" : {
                "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                "keyId" : NumberLong(0)
        }
     },
     "operationTime" : Timestamp(1675331005, 1)
}

添加从节点读权限

rs.secondaryOk()

三、spring boot 集成mongodb

    • 添加gradle依赖

implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
// testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb:2.7.8'

2、mongo副本集连接配置

@Bean
public MongoClient mongoClient() {
    return MongoClients.create("mongodb://192.168.81.200:27017,192.168.81.200:28017,192.168.81.200:29017/wmy_blog?replicaSet=wmyrs");
}

@Bean
public MongoTemplate  mongoTemplate(){
   return new MongoTemplate(mongoClient(),"wmy_blog");
 }

3、MongoTemplate操作增删改查

文档实体类

@Document("user")
public class UserDoc {

    @MongoId
    private String docId;

    private String  name;

    private int  age;

    private String  flag;

    public UserDoc() {

    }

    public UserDoc(String name, int age, String flag) {
        this.name = name;
        this.age = age;
        this.flag = flag;
    }

    public String getDocId() {
        return docId;
    }
}

添加文档数据

public   void  addUser(){
     List<UserDoc>  list  = new ArrayList<>();
     list.add(new UserDoc("LiuPing",34,"xx"));
     list.add(new UserDoc("LiuCui",31,"lk"));
     list.add(new UserDoc("GeJiaLi",33,"yz"));
     list.add(new UserDoc("ChenYingYing",36,"xx"));
     list.add(new UserDoc("YangDuan",34,"zp"));
     list.add(new UserDoc("ZhangTing",33,"hb"));
     list.add(new UserDoc("ZhaoYang",32,"hb"));
     list.add(new UserDoc("LiQian",33,"lk"));
     list.add(new UserDoc("WangWenJiao",31,"wfd"));
     list.add(new UserDoc("WangWenJiao",31,"wfd"));
     list.add(new UserDoc("YangWanWan",33,"ay"));
     list.add(new UserDoc("ZhouYuLing",33,"sq"));
     list.add(new UserDoc("PengHui",22,"xy"));
     list.forEach(e->mongoTemplate.save(e));
}

查询文档数据

public  List<UserDoc>  basicQueryUserList(){
   BasicQuery query  =new BasicQuery("{\"age\":{\"$gt\":33},\"flag\":\"xx\"}");
   return  mongoTemplate.find(query,UserDoc.class);
}

更新文档

 public void  updateUser(UserDoc  userDoc){
    Criteria criteria = new Criteria();
    criteria.and("docId").is(userDoc.getDocId());
    Query  query  = new Query(criteria);
    Update update = new Update().rename("age", "26");
    mongoTemplate.updateMulti(query, update, "user");
 }

删除文档

public void  removeUser(UserDoc  userDoc){
   mongoTemplate.remove(userDoc);
}

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

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

相关文章

自定义注解

如何实现自定义注解在我们实际开发过程中如果能合理的运用自定义注解&#xff0c;则会大大减少我们代码的开发量。那怎么才能实现自定义注解呢&#xff1f;废话不多说&#xff0c;直接上干货&#xff01;一、创建注解这一步呢&#xff0c;我们可以理解成对应的实体类&#xff0…

BetaFlight统一硬件资源抽象设计

BetaFlight统一硬件资源抽象设计1. 源由2. 资源配置注意事项3. 资源配置文件修改验证步骤Step 1&#xff1a;确认硬件修改内容Step 2&#xff1a;资源配置文件修改Step 3&#xff1a;验证配置文件Step 4&#xff1a;提交资源配置文件PR4. 参考资料就笔者接触嵌入式设计以来&…

ESP32设备驱动-MAX44009环境光传感器驱动

MAX44009环境光传感器驱动 文章目录 MAX44009环境光传感器驱动1、MAX44009介绍2、硬件准备3、软件准备4、驱动实现1、MAX44009介绍 MAX44009 环境光传感器具有 IC 数字输出,非常适合智能手机、笔记本电脑和工业传感器等多种便携式应用。 它的工作电流小于 1A,是业内功耗最低…

Springboot——Swagger

Swagger2 的 maven 依赖使用 Swagger2 工具&#xff0c;必须要导入 maven 依赖&#xff0c;当前官方最高版本是 2.8.0&#xff0c;我尝试了一下&#xff0c;个人感觉页面展示的效果不太好&#xff0c;而且不够紧凑&#xff0c;不利于操作。另外&#xff0c;最新版本并不一定是最…

Redux toolkit

Redux 是 JavaScript 应用的状态容器&#xff0c;提供可预测的状态管理。 Redux Toolkit 是官方推荐的编写 Redux 逻辑的方法 入门 Redux | Redux 中文官网 本案例是一个加&#xff0c;减的计算器&#xff0c;从零到壹 1、创建一个react的项目 Create-react-app react-too…

MybatisX快速生成增删改查

MybatisX快速生成增删改查 MybatisX 是一款基于 IDEA 的快速开发插件&#xff0c;方便在使用mybatis以及mybatis-plus开始时简化繁琐的重复操作&#xff0c;提高开发速率。 注意&#xff1a;idea得用最新的版本才能生效一些功能&#xff0c;我用的是2021.3版本的 1 安装 file …

【Unity VR开发】结合VRTK4.0:直线

桃花坞里桃花庵&#xff0c;桃花庵里桃花仙。桃花仙人种桃树&#xff0c;又折桃花当酒钱。 酒醒只在花前坐&#xff0c;酒醉还来花下眠。半醉半醒日复日&#xff0c;花落花开年复年。 但愿老死花酒间&#xff0c;不愿鞠躬车马前。车尘马足富者趣&#xff0c;酒盏花枝贫者缘。…

新C++(7):多态那些事儿_上

"也应该歌颂赞美那株鲜红的玫瑰。"一、回顾多态(1)什么是多态呢在编程语言和类型轮中&#xff0c;多态&#xff08;英语&#xff1a;polymorphism&#xff09;指为不同数据类型的实体提供统一的接口。多态类型(英语:polymorphic type&#xff09;可以将自身所支持的操…

FreeRTOS任务通知实验

从 V8.2.0 版本开始&#xff0c;FreeRTOS 新增了任务通知这个功能&#xff0c;可以使用任务通 知来代替信号量、消息队列、事件组等这些东西。使用任务通知的话效率会更高。 本章要实现的功能是&#xff1a;使用任务通知方式实现消息队列、二值信号量、计数信号 量、事件标记功…

极狐场景化造车理念受热捧,北汽蓝谷构建未来5年核心竞争力

近日&#xff0c;极狐汽车以“一米视角”为设计思考的原点&#xff0c;围绕亲子出行的全场景&#xff0c;推出全球首款智能亲子车——考拉。作为北汽蓝谷场景化造车的首款产品&#xff0c;极狐汽车考拉无疑是继高阶智能驾驶标杆产品HI之后的又一次先行探索&#xff0c;致力于卡…

1月VR大数据:Quest 2增长2.91%,HTC份额跌至10%以下

Hello大家好&#xff0c;每月一期的VR内容/硬件大数据统计又和大家见面了。 想了解VR软硬件行情么&#xff1f;关注这里就对了。我们会统计Steam平台的用户及内容等数据&#xff0c;每月初准时为你推送&#xff0c;不要错过喔&#xff01;本数据报告包含&#xff1a;Steam VR硬…

初识C语言(对c语言的简单介绍)

初识C语言什么是C语言&#xff1f;第一个C语言程序数据类型类型的使用&#xff1a;变量、常量定义变量的方法变量的分类变量的使用变量的作用域和生命周期常量字符串转义字符注释字符串转义字符注释选择语句循环语句函数数组数组定义数组的使用操作符常见关键字关键字 typedef关…

MySQL进阶篇之SQL优化

03、SQL优化 3.1、插入数据 1、insert优化 批量插入 INSERT INTO 表名 (字段1,字段2,...) VALUES (值1,值2,...),(值1,值2,...),(值1,值2,...);INSERT INTO 表名 VALUES (值1,值2,...),(值1,值2,...),(值1,值2,...);手动提交事务 start transaction; INSERT INTO 表名 (字段1…

【SQL 审核查询平台】Archery使用介绍

Archery 读作&#xff1a;[ˈɑːrtʃəri] Archery目录界面截图功能清单依赖清单框架前端组件服务端部署准备运行配置启动访问修改配置项基础设置添加实例添加资源组资源组关联用户/实例添加权限组用户关联权限组/权限设置工单上线和查询的审批流程设置默认资源组和默认权限组…

数组的几种常见方法及其返回值

push()&#xff1a;向数组的末尾添加一个或多个元素&#xff1b;返回的是数组的新长度。unshift()&#xff1a;向数组的开头添加一个或多个元素&#xff1b;返回的是数组的新长度。shift()&#xff1a;删除数组的第一个元素&#xff0c;并返回被删除的&#xff08;即第一个元素…

品牌社交营销链路 | 小红书数据分析网站

【导语】 2022年&#xff0c;小红书品牌推广竞争愈演愈烈&#xff0c;从小红书用户画像分析&#xff0c;到抢占小红书关键词排名&#xff0c;营销动作内卷升级&#xff0c;那么在2023的新篇章&#xff0c;如何打通社交种草的链路呢&#xff1f; 1、运营企业账号&#xff0c;建立…

MQTT 代理助力ECARX实现汽车智能互联

一、应用背景 ECARX是中国汽车制造商吉利旗下的一家科技创新企业&#xff0c;致力于持续打造行业领先的智能网联生态开放平台&#xff0c;全面为车企赋能&#xff0c;创造更智能、更安全的出行体验&#xff0c;为智能互联汽车提供智能解决方案。 ECARX主要业务包括吉利汽车的…

让Apache Beam在GCP Cloud Dataflow上跑起来

简介 在文章《Apache Beam入门及Java SDK开发初体验》中大概讲了Apapche Beam的简单概念和本地运行&#xff0c;本文将讲解如何把代码运行在GCP Cloud Dataflow上。 本地运行 通过maven命令来创建项目&#xff1a; mvn archetype:generate \-DarchetypeGroupIdorg.apache.b…

Swift 新 async/await 同步机制小技巧:消除“多余”的 await 关键字

概览 在使用多个Actor 共同实现同步功能的时候&#xff0c;我们往往会看到如下使用场景&#xff1a; Actor A 必须在主线程上运行&#xff0c;Actor B可以在任意线程上运行&#xff0c;但需要适时的调用 Actor A 中的方法。 在这种情况下&#xff0c;我们会遇到如下代码&#…

从移动激光扫描数据中自动提取单棵树的双重生长方法

论文题目&#xff1a;A dual growing method for the automatic extraction of individual trees from mobile laser scanning data Abstract 在城市场景的杂乱点云中&#xff0c;街道树木与其他物体交织在一起&#xff0c;阻碍了对单个树木的自动提取。根据树木的一般构成&a…