分布式数据库中全局自增序列的实现

news2024/12/23 3:11:38

自增序列广泛使用于数据库的开发和设计中,用于生产唯一主键、日志流水号等唯一ID的场景。传统数据库中使用Sequence和自增列的方式实现自增序列的功能,在分布式数据库中兼容Oracle和MySQL等传统数据库语法,也是基于Sequence和自增列的方式实现分布式架构下的全局唯一ID。本文简要介绍了传统数据库和分布式数据库的自增序列实现方式,并且突出NOCYCLE非循环使用的自增序列在监控上的策略。


1、传统数据库的自增序列实现

在关系型数据库的开发过程中,自增序列或自增列使用场景非常广泛,可以生成唯一ID作为主键、生成唯一标识符,也可以生成顺序编号如交易流水号、订单编号等。因此在传统的Oracle、DB2和MySQL等数据库中通过Sequence这一特殊的数据库对象或者自增列的方式实现自增序列,满足应用开发中唯一ID的需求和性能要求。

1.1 Sequence对象实现
1.1.1 Oracle数据库

Sequence是Oracle数据库中的特殊的数据库对象,用于生成唯一的序列。Oracle数据库中创建Sequence语法如下:

CREATE SEQUENCE sequence_name  
    START WITH start_value  
    INCREMENT BY increment_value  
    [NO MAXVALUE] | [MAXVALUE max_value]  
    [NO MINVALUE] | [MINVALUE min_value]  
    [CACHE cache_value]  
    [NO ORDER] | [ORDER]  
    [CYCLE] | [NO CYCLE]  
[RESET ON START] | [NO RESET ON START];

相关参数如下:

  • sequence_name:Sequence的名称。
  • START WITH start_value:指定Sequence的起始值。
  • INCREMENT BY increment_value:指定每次调用Sequence时数值的增量。
  • MAXVALUE max_value和MINVALUE min_value:指定Sequence的最大值和最小值。
  • CACHE cache_value:指定预先生成的数值数量并存储在内存中以提高性能。
  • NO ORDER和ORDER:指定Sequence值是否按请求顺序生成。
  • CYCLE和NO CYCLE:指定当Sequence达到最大值或最小值后是否重新开始。
  • RESET ON START 和 NO RESET ON START:指定在数据库重启后是否重置Sequence值。

注意CYCLE和NO CYCLE定义,指定自增列是否定义为循环使用。

2)Sequence的使用

Oracle中使用CURRVAL和NEXTVAL获取序列的当前值和下一个值,如下所示:

##获取当前值
select 序列名称.currval  from  dual
##获取下一个值 
select  序列名称.nextval  from dual

Sequence在使用上主要包括以下,对于一些子查询、关联查询或者GROUP BY/ORDER BY语句中是不可以使用sequence的:

  • INSERT的VALUES子句、子查询
  • 不包含子查询、snapshot、视图的SELECT语句中的列表
  • UPDATE的SET子句

需要注意的是同个Sequence有多个用户并发使用时,每个用户只能获取一次Sequence的下一个值。如果需要确保并发访问时的唯一性,需要使用数据库锁或其他机制来控制并发访问。

1.1.2 DB2数据库

DB2数据库中sequence对象出现之前最早是Identify列(类似自增列的概念),后来为解决自增列的一些问题及合入其它功能,引入Sequence。创建Sequence语法与Oracle类似:

CREATE SEQUENCE sequence_name  
    START WITH start_value  
    INCREMENT BY increment_value  
    [NO MAXVALUE] | [MAXVALUE max_value]  
    [NO MINVALUE] | [MINVALUE min_value]  
    [CACHE cache_value]  
    [NO ORDER] | [ORDER]  
    [CYCLE] | [NO CYCLE]  
[RESET ON START] | [NO RESET ON START];

相关参数如下:

  • sequence_name:Sequence的名称。
  • START WITH start_value:指定Sequence的起始值。
  • INCREMENT BY increment_value:指定每次调用Sequence时数值的增量。
  • MAXVALUE max_value和MINVALUE min_value:指定Sequence的最大值和最小值。
  • CACHE cache_value:指定预先生成的数值数量并存储在内存中以提高性能。
  • NO ORDER和ORDER:指定Sequence值是否按请求顺序生成。
  • CYCLE和NO CYCLE:指定当Sequence达到最大值或最小值后是否重新开始。
  • RESET ON START 和 NO RESET ON START:指定在数据库重启后是否重置Sequence值。

创建好Sequence后,可以在SQL语句中使用sequence,如INSERT语句中插入自增序列值、select语句中查询自增值。

1)在INSERT语句中使用NEXTVAL FOR来获取Sequence的下一个值,并将其插入到表的相应列中

INSERT INTO USER(USER_ID, USER_NAME)  VALUES(NEXTVAL FOR SEQ_USER_ID, 'username1');

2)通过查询Sequence来获取其当前值或下一个值

SELECT NEXTVAL FOR SEQ_USER_ID FROM SYSIBM.SYSDUMMY1;
1.2 自增列实现
1.2.1 Oracle数据库

Oracle数据库本身并不直接支持自增列(类似MySQL中的AUTO_INCREMENT)的创建,其提供了触发器结合Sequence来实现类似的功能。在创建了Sequence以后,创建一个BEFORE INSERT触发器,该触发器会在每次插入新行之前从序列中获取下一个值,并将其设置为自增列的值。

CREATE OR REPLACE TRIGGER trg_my_table_before_insert  
BEFORE INSERT ON my_table  
FOR EACH ROW  
BEGIN  
    SELECT seq_name.NEXTVAL  
    INTO   :new.id  
    FROM   dual;  
END;  
/

当插入数据时,不需要指定自增列的值,触发器会自动创建自增的序列值。

1.2.2 DB2数据库

DB2数据库在引入Sequence之前是使用identify列实现自增列,语法如下:

CREATE TABLE table_name (  
    column1 datatype [constraint],  
    column2 datatype [constraint],  
    identity_column datatype GENERATED ALWAYS AS IDENTITY (  
        START WITH start_value  
        INCREMENT BY increment_value  
        [NO MAXVALUE] | [MAXVALUE max_value]  
        [NO MINVALUE] | [MINVALUE min_value]  
        [CACHE cache_value]  
        [CYCLE] | [NO CYCLE]  
    ),  
    ...  
);

其中GENERATED ALWAYS AS IDENTITY指定该列为自增列。可以看到DB2中的自增列是在创建表时直接定义的,而不是在表创建后单独添加。此外,自增列只能用于表的主键,且每个表只能有一个自增列。和Sequence相比,自增列在使用上有限制,只能定义在单表上,另外对自增列的更改将导致表空间被置为Reorg-pending状态。

1.2.3 MySQL数据库

在MySQL数据库中没有Sequence这个数据库对象,但是通过为表的某一列设置AUTO_INCREMENT属性来创建一个自增列,并且通常作为主键。如下所示,在创建表时,在id列指定AUTO_INCREMENT属性,每次插入新行时,这一列的值就会自动递增。

CREATE TABLE t1 (  
    id INT NOT NULL AUTO_INCREMENT,  
    c1 VARCHAR(50) NOT NULL,  
    PRIMARY KEY (id)  
);

另外在MySQL中有一些系统变量定义了自增列的属性:

mysql> show vaiables like 'AUTO_INCREMENT%'
+----------------------------------+-------+  
| Variable_name                    | Value |  
+----------------------------------+-------+  
| auto_increment_increment         | 1     |  
| auto_increment_offset            | 1     |  
| auto_increment_wrap              | 0     |  
| auto_increment_for_each_replica  | OFF   |  
+----------------------------------+-------+

相关参数解释如下:

  • auto_increment_increment:控制自增列每次递增的量。默认值为1,意味着每次插入新行时自增列的值增加1。
  • auto_increment_offset:在复制环境中,用于设置自增列的起始偏移量,以避免在多个服务器上生成相同的自增ID。默认值为1。
  • auto_increment_wrap:当设置为非零值时,自增列的值会在达到最大值后回绕到最小值。这通常用于循环使用自增ID的场景。默认值为0,表示不启用回绕。相当于Sequence定义中的Cycle和Nocycle。
  • auto_increment_for_each_replica: 在MySQL 8.0及更高版本中,当设置为ON时,每个复制从服务器将独立生成自增ID。这有助于避免在多个从服务器上生成相同的自增ID。默认值为OFF。

另外在mysql中多并发申请自增列时通过innodb_autoinc_lock_mode参数控制在插入新记录时如何锁定自增计数器,这个参数影响在并发插入操作中的性能和锁争用。

  • 0 (TRADITIONAL):这是传统的锁定模式。在每次插入操作中,InnoDB 会对自增计数器进行锁定,以确保生成的自增 ID 是唯一的。这种模式下,并发插入可能会受到严重的限制,因为每次插入都需要等待前一个插入操作完成并释放锁。
  • 1 (CONSECUTIVE):在这种模式下,InnoDB 会尝试在单个事务中预先分配多个自增 ID,然后逐个使用它们。这样可以减少锁定的次数,从而提高并发插入的性能。但是,如果事务被回滚,那么预先分配但未使用的 ID 会被浪费。
  • 2 (INTERLEAVED):这是MySQL 5.6引入的新模式。在这种模式下,InnoDB会根据实际需要动态地选择是否预先分配多个自增 ID。这结合了前两种模式的优点,试图在并发性和ID浪费之间找到一个平衡点。

默认情况下是1,innodb_autoinc_lock_mode参数的修改要重启mysql实例才能生效。

1.3 Sequence和自增列对比

从上文中可以看到在传统数据库中自增序列的实现有两种方式:sequence和自增列,那么二者在使用上有哪些不同之处?如下表所示:

在这里插入图片描述

最主要的区别是Sequence是数据库中的对象,可以创建、修改和删除、授权等操作,并且在使用上更为灵活。

2、分布式数据库中自增序列实现

上文看到在传统数据库Oracle、DB2和MySQL中对自增序列的支持,当然在国产分布式数据库中对传统数据库语法的兼容,也支持通过Sequence对象和自增列的方式实现自增序列。不过与传统集中数据库不同之处是,分布式数据库中如何保证自增序列在分布式架构下的全局自增。

2.1 OceanBase数据库

OceanBase数据库中支持创建sequence对象和自增列两种方式实现自增序列。

1)Sequence实现

使用CREATE SEQUENCE语句可以创建sequence对象,语法如下:

CREATE SEQUENCE [ IF NOT EXISTS ] [ schema. ] sequence_name
{ START WITH int_value
|[ INCREMENT BY int_value ]
|[ MINVALUE int_value | NOMINVALUE ]
|[ MAXVALUE int_value | NOMAXVALUE ]  
|[ CACHE int_value | NOCACHE ]
|[ ORDER | NOORDER ]
|[ CYCLE | NOCYCLE ]  
}
;

语法上和传统数据库没有什么区别。创建序列后,可以在SQL语句中使用CURRVAL伪列返回序列当前值或使用NEXTVAL伪列返回递增的新值。

  • Cache指在内存中预分配的自增值个数,默认为20
  • CYCLE/NOCYCLE:CYCLE为默认值,指定序列在达到其最大值或最小值后无法生成更多值。

2)自增列AUTO_INCRREMENT

OceanBase作为分布式数据库,兼容MySQL的自增列特性,不同的是在分布式多实例的场景下自增列生成会出现跳变。

CREATE TABLE t1(id bigint not null auto_increment primary key, 
c1 varchar(50));
Query OK, 0 rows affected

在OceanBase数据库V4.x版本开始新增了ORDER模式的自增列,以避免NOORDER模式中多机多分区生成自增值和通过INSERT语句插入指定的最大值等比较常用的使用场景下发生自增值跳变的问题。

在这里插入图片描述

ORDER模式的自增列会在所有OBServer节点中选取当前集群的Leader作为自增列服务的Leader,其它作为Follower的OBServer节点需要通过发送RPC请求来从作为Leader的OBServer节点处申请自增值,而作为Leader的OBServer节点会从内部表申请自增区间来作为自增缓存。

因此,在大部分场景下和单机MySQL一样可以生成连续的全局自增序列,但是在大并发场景下,ORDER模式的性能会较差。并且在Leader节点重启或宕机、切主等极端情况下,仍然会出现自增值的跳变情况。为了避免切主场景下出现自增值跳变的问题,发生切主的时候会将将原Leader的OBServer节点上的缓存区间清理掉。

2.2 TiDB数据库

1)Sequence使用

TiDB数据库v4.0版本开始支持序列功能,具体语法如下:

CREATE [TEMPORARY] SEQUENCE [IF NOT EXISTS] sequence_name
    [ INCREMENT [ BY | = ] increment ]
    [ MINVALUE [=] minvalue | NO MINVALUE | NOMINVALUE ]
    [ MAXVALUE [=] maxvalue | NO MAXVALUE | NOMAXVALUE ]
    [ START [ WITH | = ] start ]
    [ CACHE [=] cache | NOCACHE | NO CACHE]
    [ CYCLE | NOCYCLE | NO CYCLE]
    [table_options]
  • Cache:指定每个TIDB实例本地缓存的大小,默认是1000
  • CYCLE/COCYCLE:指定序列用完之后是否循环使用

定义完Sequence后,可以通过NEXTVAL、LASTVAL获取下一个序列值和上一次使用的序列值,SETVAL可以设置序列的增长返回一个满足增长值的序列值。

SELECT nextval(seq);
SELECT lastval(seq);
SELECT setval(seq, 10);

2)自增列auto_increment

TiDB中兼容MySQL数据库的auto_increment特性,在v6.4.0版本之前TiDB数据库和OceanBase一样存在自增值跳变的问题,v6.4.0版本之后支持在所有TiDB实例上全局单调自增。建表时候创建自增列语法如下:

CREATE TABLE t(id int PRIMARY KEY AUTO_INCREMENT, c int);

TiDB 在v6.4.0版本实现了中心化分配自增ID的服务,当前中心化分配服务内置在TiDB进程,类似于DDL Owner的工作模式。其中有一个TiDB实例将充当“主”的角色提供ID分配服务,而其它的TiDB实例将充当“备”角色。当“主”节点发生故障时,会自动进行“主备切换”,从而保证中心化服务的高可用。

在建表时将AUTO_ID_CACHE设置为1,表示使用MySQL兼容模式,该模式下能保证ID唯一、单调递增,行为几乎跟MySQL完全一致。只有当中心化服务的“主”TiDB实例异常崩溃时,才有可能造成少量ID不连续。这是因为主备切换时,“备”节点需要丢弃一部分之前的“主”节点可能已经分配的ID,以保证ID不出现重复。

2.3 GoldenDB数据库

GoldenDB分布式数据库中的自增序列有sequence和auto_increment两种方式,自增序列值由全局事务节点GTM统一分配和维护管理。

1)Sequence创建

Sequence创建的语法:

CREATE SEQUENCE schema.sequence
INCREMENT BY num
START WITH num
MAXVALUE num | NOMAXVALUE
MINVALUE num | NOMINVALUE
CYCLE | NOCYCLE
CACHE | NOCACHE

SEQUENCE默认CACHE为100,修改步长时会导致当前CACHE丢失。由于SEQUENCE的值是在SQL语句执行之前向GTM申请,语句执行失败的情形下申请的SEQUENCE值不能够回收,所以表中的数据会有不连续的情形。

2)自增列auto_increment

GoldenDB数据库兼容MySQL的自增列特性,在建表时候指定auto_increment即可:

CREATE TABLE t1 (  
    id INT NOT NULL AUTO_INCREMENT,  
    c1 VARCHAR(50) NOT NULL,  
    PRIMARY KEY (id)  
);

GoldenDB数据库中的Sequence和自增列由GTM统一管理,定义后通过dbtool -gtm -show-seq命令可以查看自增列的信息:

dbtool -gtm -show-seq -clusterid=2
Send message to other module successfully!
The response message: RSP Code[0].{0:success; 1:provisional response; other: fail.}
Successful response: 
clusterid|database|name,start,step,minval,maxval,cache,cycle,curvalue
1|testdb1|t_seq,10,10,1,9223372036854775807,5,0,160610
2|testdb2 |seq_test1,1,1,1,9223372036854775807,1,0,16016
~success~

在多并发申请自增列的场景中,GTM会先将请求放到一个队列中,再统一分配自增值,这样可以减少自增序列请求交互的开销、保证自增列的连续性,不过在极少数高并发场景下可能会存在一定的性能瓶颈。

2.4 TDSQL for MySQL数据库

TDSQL for MySQL分布式数据库版本中支持创建sequence和自增列。

1)Sequence支持

TDSQL支持使用sequence,需要注意的是Sequence为保证分布式全局数值唯一,导致性能较差,主要适用于并发不高的场景。语法如下:

CREATE TDSQL_SEQUENCE {DATABASE | SCHEMA} [IF NOT EXISTS] sequence_name
[ TDSQL_INCREMENT BY increment ]
[ START WITH startvalue ]
[ TDSQL_MINVALUE minvalue] | [ TDSQL_NOMINVALUE ] 
[ TDSQL_MAXVALUE maxvalue] | [ TDSQL_NOMAXVALUE ]
[ TDSQL_CACHE cachevalue ] | [ TDSQL_NOCACHE ]
[ TDSQL_CYCLE ] | [ TDSQL_NOCYCLE ]
[ TDSQL_ORDER ] | [ TDSQL_NOORDER ]
-- 查看sequence建表语句
SHOW CREATE TDSQL_SEQUENCE sequence_name;

创建sequence后,可以通过nextval和lastval获取下一个序列值和上一次使用的值:

-- 使用Sequence获取下一个数值
select tdsql_nextval(test.seq2);
select next value for test.seq2;
-- 获取上一次的值
select tdsql_lastval(test.seq2);
select tdsql_previous value for test.seq2;

2)全局唯一序列auto_increment

TDSQL支持全局唯一数字序列(auto_increment)的使用;当前10.3.22版本暂时仅保证自增字段全局唯一和递增性,但是不保证单调递增(也就是OceanBase和TiDB之前版本出现的跳变问题)。全局唯一数字序列(auto_increment)长8字节,最大为18446744073709551616,建表时候创建自增列:

create table auto_inc 
(a int,
b int auto_increment,
key auto(b),
primary key p(a,b)) 
shardkey=a;

通过select last_insert_id()命令获取最新自增值,暂不支持直接从Insert返回包获取。目前select last_insert_id()只能跟shard表和广播表的自增字段一起使用,不支持noshard表。

MySQL [test]> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 1009 |
+------------------+
1 row in set (0.00 sec)

由于auto_increment仅保证自增字段全局唯一和递增性,如果在节点调度切换、重启等过程中,自增长字段中间会出现空洞。

2.5 GaussDB for OpenGauss数据库

GaussDB分布式数据库(for opengauss)版本中也支持sequence对象和自增列方式实现自增序列,并由GTM(全局事务管理器)统一维护管理,保证序列号全局唯一性。

  • 建表时声明字段的类型为序列整型,由数据库在后台自动创建一个对应的Sequence。
  • 使用CREATE SEQUENCE自定义一个新的Sequence,然后将nextval(‘sequence_name’)函数读取的序列值,指定为某一字段的默认值,这样该字段就可以作为唯一标识符。

1)Sequence对象

GaussDB中Sequence是一个存放等差数列的特殊表,该表受DBMS控制。这个表没有实际意义,通常用于为行或者表生成唯一的标识符。创建语法如下:

CREATE SEQUENCE name [ INCREMENT [ BY ] increment ]
    [ MINVALUE minvalue | NO MINVALUE | NOMINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE | NOMAXVALUE] 
    [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE | NOCYCLE ] 
    [ OWNED BY { table_name.column_name | NONE } ];
  • Cache:为了快速访问,而在内存中预先存储序列号的个数,默认为1。
  • CYCLE/NOCYCLE:用于使序列达到maxvalue或者minvalue后可循环并继续下去。若定义序列为CYCLE,则不能保证序列的唯一性。

在GaussDB中,不建议同时定义cache和maxvalue或minvalue。因为定义cache后不能保证序列的连续性,可能会产生空洞,造成序列号段浪费。如对并发性能有要求,指定参数session_sequence_cache。cache指定了单CN/DN一次向GTM中申请的值;session_sequence_cache指定的是单个会话一次向CN/DN申请缓存的值,会话结束后会自动丢弃。

2)声明字段类型为serial

gaussdb=# CREATE TABLE T1
(
    id    serial,
    name  text
);

在后台会自动创建一个sequence序列。另外,将sequence和一个表的指定字段关联后,当删除那个字段或其所在表的时候会自动删除已关联的sequence。

2.6 自增序列的维护和监控

从上文可以看到各个分布式数据库产品中已经实现了自增序列的功能保证全局唯一性,在实际使用过程中开发关心的是全局序列的唯一性和并发访问时候的性能,从运维视角来看主要是自增序列的使用值监控。Sequence在定义的时候有CYCLE和NOCYCLE两种模式,业务使用场景中不是所有的都能使用CYCLE循环模式,毕竟无法保证它的唯一性。如果是NOCYCLE模式,肯定有个上限,申请的序列值达到上限后,业务访问会报错,如何做好监控和维护?

1)Sequence序列对象的监控

Sequence对象在定义的时候指定了MAXVALUE或者使用系统默认的最大value,通过SQL语句查询当前的VALUE值CURRVAL和最大值比较获得使用率,并以定时任务或脚本方式部署到监控中。有些数据库如GoldenDB和GaussDB中,本身有管理组件GTM对sequence维护管理,由数据库本身实现sequence使用率的监控。

2)自增列的监控

自增列auto_increment随着业务的插入操作,自增值不断增长。在MySQL系列的数据库中,通过自定义视图来监控自增列的使用情况,以下是一个例子:

##1、从information_schema.full_columns中查出table_name,table_schema,column_name,data_type,column_type等信息

##2、根据自增列的data_type得到最大值
case information_schema.full_columns.data_type when ‘tinyint’ then 255 when ‘smallint’ then 65535 when ‘mediumint’ then 16777215 when ‘int’ then 4294967295 when ‘bigint’ then 18446744073709551615)

##3、从表information_schema.full_tables中获取auto_increment使用值

以上是自增序列的监控手段,实际操作过程中需要增加自增序列的使用这一监控指标并定制监控策略。


参考资料:

  1. https://www.oceanbase.com/docs
  2. https://docs.pingcap.com/zh/tidb/stable/
  3. https://cloud.tencent.com/document/product/557/47526
  4. GoldenDB分布式数据库SQL指南
  5. GaussDB云数据库操作指南

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

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

相关文章

使用Visual Studio 2022 创建lib和dll并使用

概述:对于一个经常写javaWeb的人来说,使用Visual Studio似乎没什么必要,但是对于使用ffi的人来说,使用c或c编译器,似乎是必不可少的,下面我将讲述如何用Visual Studio 2022 来创建lib和dll,并使用。 静态库…

UNIapp实现局域网内在线升级

首先是UNIapp 生成apk 用Hbuilder 进行打包 可以从网站https://www.yunedit.com/reg?gotocert 使用自有证书,目测比直接使用云证书要快一些。 发布apk 网站 用IIS发布即可 注意事项中记录如下内容 第一、需要在 iis 的MiMe 中添加apk 的格式,否则无法…

Java架构之路-架构应全面了解的技术栈和工作域

有时候我在想这么简单简单的东西,怎么那么难以贯通。比如作为一个架构师可能涉及的不单单是技术架构,还包含了项目管理,一套完整的技术架构也就那么几个技术栈,只要花点心思,不断的往里面憨实,总会学的会&a…

UE4升级UE5 蓝图节点变更汇总(4.26/27-5.2/5.3)

一、删除部分 Ploygon Editing删除 Polygon Editing这个在4.26、4.27中的插件,在5.1后彻底失效。 相关的蓝图,如编辑器蓝图 Generate mapping UVs等,均失效。 如需相关功能,请改成Dynamic Mesh下的方法。 GetSupportedClass删…

在K8S集群中部署SkyWalking

1. 环境准备 K8S 集群kubectlhelm 2. 为什么要部署SkyWalking? 我也不道啊,老板说要咱就得上啊。咦,好像可以看到服务的各项指标,像SLA,Apdex这些,主要是能够进行请求的链路追踪,bug排查的利…

C向C++的一个过渡

思维导图 输入输出,以及基础头文件 在c语言中我们常用scanf("%d",&n);和printf("%d\n",n);来输出一些变量和常量,在C中我们可以用cin;和cout;来表示输入输出。 在C语言中输入输出有头文件,在C也有头文件&#xff0…

解放人力,提升品质:码垛输送机的工业应用与价值

在现代工业生产中,码垛输送机已成为许多企业自动化生产线上的关键设备。它不仅可以提高生产效率,降低人力成本,还能确保产品质量,并为企业带来许多其他方面的实际好处。 1. 提高生产效率: 快速码垛:码垛输…

蓝桥杯练习题——dp

五部曲(代码随想录) 1.确定 dp 数组以及下标含义 2.确定递推公式 3.确定 dp 数组初始化 4.确定遍历顺序 5.debug 入门题 1.斐波那契数 思路 1.f[i]:第 i 个数的值 2.f[i] f[i - 1] f[i - 2] 3.f[0] 0, f[1] 1 4.顺序遍历 5.记得特判 …

基于springboot+vue的医院药品管理系统

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

STM32CubeIDE基础学习-新建STM32CubeIDE基础工程

STM32CubeIDE基础学习-新建STM32CubeIDE基础工程 前言 有开发过程序的朋友都清楚,后面开发是不需要再新建工程的,一般都是在初学时或者有特殊需要的时候才需要新建项目工程的。 后面开发都是可以在这种已有的工程上添加相关功能就行,只要前…

Linux系统部署Discuz论坛并发布至公网随时随地可远程访问

目录 ​编辑 前言 1.安装基础环境 2.一键部署Discuz 3.安装cpolar工具 4.配置域名访问Discuz 5.固定域名公网地址 6.配置Discuz论坛 结语 作者简介: 懒大王敲代码,计算机专业应届生 今天给大家聊聊Linux系统部署Discuz论坛并发布至公网随时随地…

Qt+FFmpeg+opengl从零制作视频播放器-1.项目介绍

1.简介 学习音视频开发,首先从做一款播放器开始是比较合理的,每一章节,我都会将源码贴在最后,此专栏你将学习到以下内容: 1)音视频的解封装、解码; 2)Qtopengl如何渲染视频&#…

matlab 提取分割位于多边形区域边缘内部或边缘上的点

[in,on] = inpolygon(xq,yq,xv,yv) xv 和 yv 为定义的多边形区域的,如xv = [1 4 4 1 1 ];yv = [1 1 4 4 1 ];注意最后一个数字与第一个重复,保证多边形闭合; xq 和 yq 为待查询的点in:在多边形内部和边缘的点序号on:仅在多边形边缘的点序号 提取分割方法: matrix=[xq yq…

Hystrix的一些了解

Hystrix如何实现容错 Hystrix是一个延迟和容错库,旨在隔离远程系统,服务和第三方库的访问点,当出现故障是不可避 免的故障时,停止级联故障并在复杂的分布式系统中实现弹性。 通常对于使用微服务架构开发的系统,涉及到…

12. Nginx进阶-Location

简介 Nginx的三大区块 在Nginx中主要配置包括三个区块,结构如下: http { #协议级别include /etc/nginx/mime.types;default_type application/octet-stream;log_format main $remote_addr - $remote_user [$time_local] "$r…

13-Java代理模式 ( Proxy Pattern )

Java代理模式 摘要实现范例 代理模式(Proxy Pattern)使用一个类代表另一个类的功能 代理模式创建具有现有对象的对象,以便向外界提供功能接口 代理模式属于结构型模式 摘要 1. 意图 为其他对象提供一种代理以控制对这个对象的访问2. 主…

游戏引擎用什么语言开发上层应用

现在主流的游戏引擎包括: 1、Unity3D,C#语言,优点在于支持几乎所有平台 丹麦创立的一家公司,现已被微软收购。在中国市场占有率最高,也是社群很强大,一般解决方案也能在网上找到,教程丰富。物理…

springboot项目单纯使用nacos注册中心功能

Spring Boot 项目完全可以单独使用 Nacos 作为注册中心。Nacos 是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。它支持服务的注册与发现,能够与 Spring Boot 应用无缝集成,为微服务架构提供了强大的支持。 在使用 Nacos 作为注册中…

eclipse搭建java web项目

准备条件 eclipsejdk1.8 (配置jdk环境)apache-tomcat-8.5.97(记住安装位置) 一 点击完成 开始创建javaweb项目 import java.io.IOException; import java.io.PrintWriter;import javax.servlet.ServletException; import javax.s…

java VR全景商城 saas商城 b2b2c商城 o2o商城 积分商城 秒杀商城 拼团商城 分销商城 短视频商城 小程序商城搭建

1. 涉及平台 平台管理、商家端(PC端、手机端)、买家平台(H5/公众号、小程序、APP端(IOS/Android)、微服务平台(业务服务) 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…