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

etcd 的安装及使用

介绍

Etcd 是一个 golang 编写的分布式、高可用的一致性键值存储系统,用于配置共享和服务发现等。它使用 Raft 一致性算法来保持集群数据的一致性,且客户端通过长连接 watch 功能,能够及时收到数据变化通知,相较于 Zookeeper 框架更加轻量化。

安装

首先,需要在你的系统中安装 Etcd Etcd 是一个分布式键值存储,通常用于服务发现和配置管理。以下是在 Linux 系统上安装 Etcd 的基本步骤:
  • 安装 Etcd
sudo apt-get install etcd
  • 启动 Etcd 服务:
sudo systemctl start etcd
  • 设置 Etcd 开机自启:
sudo systemctl enable etcd

配置文件

如果是单节点集群其实就可以不用进行配置,默认 etcd 的集群节点通信端口为 2380 ,客户端访问端口为 2379。若需要修改,则可以配置:/etc/default/etcd。
我们可以先查看 etcd 监听的地址,发现其默认监听的都是本地主机端口,要想让外部主机也能连接上 etcd 服务器,则可以修改 /etc/default/etcd 文件下的配置。
#用于客户端连接的 URL
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
#用于客户端访问的公开,也就是提供服务的 URL,ip要填入主机的公网ip
ETCD_ADVERTISE_CLIENT_URLS="http://ip:2379"

重新启动 etcd 服务后再查看 etcd 服务器的监听情况

运行验证

etcdctl put mykey "this is awesome"
如果出现报错:
No help topic for 'put'
sudo vi /etc/profile 在末尾声明环境变量 ETCDCTL_API=3 以确定 etcd 版本。
export ETCDCTL_API=3
完毕后,加载配置文件,并重新执行测试指令
source /etc/profile
etcdctl put mykey "this is awesome"

搭建服务注册发现中心

使用 Etcd 作为服务注册发现中心,你需要定义服务的注册和发现逻辑。这通常涉及到以下几个操作:
  • 服务注册:服务启动时,向 Etcd 注册自己的地址和端口。
  • 服务发现:客户端通过 Etcd 获取服务的地址和端口,用于远程调用。
  • 健康检查:服务定期向 Etcd 发送心跳,以维持其注册信息的有效性。
etcd 采用 golang 编写, v3 版本通信采用 grpc API ,即 (HTTP2+protobuf),官方只维护了 go 语言版本的 client 库,如果想使用 C/C++ 编写,则需要找到 C/C++ 非官方的 client 开发库:

etcd-cpp-apiv3

etcd-cpp-apiv3 是一个 etcd C++ 版本客户端 API 。它依赖于 mipsasm, boost, protobuf, gRPC, cpprestsdk 等库。
etcd-cpp-apiv3 GitHub 地址是: https://github.com/etcd-cpp-apiv3/etcd-cpp-apiv3
依赖安装:
sudo apt-get install libboost-all-dev libssl-dev
sudo apt-get install libprotobuf-dev protobuf-compiler-grpc
sudo apt-get install libgrpc-dev libgrpc++-dev
sudo apt-get install libcpprest-dev
api 框架安装:
可以先创建一个 etcd 目录并进入该目录,然后在该目录下拉取文件并用 cmake 构建文件
mkdir etcd && cd etcd
git clone https://github.com/etcd-cpp-apiv3/etcd-cpp-apiv3.git
cd etcd-cpp-apiv3
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr
make -j$(nproc) && sudo make install

客户端类与接口介绍

// pplx::task 并行库异步结果对象
// 阻塞方式 get(): 阻塞直到任务执行完成,并获取任务结果
// 非阻塞方式 wait(): 等待任务到达终止状态,然后返回任务状态
namespace etcd
{class Value{bool is_dir();                  // 判断是否是一个目录std::string const &key();       // 键值对的 key 值std::string const &as_string(); // 键值对的 val 值int64_t lease();                // 用于创建租约的响应中,返回租约 ID};// etcd 会监控所管理的数据的变化,一旦数据产生变化会通知客户端// 在通知客户端的时候,会返回改变前的数据和改变后的数据class Event{enum class EventType{PUT,     // 键值对新增或数据发生改变DELETE_, // 键值对被删除INVALID,};enum EventType event_type();const Value &kv();const Value &prev_kv();};class Response{bool is_ok();std::string const &error_message();Value const &value();               // 当前的数值 或者 一个请求的处理结果Value const &prev_value();          // 之前的数值Value const &value(int index);      //std::vector<Event> const &events(); // 触发的事件};class KeepAlive{KeepAlive(Client const &client, int ttl, int64_t lease_id = 0);// 返回租约 IDint64_t Lease();// 停止保活动作void Cancel();};class Client{// etcd_url: "http://127.0.0.1:2379"Client(std::string const &etcd_url, std::string const &load_balancer = "round_robin");// Put a new key-value pair 新增一个键值对pplx::task<Response> put(std::string const &key, std::string const &value);// 新增带有租约的键值对 (一定时间后,如果没有续租,数据自动删除)pplx::task<Response> put(std::string const &key, std::string const &value,const int64_t leaseId);// 获取一个指定 key 目录下的数据列表pplx::task<Response> ls(std::string const &key);// 创建并获取一个存活 ttl 时间的租约pplx::task<Response> leasegrant(int ttl);// 获取一个租约保活对象,其参数 ttl 表示租约有效时间pplx::task<std::shared_ptr<KeepAlive>> leasekeepalive(int ttl);// 撤销一个指定的租约pplx::task<Response> leaserevoke(int64_t lease_id);// 数据锁pplx::task<Response> lock(std::string const &key);};class Watcher{Watcher(Client const &client,std::string const &key,                 // 要监控的键值对 keystd::function<void(Response)> callback, // 发生改变后的回调bool recursive = false);                // 是否递归监控目录下的所有数据改变Watcher(std::string const &address,std::string const &key,std::function<void(Response)> callback,bool recursive = false);// 阻塞等待,直到监控任务被停止bool Wait();bool Cancel();};
}

使用案例

put.cc
#include <etcd/Client.hpp>
#include <etcd/KeepAlive.hpp>
#include <etcd/Response.hpp>
#include <thread>
#include <iostream>
int main()
{// etcd服务器的ip地址std::string etcd_host = "http://127.0.0.1:2379";// 实例化客户端连接etcd服务器etcd::Client client(etcd_host);// 向etcd新增数据auto rsp1 = client.put("/service/user", "127.0.0.1:8080").get();if (rsp1.is_ok() == false){std::cout << "新增数据失败:" << rsp1.error_message() << std::endl;return -1;}// 新增一个有保活期限的数据// 1.获取租约保活对象,设定租期为3sauto keep_alive = client.leasekeepalive(3).get();// 2.获取租约idauto lease_id = keep_alive->Lease();// 3.新增数据auto rsp2 = client.put("/service/friend", "127.0.0.1:9090",lease_id).get();if (rsp2.is_ok() == false){std::cout << "新增数据失败:" << rsp2.error_message() << std::endl;return -1;}std::this_thread::sleep_for(std::chrono::seconds(10));return 0;
}

get.cc

#include <etcd/Client.hpp>
#include <etcd/KeepAlive.hpp>
#include <etcd/Response.hpp>
#include <etcd/Value.hpp>
#include <etcd/Watcher.hpp>
#include <iostream>
void callback(const etcd::Response &rsp)
{if (rsp.is_ok() == false){std::cout << "收到一个错误的事件通知:" << rsp.error_message() << std::endl;return;}for (auto &ev : rsp.events()){if (ev.event_type() == etcd::Event::EventType::PUT){std::cout << "服务信息发生了改变:\n";std::cout << "当前值:" << ev.kv().key() << "-" << ev.kv().as_string() << std::endl;std::cout << "原先值:" << ev.prev_kv().key() << "-" << ev.prev_kv().as_string() << std::endl;}else if (ev.event_type() == etcd::Event::EventType::DELETE_){std::cout << "服务信息下线:\n";std::cout << "当前值:" << ev.kv().key() << "-" << ev.kv().as_string() << std::endl;std::cout << "原先值:" << ev.prev_kv().key() << "-" << ev.prev_kv().as_string() << std::endl;}}
}
int main()
{// etcd服务器的ip地址std::string etcd_host = "http://127.0.0.1:2379";// 实例化客户端连接etcd服务器etcd::Client client(etcd_host);// 从etcd获取指定数据auto rsp = client.ls("/service").get();if (rsp.is_ok() == false){std::cout << "获取数据失败:" << rsp.error_message() << std::endl;return -1;}int sz = rsp.keys().size();for (int i = 0; i < sz; i++)std::cout << rsp.value(i).as_string() << "可以提供" << rsp.key(i) << "服务" << std::endl;// 实例化一个键值对事件的监控对象auto watcher = etcd::Watcher(client, "/service", callback, true);watcher.Wait();return 0;
}

makefile

all:put get
put:put.ccg++ -o $@ $^ -std=c++17 -letcd-cpp-api -lcpprest
get:get.ccg++ -o $@ $^ -std=c++17 -letcd-cpp-api -lcpprest.PHONY:clean
clean:rm -f put get

封装服务发现与注册功能

在服务的注册与发现中,主要基于 etcd 所提供的可以设置有效时间的键值对存储来实现。

服务注册

主要是在 etcd 服务器上存储一个租期 ns 的保活键值对,表示所能提供指定服务的节点主机,比如 /service/user/instance-1 key ,且对应的 val 为提供服务的主机节点地址:
<key, val> -- < /service/user/instance-1, 127.0.0.1:9000>
  • /service 是主目录,其下会有不同服务的键值对存储
  • /user 是服务名称,表示该键值对是一个用户服务的节点
  • /instance-1 是节点实例名称,提供用户服务可能会有很多节点,每个节点都应该有自己独立且唯一的实例名称
当这个键值对注册后,服务发现方可以基于目录进行键值对的发现。且一旦注册节点退出,保活失败,则 租约失效键值对被删除, etcd 会通知发现方数据的失效,进而实现服务下线通知的功能。

服务发现

服务发现分为两个过程:
  • 刚启动客户端的时候,进行 ls 目录浏览,进行/service 路径下所有键值对的获取
  • 对关心的服务进行 watcher 观测,一旦数值发生变化(新增/删除),收到通知进行节点的管理
如果 ls 的路径为 /service ,则会获取到 /service/user, /service/firend  等其路径下的所有能够提供服务的实例节点数据。如果 ls 的路径为 /service/user ,则会获取到 /service/user/instancd-1, /service/user/instance-2 等所有提供用户服务的实例节点数据。
客户端可以将发现的所有 < 实例 - 地址 > 管理起来,以便于进行节点的管理:
  • 收到新增数据通知,则向本地管理添加新增的节点地址 -- 服务上线
  • 收到删除数据通知,则从本地管理删除对应的节点地址 -- 服务下线
因为管理了所有的能够提供服务的节点主机的地址,因此当需要进行 rpc 调用的时候,则根据服务名称,获取一个能够提供服务的主机节点地址进行访问就可以了,而这里的获取策略,我们采用 RR 轮转策略。

封装思想

etcd 的操作全部封装起来,也不需要管理数据,只需要向外四个基础操作接口:
  • 进行服务注册,也就是向 etcd 添加 <服务-主机地址>的数据
  • 进行服务发现,获取当前所有能提供服务的信息
  • 设置服务上线的处理回调接口
  • 设置服务下线的处理回调接口
这样封装之后,外部的 rpc 调用模块,可以先获取所有的当前服务信息,建立通信连接进行 rpc 调用,也能在有新服务上线的时候新增连接,以及下线的时候移除连接。
#pragma once
#include <iostream>
#include <etcd/Client.hpp>
#include <etcd/KeepAlive.hpp>
#include <etcd/Response.hpp>
#include <etcd/Watcher.hpp>
#include <etcd/Value.hpp>
#include <functional>
// 服务注册客户端
class Registry
{
public:using ptr = std::shared_ptr<Registry>;Registry(const std::string &host): _client(std::make_shared<etcd::Client>(host)),_keep_alive(_client->leasekeepalive(3).get()),_lease_id(_keep_alive->Lease()){}~Registry(){_keep_alive->Cancel();}bool registry(const std::string &key, const std::string &val){auto rsp = _client->put(key, val, _lease_id).get();if (rsp.is_ok() == false){std::cout << "服务注册失败:" << rsp.error_message() << std::endl;return false;}return true;}private:std::shared_ptr<etcd::Client> _client;std::shared_ptr<etcd::KeepAlive> _keep_alive;uint64_t _lease_id; // 注意租约id的类型必须是uint64_t
};
// 服务发现客户端
class Discovery
{
public:using ptr = std::shared_ptr<Discovery>;using NotifyCallback = function<void(std::string, std::string)>;Discovery(const std::string &host, const std::string &basedir,const NotifyCallback &put_cb, const NotifyCallback &del_cb): _client(std::make_shared<etcd::Client>(host)),_put_cb(put_cb), _del_cb(del_cb){// 先进行服务发现,获取当前已有的数据auto rsp = _client->ls(basedir).get();if (rsp.is_ok() == false){std::cout << "获取服务信息失败:" << rsp.error_message() << std::endl;}int sz = rsp.keys().size();for (int i = 0; i < sz; i++){if (_put_cb)_put_cb(rsp.key(i), rsp.value(i).as_string());}// 然后进行事件监控,监控数据的变化并调用回调函数进行处理_watcher = std::make_shared<etcd::Watcher>(*_client.get(), basedir,std::bind(&Discovery::callback, this, std::placeholders::_1), true);}void wait(){_watcher->Wait();}~Discovery(){_watcher->Cancel();}private:void callback(const etcd::Response &rsp){if (rsp.is_ok() == false){std::cout << "收到一个错误的事件通知" << std::endl;return;}for (auto &ev : rsp.events()){if (ev.event_type() == etcd::Event::EventType::PUT){if (_put_cb)_put_cb(ev.kv().key(), ev.kv().as_string());cout << "新增服务" << ev.kv().key() << "-" << ev.kv().as_string() << std::endl;}else if (ev.event_type() == etcd::Event::EventType::DELETE_){if (_del_cb)_del_cb(ev.prev_kv().key(), ev.prev_kv().as_string());cout << "下线服务" << ev.prev_kv().key() << "-" << ev.prev_kv().as_string() << std::endl;}}}private:NotifyCallback _put_cb;NotifyCallback _del_cb;std::shared_ptr<etcd::Client> _client;std::shared_ptr<etcd::Watcher> _watcher;
};

相关文章:

etcd 的安装及使用

介绍 Etcd 是一个 golang 编写的分布式、高可用的一致性键值存储系统&#xff0c;用于配置共享和服务发现等。它使用 Raft 一致性算法来保持集群数据的一致性&#xff0c;且客户端通过长连接 watch 功能&#xff0c;能够及时收到数据变化通知&#xff0c;相较于 Zookeepe…...

uni-app vue3 实现72小时倒计时功能

功能介绍 &#xff0c;数组项有一个下单时间 &#xff0c;比如今天下单在72小时内可以继续支付&#xff0c;超过则默认取消订单 页面按钮处 加上倒计时 <!-- 倒计时 --> <text v-if"item.timeLeft > 0">{{ formatTime(item.remaining) }}</text&g…...

【C语言】初阶算法相关习题(二)

个人主页&#xff1a;夜晚中的人海 文章目录 ⭐一、两数之和&#x1f3e0;二、珠玑妙算&#x1f3a1;三、寻找奇数&#x1f680;四、截取字符串&#x1f389;五、寻找峰值 ⭐一、两数之和 题目描述&#xff1a;两数之和 解题思路&#xff1a; 1.先创建一个动态分配的数组ret&a…...

Flutter 学习之旅 之 Flutter 和 Android 原生 实现数据交互的MethodChanel和EventChannel方式的简单整理

Flutter 学习之旅 之 Flutter 和 Android 原生 实现数据交互的MethodChanel和EventChannel方式的简单整理 目录 Flutter 学习之旅 之 Flutter 和 Android 原生 实现数据交互的MethodChanel和EventChannel方式的简单整理 一、简单介绍 二、Flutter 和 Android 原生之间的数据…...

STM32的SysTick

SysTick介绍 定义&#xff1a;Systick&#xff0c;即滴答定时器&#xff0c;是内核中的一个特殊定时器&#xff0c;用于提供系统级的定时服务。该定时器是一个24位的递减计数器&#xff0c;具有自动重载值寄存器的功能。当计数器到达自动重载值时&#xff0c;它会自动重新加载…...

【JS事件循环机制event-loop】

目录 0、总结1、Event-Loop 概念2、宏任务-微任务3、事件循环执行机制4、调用栈5、示例 0、总结 Tasks execute in order, and the browser may render between them 【宏任务按序执行&#xff0c;浏览器可以在它们之间进行渲染】Microtasks execute in order, and are execut…...

对比N+1查询和关联聚合查询

通常我们管第一种模式叫 “N1 查询”&#xff0c;第二种叫 “关联聚合查询”。下面从几个角度来比较&#xff0c;帮助你做出选择。 1. 性能与资源消耗 方案SQL 语句数网络往返次数数据库负载Java 处理N1 查询&#xff08;先查项目&#xff0c;再遍历项目查设备状态数&#xff…...

优化 Flutter 应用启动:从冷启动到就绪仅需 2 秒

冷启动序列剖析&#xff1a;冷启动时&#xff0c;Flutter 应用需经历引擎和 Dart VM 初始化、启动 Dart Isolate、渲染第一帧等步骤。Android 和 iOS 系统分别通过启动屏幕和 Storyboard 缓解启动延迟。应用大小、初始化工作、调试模式下的 JIT 编译等因素会影响冷启动时间。优…...

牟乃夏《ArcGIS Engine 地理信息系统开发教程》学习笔记 4-空间分析与高级功能开发

目录 一、核心组件与接口回顾 &#xff08;一&#xff09;空间分析基础架构 &#xff08;二&#xff09;网络分析模块 二、矢量数据空间分析实战 &#xff08;一&#xff09;缓冲区分析 &#xff08;二&#xff09;叠加分析&#xff08;以裁剪为例&#xff09; 三、栅格…...

UE 滚动提示条材质制作

需要两个贴图 先制作条纹屏闪 这里RGB输出连到alpha&#xff0c;0为白色&#xff0c;到1就为黑色了 因为这个图片是RGB输出代表三个图片&#xff0c;看贴图颜色就知道了&#xff0c;然后把这三个相加一下&#xff1b;链接自发光颜色&#xff0c; 这里设置速度变量 通过网盘分…...

金融业数字化转型——深入解读77页2024年中国金融体系指标大全【附全文阅读】

本文主要介绍了金融业通行宝典中国金融体系指标大全的内容,包括央行体系、商业银行体系、非银金融机构与地方金融组织的各项指标。文章详细分析了美联储资产负債表的结构,并概述了美日欧等主要经济体资产负债表状况。 重点内容: 1. 央行体系是金融分析的重点。 2. 美联储资产…...

研究:大模型输出一致性:确定性与随机性的场景化平衡

大模型在相同输入下的输出是否一致,本质上取决于其设计目标、任务性质以及技术实现方式。这一问题需要从技术原理、应用场景、用户需求三个维度进行深度分析: 一、技术实现:确定性与随机性的平衡 模型架构的确定性基础 大模型的核心参数(如权重矩阵)在训练完成后是固定的…...

数据分析1

一、常用数据处理模块Numpy Numpy常用于高性能计算&#xff0c;在机器学习常常作为传递数据的容器。提供了两种基本对象&#xff1a;ndarray、ufunc。 ndarray具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组。 ufunc提供了对数组快速运算的标准数学函数。 ndar…...

vmare pro安装报错用户在命令行上发出了EULAS_AGREED=1,表示不接受许可协议的错误解决方法

问题现状和原因 用户在命令行上发出了EULAS_AGREED1&#xff0c;表示不接受许可协议的错误。 以上错误主要原因是因为机器安装过了vmare 卸载时没有卸载干净导致的。 解决方法&#xff1a; 1、控制面板-程序和功能-卸载程序。找到vamre卸载掉。 2、打开开始菜单输入注册表 …...

《Linux篇》基础开发工具——vim详细介绍

文章目录 1.软件包管理1.1 什么是软件包1.2 Linux软件生态 2.编辑器vim2.1 vim的正常/命令模式2.2 vim的末行模式2.3 vim的插入模式 3.配置vim 1.软件包管理 我们先来看一下再Linux是那个如何安装软件&#xff1f; 源码安装&#xff1a;软件是存在相互依赖的关系的&#xff0…...

AI图片跳舞生成视频,animate X本地部署。

本期内容打包限时免费下载https://www.kdocs.cn/l/cnQ5lNU5DFZB 对比不同算法&#xff0c;使用同一组图片和舞蹈视频。animate X官网&#xff0c;下载项目解压。按照官方教程下载模型&#xff0c;项目包和命名好的模型包已上传网盘&#xff0c;放到解压目录下即可。 安装好cond…...

Web技术与Apache网站部署

一、Web 基础与 HTTP 协议 1.1 静态网页与动态网页 静态网页 定义&#xff1a;由纯 HTML、CSS、JavaScript 构成&#xff0c;文件扩展名为 .htm 或 .html。内容在服务器生成后固定不变&#xff0c;仅通过客户端脚本&#xff08;如 JS&#xff09;实现视觉动态效果&#xff08…...

第七章:Server/Client Communication

Chapter 7: Server/Client Communication 从工具集成到服务器通信&#xff1a;如何让AI“远程协作”&#xff1f; 在上一章的工具与LLM集成中&#xff0c;我们已经能让AI调用真实世界的工具。但你是否想过&#xff1a;如果多个用户同时请求天气查询&#xff0c;或者需要远程控…...

Linux调试器 - gdb使用指南

目录 一、背景知识 二、开始使用 gdb &#xff08;一&#xff09;查看源代码相关指令 &#xff08;二&#xff09;程序执行控制指令 &#xff08;三&#xff09;断点相关指令 &#xff08;四&#xff09;变量操作相关指令 &#xff08;五&#xff09;其他常用指令 在Li…...

C++面试常青客:LRUCache最近最少使用算法

C面试常青客&#xff1a;LRUCache最近最少使用算法 文章目录 C面试常青客&#xff1a;LRUCache最近最少使用算法1.背景&#x1f3c6;2.原理&#x1f680;2.1基本原理2.2核心特性 3.结构3.1为什么需要 list<pair<int,int>>&#xff08;双向链表&#xff09;&#xf…...

【含文档+PPT+源码】基于微信小程序的社交摄影约拍平台的设计与实现

项目介绍 本课程演示的是一款基于微信小程序的社交摄影约拍平台的设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系…...

jetson nano上Ubuntu系统调用摄像头bug

今天在做一个比赛的时候&#xff0c;通过调用摄像头做检测并输出目标角度和距离。刚开始用的是 cv::VideoCapture cap; cap.open("/dev/video0");没有任何问题&#xff0c;使用pnp解算得到的角度和距离都是正确的&#xff0c;画面也是小画面。 后面加了一些功能&…...

用Python做有趣的AI项目5:AI 画画机器人(图像风格迁移)

这个项目将使用 PyTorch 实现图像风格迁移&#xff08;Neural Style Transfer&#xff09;&#xff0c;让一张图片看起来具有另一张图片的“艺术风格”。 &#x1f527; 开发环境建议 Python 3.8 PyTorch&#xff08;pip install torch torchvision&#xff09; PIL&#x…...

一种用于从视网膜图像中识别疾病的 BERT 式自监督学习 CNN

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 在医学成像领域&#xff0c;深度学习的出现&#xff0c;尤其是卷积神经网络 &#xff08;CNN&#xff09; 的应用&#xff0c;彻底改变了医学影像的分析和解释。然而&#xff0c;深度学习方法通常依…...

OpenCV 图形API(68)图像与通道拼接函数------垂直拼接两个图像/矩阵的函数concatVert()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 对给定的矩阵执行垂直拼接。该函数将两个 GMat 矩阵&#xff08;列数相同&#xff09;垂直连接&#xff1a; GMat A { 1, 7,2, 8,3, 9 }; GMat…...

重测序关系矩阵构建方式汇总

样本间亲缘关系矩阵&#xff08;kinship matrix&#xff09;和同源性矩阵&#xff08;IBS matrix&#xff09;构建的方式 1. 可以使用plink的–make-rel计算个体之间的亲缘关系&#xff08;强调个体之间的遗传相似性&#xff09; /opt/software/plink --bfile vcf_bfile--mak…...

OpenCV 图形API(70)图像与通道拼接函数-----创建一个图像或矩阵(GMat)的副本的操作函数copy()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 制作输入图像的一个副本。请注意&#xff0c;这个副本可能不是实际存在的&#xff08;没有实际复制数据&#xff09;。使用此函数来维护图的契约…...

30天通过软考高项-第六天

30天通过软考高项-第六天 任务&#xff1a;项目质量管理 思维导图阅读 知识点集锦阅读 知识点记忆 章节习题练习 知识点练习 手写回忆ITTO 听一遍喜马拉雅关于范围的内容 质量管理 -背 1. 过程定义 龟管控 要求标准规划定&#xff0c;计划转化看过程&#xf…...

JUC中各种锁机制的应用和原理及死锁问题定位

JUC中各种锁机制的应用和原理及死锁问题定位 在互联网大厂Java求职者的面试中&#xff0c;经常会被问到关于JUC&#xff08;Java Util Concurrency&#xff09;中的各种锁机制及其应用和原理的问题。本文通过一个故事场景来展示这些问题的实际解决方案。 第一轮提问 面试官&…...

区块链vs实体经济:一场金融、医疗、政务与物流的“效率革命”

区块链技术作为一种去中心化、不可篡改的分布式账本技术&#xff0c;正在重塑多个行业的运行模式。从金融交易的透明化到医疗数据的安全共享&#xff0c;从政务服务的效率提升到物流供应链的全程可追溯&#xff0c;区块链的跨行业应用展现出巨大的潜力与价值。以下是其在金融、…...

FTP-网络文件服务器

部署思路 单纯上传下载ftp系统集成间的共享 samba网络存储服务器 NFS 网络文件服务器&#xff1a;通过网络共享文件或文件夹&#xff0c;实现数据共享 NAS &#xff08; network append storage):共享的是文件夹 FTP&#xff1a;文件服务器samba&#xff1a;不同系统间的文件…...

嵌入式RTOS实战:uC/OS-III最新版移植指南(附项目源码)

文章目录 前言一、uC/OS简介二、工程移植2.1 下载ucos源码2.2 创建空白工程2.3 拷贝ucosiii源码文件2.3.1 UC-CONFIG2.3.2 UC-CPU2.3.3 UC-LIB2.3.4 UC-OS3 2.3 添加工程文件分组及路径2.4 代码首次编译2.5 源码修改2.5.1 cpu_cfg.h2.5.2 os_cpu_c.c2.5.3 lib_cfg.h2.5.4 sys.h…...

10.Excel:快速定位目标值

一 批量删除 1.如何使用 快捷键 CTRLG 补充&#xff1a;直接选择定位条件。 2.作用 1.批量删除工作表中的图片 补充&#xff1a;无法通过框选的方式选中这些图片进行删除。 这样只框选了表格&#xff0c;无法框选图片。因为图片在excel中被认为是一个对象&#xff0c;对象无法通…...

状态模式 (State Pattern)

状态模式(State Pattern)是一种行为型设计模式,它允许对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。该模式将状态封装成独立的类,并将请求委托给当前的状态对象,当对象的内部状态发生变化时,其行为也会随之改变。 一、基础部分 1. 意图 允许一个…...

【Java面试题04】MySQL 篇

文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、MySQL 篇&#xff1a;☀️☀️☀️1、MySQL 是如何实现事务的? 后序还在更新中~~~三、总结&#xff1a;&#x1f353;&#x1f353;&#x1f353; 一、前言&#x1f680;&#x1f680;&#x1f680; ☀️ 你每一…...

同时安装多个版本的golang

https://golang.google.cn/dl/ go install golang.org/dl/go1.20latest 这样就会将 go1.20.exe 下载到 GOPATH/bin&#xff0c;但是此时并没有 go1.20 的源码包&#xff0c;也就不能正常执行 build/run 等指令。 然后执行 go1.20 download下载源码包 > go1.20 download …...

【Web应用服务器_Tomcat】三、Tomcat 性能优化与监控诊断

在企业级 Java Web 应用的运行过程中&#xff0c;Apache Tomcat 作为广泛使用的 Servlet 容器和 Web 服务器&#xff0c;其性能表现直接影响用户体验和业务稳定性。本篇文章将深入探讨 Tomcat 性能优化的实用技巧&#xff0c;以及如何通过有效的监控诊断手段&#xff0c;及时发…...

stm32week13

stm32学习 九.stm32与HAL库 4.时钟树 stm32f103所拥有的时钟源&#xff1a; 外部时钟的稳定性比内部的高&#xff0c;但是成本高&#xff0c;需要在外部额外接 关于上述时钟树的简图&#xff1a; 右下四个是HAL库中的初始化函数 F4的时钟树简图&#xff1a; F7的时钟树简图…...

深入探究C++ 中的stack、queue和deque

目录 一、stack&#xff08;栈&#xff09; 二、queue&#xff08;队列&#xff09; 三、deque&#xff08;双向队列&#xff09; 四、容器适配器总结 在C 的标准模板库&#xff08;STL&#xff09;中&#xff0c;stack、queue和priority_queue是非常实用的容器适配器&…...

第十二节:性能优化高频题-shallowRef/shallowReactive使用场景

适用场景&#xff1a;大型对象/列表仅需第一层响应式变化&#xff08;如JSON配置数据&#xff09; Vue3 浅层响应式 API&#xff08;shallowRef/shallowReactive&#xff09;使用场景深度解析 一、核心使用场景与性能优化原理 大型 JSON 配置数据管理 • 场景特征&#xff1a;…...

openGauss DB4AI与scikit-learn模块对比探究

openGauss当前版本支持了原生DB4AI能力&#xff0c;引入原生AI算子&#xff0c;简化操作流程&#xff0c;充分利用数据库优化器、执行器的优化与执行能力&#xff0c;获得高性能的数据库内模型训练能力。 本文介绍了笔者采用鸢尾花数据集&#xff0c;对openGauss DB4AI功能进行…...

基于大模型的公安预审办案笔录分析的挑战与应对策略-3

引言 &#xff1a;在基于大模型的公安预审办案笔录分析应用过程中&#xff0c;虽然取得了一定的成果&#xff0c;但也面临着诸多挑战。本文将分析这些挑战&#xff0c;并提出相应的应对策略&#xff0c;以推动该技术在公安领域的更好地发展和应用。 引文&#xff1a;https://c…...

ubantu18.04(Hadoop3.1.3)之Flink安装与编程实践(Flink1.9.1)

说明&#xff1a;本文图片较多&#xff0c;耐心等待加载。&#xff08;建议用电脑&#xff09; 注意所有打开的文件都要记得保存。 第一步&#xff1a;准备工作 本文是在之前Hadoop搭建完集群环境后继续进行的&#xff0c;因此需要读者完成我之前教程的所有操作。 注意本次实…...

AI辅助编程-cursor开发煤矿持证上岗管理程序需求与设计篇

​ Cursor 是一款由人工智能驱动的智能代码编辑器&#xff0c;深度融合AI技术以提升开发效率。其核心功能基于GPT-4等先进模型&#xff0c;支持代码生成、错误修复、智能补全及自然语言编程。开发者可通过对话交互直接描述需求&#xff0c;AI即时生成对应代码片段&#xff0c;显…...

如何使用极狐GitLab 议题看板?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 议题看板 (BASIC ALL) 议题看板是一个软件项目管理工具&#xff0c;用于计划、组织和可视化功能或产品发布的工作流程。它可…...

计网分层体系结构(包括OSI,IP,两者对比和相关概念)

1. 应用层&#xff1a; 用户与网络的界面&#xff0c;FTP&#xff0c;SMTP, HTTP 2. 表示层(Presentation Layer)&#xff1a; 解决用户信息的语法表示问题 数据压缩&#xff0c;加密解密 表示变换 3. 对话层(Session Layer)&#xff1a; 功能&#xff1a;允许不同主机的各个进…...

爬虫过程中如何确保数据准确性

在爬虫过程中&#xff0c;确保数据的准确性是非常重要的。数据不准确可能会导致分析结果的偏差&#xff0c;甚至影响决策。以下是一些确保爬虫数据准确性的方法和技巧&#xff1a; 一、验证数据来源 确保数据来源的可靠性是确保数据准确性的第一步。选择信誉良好的网站作为数…...

Maven多模块工程版本管理:flatten-maven-plugin扁平化POM

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…...

数据库基础与核心操作:从概念到实战的全面解析

目录 1 基本概念2 基本操作2.1 DCL2.2 DDL2.3 DML2.4 DQL(高级查询) 3 高级功能3.1 视图&#xff08;无参函数&#xff09;3.2 存储过程(有参函数)3.3 触发器 4 约束4.1 主键约束4.2 UNIQUE KEY&#xff08;唯一键约束&#xff09;4.3 FOREIGN KEY&#xff08;外键约束&#xf…...

网络原理 - 10(HTTP/HTTPS - 1)

前面的网络原理 1 - 9&#xff0c;按照 TCP/IP 五层协议栈&#xff0c;介绍了各个层次的核心协议。 应用层&#xff1a;自定义协议&#xff08;xml&#xff0c;json....&#xff09; 传输层&#xff1a;UDP/TCP 网络层&#xff1a;IP 数据链路层&#xff1a;以太网 我们这…...