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

RedisDB双机主从同步性能测试

安装redisDB

主节点


apt install redis-server

修改配置 /etc/redis/redis.conf

bind 0.0.0.0save ""   # 禁止RDB持久化
#save 900 1
#save 300 10
#save 60 10000appendonly no  # 禁止AOF持久化

重启服务

systemctl restart redis-server

从节点配置文件

bind 0.0.0.0save ""   # 禁止RDB持久化
#save 900 1
#save 300 10
#save 60 10000appendonly no  # 禁止AOF持久化# 从节点关键配置
slaveof 172.40.20.132 6379

主从验证

主从状态

主节点执行 redis-cli info replication

root@r750-132:~# redis-cli  info replication
# Replication
role:master
connected_slaves:1
slave0:ip=172.40.20.131,port=6379,state=online,offset=84,lag=0
master_replid:1e214902bfe781c96a43a65ff20eefa9a9e6a75d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:84
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:84

从节点检查

redis-cli info replication
# Replication
role:slave
master_host:172.40.20.132
master_port:6379
master_link_status:up
master_last_io_seconds_ago:6
master_sync_in_progress:0
slave_repl_offset:168
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:1e214902bfe781c96a43a65ff20eefa9a9e6a75d
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:168
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:168
数据同步

主节点插入数据

root@r750-132:~# redis-cli set name1 ckun
OK
root@r750-132:~# redis-cli get name1
"ckun"

从节点读取数据

root@r750-131:~# redis-cli get name1
"ckun"

测试程序

安装hiredis API

git clone https://github.com/redis/hiredis.git
cd hiredis/
make
make install
ldconfig

测试代码

#include <stdio.h>
#include <stdint.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <hiredis/hiredis.h>typedef struct {uint32_t orig_saddr;uint32_t orig_daddr;uint8_t  proto;uint16_t orig_sport;uint16_t orig_dport;uint32_t new_saddr;uint32_t new_daddr;uint16_t new_sport;uint16_t new_dport;
} session_t;#define CHANNEL "session_channel"
#define SESS_NUM 100000uint16_t random_port() {return rand() % 65535 + 1;
}char* session_to_string(session_t *session) {char *str = (char *)malloc(256);snprintf(str, 256,"{""\"orig_saddr\":%u,""\"orig_daddr\":%u,""\"proto\":%u,""\"orig_sport\":%u,""\"orig_dport\":%u,""\"new_saddr\":%u,""\"new_daddr\":%u,""\"new_sport\":%u,""\"new_dport\":%u""}",session->orig_saddr,session->orig_daddr,session->proto,session->orig_sport,session->orig_dport,session->new_saddr,session->new_daddr,session->new_sport,session->new_dport);return str;
}static int count = 0;
static struct timeval start_time, end_time;
// 订阅消息的回调函数
void subscribe_callback(redisContext *c, redisReply *reply) {if (reply == NULL) {printf("Received NULL or empty message\n");return;}switch (reply->type) {case REDIS_REPLY_ERROR:case REDIS_REPLY_STRING:case REDIS_REPLY_NIL:case REDIS_REPLY_INTEGER:case REDIS_REPLY_STATUS:break;case REDIS_REPLY_ARRAY:{int i = 0;// for (i = 0; i < reply->elements; ++i)// {//     redisReply* childReply = reply->element[i];//     if (childReply->type == REDIS_REPLY_STRING)//     {//         printf("value:%s\n", childReply->str);//     }// }// 增加计数i = reply->elements - 1;redisReply* childReply = reply->element[i];if ( childReply->str != NULL) {//printf("value: %s\n", childReply->str);count++;}}break;default:break;}if (count == 1) {gettimeofday(&start_time, NULL); // 记录开始一时间}// 如果接收了 100,000 条数据,计算时间if (count == SESS_NUM) {gettimeofday(&end_time, NULL);double elapsed_time = (end_time.tv_sec - start_time.tv_sec) +(end_time.tv_usec - start_time.tv_usec) / 1000000.0;printf("Received %d sessions in %.3f seconds\n", SESS_NUM, elapsed_time);exit(0);}
}// 订阅 Redis 频道并接收消息
void subscribe_to_redis(redisContext *c) {redisReply *reply;redisAppendCommand(c, "SUBSCRIBE %s", CHANNEL);while (1) {if (redisGetReply(c, (void **)&reply) == REDIS_OK) {// 调用回调函数处理数据subscribe_callback(c, reply);freeReplyObject(reply);}}
}// 连接 Redis 并插入数据
void insert_sessions_to_redis(redisContext *c, int set_no_pub) {redisReply *reply = NULL;session_t session;char key[256];srand(time(NULL));gettimeofday(&start_time, NULL); // 记录开始一时间int printsize = 1;for (int i = 0; i < SESS_NUM; i++) {// 构造五元组 keysession.orig_saddr = 0xC0A8000A + i;  // orig_saddr 递增session.orig_daddr = 0x0A000001;session.proto = 6;  // 假设是 TCP 协议session.orig_sport = 12345;session.orig_dport = 8080;// 为 session 生成随机数据session.new_saddr = 0xAC100001;session.new_daddr = 0xAC10000A;session.new_sport = random_port();session.new_dport = random_port();// 生成 Redis key (五元组)snprintf(key, sizeof(key), "SESS:%u:%u:%u:%u:%u", session.orig_saddr, session.orig_daddr, session.proto, session.orig_sport, session.orig_dport);// 将 session 转为字符串存入 Redischar *session_str = session_to_string(&session);if (printsize) {int valuesize = strlen(session_str);int keysize = strlen(key);printf("KeySize: %d, ValueSize: %d\n", keysize, valuesize);printsize = 0;}reply = redisCommand(c, "SET %s %s", key, session_str);free(session_str);if (reply != NULL) {freeReplyObject(reply);}// 发布消息到订阅频道if (set_no_pub == 0) {redisCommand(c, "PUBLISH %s %s", CHANNEL, key);  // 发布消息}}gettimeofday(&end_time, NULL);double elapsed_time = (end_time.tv_sec - start_time.tv_sec) +(end_time.tv_usec - start_time.tv_usec) / 1000000.0;printf("SET %d sessions in %.3f seconds\n", SESS_NUM, elapsed_time);
}int sub_session() {redisContext *c = redisConnect("127.0.0.1", 6379);if (c == NULL || c->err) {if (c) {printf("Redis connection error: %s\n", c->errstr);} else {printf("Redis connection error: can't allocate redis context\n");}return 1;}// 订阅 Redis 频道subscribe_to_redis(c);redisFree(c);return 0;
}int pub_session(int set_no_pub) {redisContext *c = redisConnect("127.0.0.1", 6379);if (c == NULL || c->err) {if (c) {printf("Redis connection error: %s\n", c->errstr);} else {printf("Redis connection error: can't allocate redis context\n");}return 1;}printf("Begin to insert data\n");// 插入数据insert_sessions_to_redis(c, set_no_pub);redisFree(c);return 0;
}int main(int argc, char* argv[])
{if (argc < 2) {printf("Usage: ./redistest pub / sub\n");return 0;}if(strlen(argv[1]) >= 3) {if(strcmp(argv[1], "pub") == 0) {return pub_session(0);} else if (strcmp(argv[1], "set_no_pub") == 0) {return pub_session(1);}   else if (strcmp(argv[1], "sub") == 0) {return sub_session();}} return 0;
}

Makefile

APP_tool = redistestSRCS-t = $(wildcard *.c) 
PKGCONF ?= pkg-configCFLAGS += -g -O2 $(shell $(PKGCONF) --cflags hiredis) 
LDFLAGS += $(shell $(PKGCONF) --libs hiredis) -lpthread all: $(APP_tool)$(APP_tool): $(SRCS-t)$(CC) $(CFLAGS) $(SRCS-t) -o $@ $(LDFLAGS).PHONY: clean
clean:rm $(APP_tool)

RedisDB命令

# 清空数据库
redis-cli FLUSHDB  # 找到 SESS:前缀的 KEY, 通过这些KEY可以查到到VALUE
ckun@r750-131:~$ redis-cli KEYS "SESS:*"1) "SESS:3232235530:167772161:6:12345:8080"2) "SESS:3232235537:167772161:6:12345:8080"3) "SESS:3232235538:167772161:6:12345:8080"4) "SESS:3232235539:167772161:6:12345:8080"5) "SESS:3232235531:167772161:6:12345:8080"6) "SESS:3232235532:167772161:6:12345:8080"7) "SESS:3232235533:167772161:6:12345:8080"8) "SESS:3232235536:167772161:6:12345:8080"9) "SESS:3232235535:167772161:6:12345:8080"
10) "SESS:3232235534:167772161:6:12345:8080"# 通过KEY 查询VALUE
ckun@r750-131:~$ redis-cli get "SESS:3232235530:167772161:6:12345:8080"
"{\"orig_saddr\":3232235530,\"orig_daddr\":167772161,\"proto\":6,\"orig_sport\":12345,\"orig_dport\":8080,\"new_saddr\":2886729729,\"new_daddr\":2886729738,\"new_sport\":3543,\"new_dport\":54296}"

测试

主写入10万条记录,这里以NAT会话作为写入条目,KEY 38字节,VALUE 177字节。
从订阅10万条记录,看看同步一共花费多少时间。

主设备写入10万条花了9.49秒

ckun@r750-132:~/ws/redistest$ ./redistest pub 
Begin to insert data
KeySize: 38, ValueSize: 177
SET 100000 sessions in 9.493 seconds

从设备同步时间也是一致的 (从订阅到第一个记录开始计时)

ckun@r750-131:~$ ./redistest sub
Received 100000 sessions in 9.493 seconds

平均一秒写入并同步一万条。

那只写入,不PUB看一下性能

ckun@r750-132:~/ws/redistest$ ./redistest set_no_pub
Begin to insert data
KeySize: 38, ValueSize: 177
SET 100000 sessions in 4.484 seconds

平均有20000多条了,看起来加上PUB是要多消耗一倍的计算资源。

单机写入Benchmark
ckun@r750-132:~/ws/redistest$ redis-benchmark -h  127.0.0.1 -p 6379 -c 8 -n 100000  -t set -d 100 -P 8 -q 
SET: 395288.56 requests per secondckun@r750-132:~/ws/redistest$ redis-benchmark -h  127.0.0.1 -p 6379 -c 8 -n 100000  -t set -d 100 -P 1 -q
SET: 134408.59 requests per secondckun@r750-132:~/ws/redistest$ redis-benchmark -h  127.0.0.1 -p 6379 -c 1 -n 100000  -t set -d 100 -P 1 -q 
SET: 18419.60 requests per second

单连接,一个请求写入一个记录,性能18000 req/s 。

小结

在当前Intel® Xeon® Gold 6346 CPU @ 3.10GHz 环境下,
测试程序单连接写入并且同步只有 10000 req/s 左右的写入性能。
如果关闭PUB,单纯写入会有20000 req/s左右性能。
通过benchmark验证,单链接也有18000 req/s左右写入性能。

在大容量大并发的NAT环境中,20W每秒的新建会话速度,每个会话得有两个表, 上下行各一个,总计40W个条目,40个线程并发写入才能满足。这明显不能满足性能需求。

相关文章:

RedisDB双机主从同步性能测试

安装redisDB 主节点 apt install redis-server修改配置 /etc/redis/redis.conf bind 0.0.0.0save "" # 禁止RDB持久化 #save 900 1 #save 300 10 #save 60 10000appendonly no # 禁止AOF持久化重启服务 systemctl restart redis-server从节点配置文件 bind 0.…...

【汇编】x86汇编编程寄存器资源心中有数

1. CPU状态及控制寄存器 TR&#xff0c;GDTR&#xff0c;LDTRcr0-cr3EFLAGS 等等 2. 业务计算寄存器&#xff08;我起的名字&#xff09; 业务寄存器用于访问内存、参数传递、数据传递、计算。 段寄存器6个&#xff1a; cs&#xff0c;ds&#xff0c;es&#xff0c;ss&…...

一.项目课题 <基于TCP的文件传输协议实现>

客户端代码 需要cJSON.c文件和cJSON.h文件 在这里插入代码片#include "myheadth.h" #include "myfun.h"#define TIME 10 int sockfd; void heartbeat(int signum) {cJSON* root cJSON_CreateObject();cJSON_AddStringToObject(root,"request"…...

【数据结构学习笔记】19:跳表(SkipList)

介绍 跳表是一个能在 O ( n l o g n ) O(nlogn) O(nlogn)时间完成查找、插入、删除的数据结构&#xff0c;相比于树形结构优点就是很好写&#xff08;所以也用于实现Redis ZSet&#xff09;。其核心思想就是维护一个元素有序的&#xff0c;能随机提升索引层数的链表。最下面一…...

Cocos Creator 3.8 修改纹理像素值

修改的代码&#xff1a; import { _decorator, Component, RenderTexture, Sprite, Texture2D, ImageAsset, SpriteFrame, Vec2, gfx, director, log, math, v2 } from cc;const { ccclass, property } _decorator;ccclass(GradientTransparency) export class GradientTrans…...

【Linux】网络层

目录 IP协议 协议头格式 网段划分 2中网段划分的方式 为什么要进行网段划分 特殊的IP地址 IP地址的数量限制 私有IP地址和公有IP地址 路由 IP协议 在通信时&#xff0c;主机B要把数据要给主机C&#xff0c;一定要经过一条路径选择&#xff0c;为什么经过路由器G后&…...

单片机Day1

目录 一.什么是单片机&#xff1f; 二.单片机的组成 三.封装形式 四.优势 五.分类 通用型&#xff1a; 专用型&#xff1a; 按处理的二进制位可以分为&#xff1a; 六.应用&#xff1a; 七.发展趋势 1.增加CPU的数据总线宽度。 2.存储器的发展。 3.片内1/0的改进 …...

django基于 Python 的考研学习系统的设计与实现

以下是对Django基于Python的考研学习系统的设计与实现&#xff1a; 一、系统概述 Django基于Python的考研学习系统是一个为考研学子提供一站式学习辅助的平台。它整合了丰富的学习资源、学习计划制定、学习进度跟踪以及交流互动等功能&#xff0c;旨在满足考生在备考过程中的…...

openCvSharp 计算机视觉图片找茬

一、安装包 <PackageReference Include"OpenCvSharp4" Version"4.10.0.20241108" /> <PackageReference Include"OpenCvSharp4.runtime.win" Version"4.10.0.20241108" /> 二、准备两张图片 三、编写代码 using OpenCv…...

深入学习 Python 爬虫:从基础到实战

深入学习 Python 爬虫&#xff1a;从基础到实战 前言 Python 爬虫是一个强大的工具&#xff0c;可以帮助你从互联网上抓取各种数据。无论你是数据分析师、机器学习工程师&#xff0c;还是对网络数据感兴趣的开发者&#xff0c;爬虫都是一个非常实用的技能。在本文中&#xff…...

【Web安全】SQL 注入攻击技巧详解:UNION 注入(UNION SQL Injection)

【Web安全】SQL 注入攻击技巧详解&#xff1a;UNION 注入&#xff08;UNION SQL Injection&#xff09; 引言 UNION注入是一种利用SQL的UNION操作符进行注入攻击的技术。攻击者通过合并两个或多个SELECT语句的结果集&#xff0c;可以获取数据库中未授权的数据。这种注入技术要…...

【DAPM杂谈之一】DAPM作用与内核文档解读

本文主要分析DAPM的设计与实现 内核的版本是&#xff1a;linux-5.15.164&#xff0c;下载链接&#xff1a; Linux内核下载 主要讲解有关于DAPM相关的知识&#xff0c;会给出一些例程并分析内核如何去实现的 /****************************************************************…...

计算机网络之---防火墙与入侵检测系统(IDS)

防火墙与入侵检测系统(IDS) 防火墙&#xff08;Firewall&#xff09; 和 入侵检测系统&#xff08;IDS, Intrusion Detection System&#xff09; 都是网络安全的关键组件&#xff0c;但它们的作用、功能和工作方式有所不同。 防火墙 防火墙是网络安全的一种设备或软件&#…...

HTML中meta的用法

学习网络空间安全专业&#xff0c;每个人有每个人的学法和选择。不论他选择什么&#xff0c;哪都是他自己的选择&#xff0c;这就是大多数视频教学的博主教学的步骤都不同原因之一。有人选择丢掉大部分理论直接学习网安&#xff0c;而我&#xff0c;选择了捡起大部分理论学习网…...

前端学习-事件流,事件捕获,事件冒泡以及阻止冒泡以及相应案例(二十八)

目录 前言 事件流与两个阶段说明 说明 事件捕获 目标 说明 事件冒泡 目标 事件冒泡概念 简单理解 阻止冒泡 目标 语法 注意 综合示例代码 总结 前言 梳洗罢&#xff0c;独倚望江楼。过尽千帆皆不是&#xff0c;斜晖脉脉水悠悠。肠断白蘋洲 事件流与两个阶段说明…...

国产OS移植工业物联网OPC-UA协议

国家对于工业互联网、基础软件等关键领域的重视程度不断提升&#xff0c;为工业领域的硬件与软件国产化提供了坚实的政策保障。国产操作系统对工业物联网的一些重要领域的适配支持一直在推进。本次通过国产UOS系统移植测试OPC-UA协议。 1、OPC UA通信协议 OPC UA 协议&#xf…...

第25章 汇编语言--- 信号量与互斥锁

信号量&#xff08;Semaphore&#xff09;和互斥锁&#xff08;Mutex&#xff0c;全称Mutual Exclusion Object&#xff09;是两种用于管理对共享资源的访问的同步机制。它们在多线程或多进程编程中非常重要&#xff0c;可以确保同一时间只有一个线程或进程能够访问特定的资源&…...

写个自己的vue-cli

写个自己的vue-cli 1.插件代码2. 发布流程3. 模板代码讲解3.1 vue2模板的运行流程:3.2 vue3模板的运行流程: 1.插件代码 写一个自己的vue-cli插件 插件地址&#xff1a;插件地址 流程&#xff1a; 实现简单版 vue-cli 步骤文档1. 项目初始化 - 创建项目文件夹 qsl-vue-cli - …...

使用new Vue创建Vue 实例并使用$mount挂载到元素上(包括el选项和$mount区别)

new Vue({...}) 是创建一个新的 Vue 实例的方式。你可以通过传递一个选项对象来配置这个实例。常见的选项包括&#xff1a; •data&#xff1a;定义组件的数据属性。 •el&#xff1a;指定 Vue 实例应该挂载到哪个 DOM 元素上&#xff08;通常是一个选择器字符串&#xff0c;如…...

【理论】测试框架体系TDD、BDD、ATDD、MBT、DDT介绍

一、测试框架是什么 测试框架是一组用于创建和设计测试用例的指南或规则。框架由旨在帮助 QA 专业人员更有效地测试的实践和工具的组合组成。 这些指南可能包括编码标准、测试数据处理方法、对象存储库、存储测试结果的过程或有关如何访问外部资源的信息。 A testing framewo…...

机器学习全流程解析:数据导入到服务上线全阶段介绍

目录 1. 数据导入 2. 数据预处理 3. 超参数搜索与优化 4. 模型训练 5. 模型评估 6. 模型压缩与优化 7. 模型注册与版本管理 8. 服务上线与部署 总结 1. 数据导入 数据源&#xff1a;数据库、文件系统、API等。数据格式&#xff1a;CSV、JSON、SQL 数据库表、Parquet …...

shell脚本练习

1、shell 脚本写出检测 /tmp/size.log 文件如果存在显示它的内容&#xff0c;不存在则创建一个文件将创建时间写入。 if [ -f /tmp/size.log ];thencat /tmp/size.logelsestat exist.sh | awk -F: "NR5" > /tmp/size.logfi ​ 2、写一个 shel1 脚本,实现批量添加…...

金山WPS Android面试题及参考答案

说说你所知道的所有集合?并阐述其内部实现。 在 Android 开发(Java 语言基础上)中有多种集合。 首先是 List 集合,主要包括 ArrayList 和 LinkedList。 ArrayList 是基于数组实现的动态数组。它的内部有一个数组来存储元素,当添加元素时,如果数组容量不够,会进行扩容操作…...

分类模型为什么使用交叉熵作为损失函数

推导过程 让推理更有体感&#xff0c;进行下面假设&#xff1a; 假设要对猫、狗进行图片识别分类假设模型输出 y y y&#xff0c;是一个几率&#xff0c;表示是猫的概率 训练资料如下&#xff1a; x n x^n xn类别 y ^ n \widehat{y}^n y ​n x 1 x^1 x1猫1 x 2 x^2 x2猫1 x …...

高等数学学习笔记 ☞ 单调性、凸凹性、极值、最值、曲率

1. 单调性 1. 单调性定义&#xff1a;设函数在区间上有定义&#xff0c;对于区间上任意两点&#xff0c;若&#xff1a; ①&#xff1a;当时&#xff0c;恒有&#xff0c;则称函数在区间上单调递增。 ②&#xff1a;当时&#xff0c;恒有&#xff0c;则称函数在区间上单调递减…...

【操作系统】详解操作系统及其结构

考察频率难度40%--60%⭐⭐ 这又是一类面试考察题&#xff0c;是关于操作系统的一些概念问题&#xff0c;很少会单独拎出来作为一个问题进行提问&#xff0c;但却是必须要掌握的。因为如果这个你不会&#xff0c;其他的问题就已经没有回答的必要了。 什么是操作系统&#xff1…...

primitive 的 Appearance编写着色器材质

import { nextTick, onMounted, ref } from vue import * as Cesium from cesium import gsap from gsaponMounted(() > { ... })// 1、创建矩形几何体&#xff0c;Cesium.RectangleGeometry&#xff1a;几何体&#xff0c;Rectangle&#xff1a;矩形 let rectGeometry new…...

自动化测试框架搭建-接口数据结构设计

目的 确认数据库如何保存接口数据&#xff0c;既有扩展性&#xff0c;数据又全又好用 根据用途设计数据库字段 区分环境&#xff1a;可以明确当前接口自动化用例&#xff0c;是在哪个环境需要执行的 模块&#xff1a;微服务架构&#xff0c;不同测试同学负责不同的模块&…...

Python自学 - 使用自定义异常

<< 返回目录 1 Python自学 - 使用自定义异常 在Python中&#xff0c; 不仅可以使用内置异常&#xff0c;用户还可以创建自己的异常。自定义异常需要继承自Exception类或其子类&#xff0c;如下是一个自定义异常示例&#xff1a; 示例1&#xff1a;一个简单的自定义异常…...

微信小程序-Docker+Nginx环境配置业务域名验证文件

在实际开发或运维工作中&#xff0c;我们时常需要在 Nginx 部署的服务器上提供一个特定的静态文件&#xff0c;用于域名验证或第三方平台验证。若此时使用 Docker 容器部署了 Nginx&#xff0c;就需要将该验证文件正确地映射&#xff08;挂载&#xff09;到容器中&#xff0c;并…...

“AI智能服务平台系统,让生活更便捷、更智能

大家好&#xff0c;我是资深产品经理老王&#xff0c;今天咱们来聊聊一个让生活变得越来越方便的高科技产品——AI智能服务平台系统。这个系统可是现代服务业的一颗璀璨明珠&#xff0c;它究竟有哪些魅力呢&#xff1f;下面我就跟大家伙儿闲聊一下。 一、什么是AI智能服务平台系…...

【PPTist】插入形状、插入图片、插入图表

一、插入形状 插入形状有两种情况&#xff0c;一种是插入固定的形状&#xff0c; 一种是插入自定义的形状。 插入固定的形状时&#xff0c;跟上一篇文章 绘制文本框 是一样一样的&#xff0c;都是调用的 mainStore.setCreatingElement() 方法&#xff0c;只不多传的类型不一…...

云集电商:数据库的分布式升级实践|OceanBase案例

电商行业对数据库有哪些需求 云集电商作为一家传统电商企业&#xff0c;业务涵盖了美妆个护、服饰、水果生鲜、健康保健等多个领域&#xff0c;在创立四年后在纳斯达克上市&#xff08;股票代码&#xff1a;YJ&#xff09;。与京东、淘宝、拼多多等电商平台不同&#xff0c;云…...

OOM排查思路

K8S 容器的云原生生态&#xff0c;改变了服务的交付方式&#xff0c;自愈能力和自动扩缩等功能简直不要太好用。 有好的地方咱要夸&#xff0c;不好的地方咱也要说&#xff0c;真正的业务是部署于容器内部&#xff0c;而容器之外&#xff0c;又有一逻辑层 Pod 。 对于容器和…...

Q_OBJECT宏报错的问题

在Qt中继承QObject&#xff0c;并且加上Q_OBJECT宏&#xff0c;有时候会报错&#xff0c;比如我的错误&#xff1a; error: debug/httpmgr.o:httpmgr.cpp:(.rdata$.refptr._ZTV7HttpMgr[.refptr._ZTV7HttpMgr]0x0): undefined reference to vtable for HttpMgr 意思是没有虚…...

iOS - 关联对象

详细总结 Objective-C 的关联对象功能&#xff1a; 1. 基本使用 // 1. 设置关联对象 objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);// 2. 获取关联对象 id objc_getAssociatedObject(id object, const void *key);// 3. …...

Linux之进程

Linux之进程 一.进程进程之形ps命令进程状态特殊进程孤儿进程守护进程 进程创建之创建子进程进程特性优先级进程切换&#xff08;分时操作系统&#xff09; 二.环境变量三.进程地址空间四.进程终止&进程等待五.进程替换六.自定义shell 本篇博客希望简略的介绍进程&#xff…...

数据库事务

一 事务的概念 为什么要有事务&#xff0c;我们先前没学事务&#xff0c;也能写sql语句&#xff0c;事务的意义是什么? 由来: 是为了服务应用层开发&#xff0c;降低开发难度。假如没有事务&#xff0c;那我们身为开发人员&#xff0c;要处理转账需求&#xff0c;此时一定是有…...

Python statistics 模块

在数据分析和科学计算中&#xff0c;统计学是一个非常重要的工具。 Python 提供了一个内置的 statistics 模块&#xff0c;专门用于处理基本的统计计算。本文将详细介绍 statistics 模块的功能和使用方法&#xff0c;帮助初学者快速掌握如何使用这个模块进行基本的统计分析。 …...

AI知识-TF-IDF技术(Term Frequency-Inverse Document Frequency)

摘要 TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09;是一种常见的统计方法&#xff0c;用于评估一个词对于一个文档集或一个语料库中的其中一份文档的重要性。本文将全面阐述TF-IDF的通俗理解、技术原理、应用场景&#xff0c;并做以总结。 通俗理…...

spring cloud的核心模块有哪些

Spring Cloud 的核心模块就像一套精心设计的工具箱&#xff0c;每个模块都扮演着特定的角色&#xff0c;共同构建起微服务架构的坚实基础。 1. Spring Cloud Netflix&#xff08;部分组件已迁移或弃用&#xff0c;但仍是理解 Spring Cloud 的重要参考&#xff09;&#xff1a; …...

java_将数据存入elasticsearch进行高效搜索

使用技术简介&#xff1a; (1) 使用Nginx实现反向代理&#xff0c;使前端可以调用多个微服务 (2) 使用nacos将多个服务管理关联起来 (3) 将数据存入elasticsearch进行高效搜索 (4) 使用消息队列rabbitmq进行消息的传递 (5) 使用 openfeign 进行多个服务之间的api调用 参…...

RAG中的文本切分策略详解

RAG中的文本切分策略详解 1. 选择RAG中的文本切分策略 1.1 不同的文本切分策略 1. CharacterTextSplitter - 这是最简单的方法。它默认基于字符(默认为"")来切割,并且通过字符的数量来衡量块的长度 2. RecursiveCharacterTextSplitter - 基于字符列表拆分文本。 …...

1-1 电场基本概念

目录&#xff1a; 目录 目录&#xff1a; 1.0 电荷守恒定律 2.0 互斥与相吸 3.0 电场的概念 4.0 库伦定律 5.0 矢量的概念 1.0 电荷守恒定律 电荷守恒定律是物理学中的一个基本原理&#xff0c;它指出在一个封闭系统内&#xff0c;电荷的总量是保持不变的。这意味着电荷既…...

SpringBoot初始化执行自定义接口

SpringBoot初始化执行自定义接口 直接加载接口的方法上即可 PostConstructpublic void init() {//加载初始化数据}PostConstruct‌是一个在Java EE 5规范中引入的注解&#xff0c;用于标记在依赖注入完成后需要执行的方法。这个注解定义在javax.annotation包中&#xff0c;而不…...

【Ubuntu与Linux操作系统:一、Ubuntu安装与基本使用】

第1章 Ubuntu安装与基本使用 1.1 Linux与Ubuntu Linux是一种开源、类Unix操作系统内核&#xff0c;拥有高稳定性和强大的网络功能。由于其开源性和灵活性&#xff0c;Linux被广泛应用于服务器、嵌入式设备以及桌面环境中。 Ubuntu是基于Debian的一个流行Linux发行版&#xf…...

C++大端小端判断方法

文章目录 大端小端定义判断方法方法一&#xff1a;利用联合体&#xff08;Union&#xff09;特性判断方法二&#xff1a;通过指针类型转换判断方法三&#xff1a;利用位运算与移位操作判断方法四&#xff1a;使用系统提供的字节序相关宏&#xff08;特定平台支持&#xff09; 联…...

【IO编程】标准IO和文件IO的对比

标准 I/O 和 文件 I/O 是两种常见的输入输出操作方式。它们的核心功能都是处理数据流&#xff0c;但使用场景和实现方式有所不同&#xff0c;适用于不同的需求。 标准 I/O 标准 I/O 是指与标准输入、标准输出和标准错误流&#xff08;分别为 stdin、stdout 和 stderr&#xf…...

C#范围表达式,模式匹配,逆变和协变--11

目录 一.范围表达式 1.概述 2.语法 3.代码示例 4.实现原理 5.应用场景 二.模式匹配 1.概述 2.核心概念 3.常用模式类型 4.Switch表达式 5.使用示例 6.优势 三.逆变和协变 1.概述 2.泛型类型参数的变性 3.协变示例 4.逆变示例 5.注意事项 6.应用场景 总结 一…...

矩阵求逆的几种方式

矩阵求逆的几种方式&#xff08;以二阶为例&#xff09; 矩阵求逆的方法有多种&#xff0c;以下是常用的几种方式总结&#xff1a; 1. 行列式公式法 这是最常见的方法&#xff0c;适用于 2 2 2 \times 2 22矩阵。 对于矩阵&#xff1a; Φ [ a b c d ] , \Phi \begin{bma…...