CN115563226A - 基于数据库的数据消费方法、控制装置及可读存储介质 - Google Patents
基于数据库的数据消费方法、控制装置及可读存储介质 Download PDFInfo
- Publication number
- CN115563226A CN115563226A CN202211117619.1A CN202211117619A CN115563226A CN 115563226 A CN115563226 A CN 115563226A CN 202211117619 A CN202211117619 A CN 202211117619A CN 115563226 A CN115563226 A CN 115563226A
- Authority
- CN
- China
- Prior art keywords
- data
- message
- database
- message data
- message queue
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Pending
Links
Images
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F16/00—Information retrieval; Database structures therefor; File system structures therefor
- G06F16/20—Information retrieval; Database structures therefor; File system structures therefor of structured data, e.g. relational data
- G06F16/28—Databases characterised by their database models, e.g. relational or object models
- G06F16/284—Relational databases
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F16/00—Information retrieval; Database structures therefor; File system structures therefor
- G06F16/20—Information retrieval; Database structures therefor; File system structures therefor of structured data, e.g. relational data
- G06F16/27—Replication, distribution or synchronisation of data between databases or within a distributed database system; Distributed database system architectures therefor
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/46—Multiprogramming arrangements
- G06F9/54—Interprogram communication
- G06F9/546—Message passing systems or structures, e.g. queues
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Databases & Information Systems (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Data Mining & Analysis (AREA)
- Software Systems (AREA)
- Computing Systems (AREA)
- Information Retrieval, Db Structures And Fs Structures Therefor (AREA)
Abstract
本发明涉及数据处理技术领域,具体提供一种基于数据库的数据消费方法、控制装置及可读存储介质,旨在解决在基于消息队列进行数据处理时,如何确保数据的强一致性的问题。为此目的,本发明中生产者将生产的业务数据对应的消息数据写入数据库的消息队列表中,且消息数据和业务数据被写入同一个数据库中,由同一事务进行管理,消费者从数据库中的消息队列表中加载消息数据进行消费。通过上述配置方式,本发明通过将业务数据和对应的消息数据写入同一数据库中,由同一事物进行管理,能够有效确保数据的强一致性,从而有效避免由于程序中断等各种原因造成的消息未能通知到消费者的情况,无需再额外设置补偿机制来解决上述问题。
Description
技术领域
本发明涉及数据处理技术领域,具体提供一种基于数据库的数据消费方法、控制装置及可读存储介质。
背景技术
消息队列(Message Queue,MQ)是一种进程间通信或同一进程的不同线程间的通信方式,是分布式应用间交换信息的一种技术。现有的消息队列框架中有具备高性能、高吞吐量RabbitMQ、RocketMQ、Kafka等等。这些消息队列能够帮助我们解决很多问题。但是这些消息队列也存在着一些问题,在并不适用于所有的应用场景。如,在数据一致性非常高的情况下,即对企业外部发送消息时是不能使用上述消息队列的。
在数据一致性要求比较高的情况下,一般是使用支持事务数据库来进行消息的存储,以方便在出现异常情况时进行回滚,以确保数据的强一致性。这时如果使用消息队列来发送消息,就会导致双写不一致的问题。比如:A系统处理的业务,依赖B系统来完成,假设我们使用消息队列来实现发送消息,那么就可能出现如下情况:A系统处理完一些业务数据后写入数据库(事务已提交成功),但是消息队列通知B系统,此时由于程序突然中断等各种原因造成消息未能通知给B系统,就不能够确保数据的强一致性。
相应地,本领域需要一种新的数据消费方案来解决上述问题。
发明内容
为了克服上述缺陷,提出了本发明,以提供解决或至少部分地解决在基于消息队列进行数据处理时,如何确保数据的强一致性的问题。
在第一方面,本发明提供一种基于数据库的数据消费方法,所述方法包括:
生产者将消息数据写入数据库的消息队列表中,其中所述消息数据为所述生产者生产的业务数据对应的消息数据,所述消息数据和所述业务数据被写入同一数据库中,由同一事务进行管理;
消费者从所述数据库中的消息队列表中加载消息数据进行消费。
在上述基于数据库的数据消费方法的一个技术方案中,所述方法还包括:
在所述数据库中创建多个消息队列表和与其一一对应的失败队列表。
在上述基于数据库的数据消费方法的一个技术方案中,所述生产者将消息数据写入数据库的消息队列表中,包括:
调用依赖jar包;
生成第一配置文件,所述第一配置文件包括配置使用spring管理器进行事务管理;
根据所述第一配置文件将消息数据写入数据库的消息队列表中。
在上述基于数据库的数据消费方法的一个技术方案中,所述根据所述第一配置文件将消息数据写入数据库的消息队列表中,包括:
通过SQL语句根据所述第一配置文件将消息数据写入数据库的消息队列表中。
在上述基于数据库的数据消费方法的一个技术方案中,当所述消息数据需要通知给多个消费者时,通过所述SQL语句中的类型属性对所述多个消费者进行区分。
在上述基于数据库的数据消费方法的一个技术方案中,所述消费者从所述数据库中的消息队列表中加载消息数据进行消费,包括:
将所述消息数据加载在数据加载器中;
将加载的消息数据加入至工作线程池,从而由处理器进行处理并返回执行结果至所述工作线程池;
所述工作线程池根据所述执行结果更新所述数据库中的消息数据的状态。
在上述基于数据库的数据消费方法的一个技术方案中,所述将所述消息数据加载在数据加载器中,包括:
在消费者中设置多个数据加载器并且所述消息队列表为多个消息队列表的情况下,所述多个数据加载器中的每个数据加载器只加载所述多个消息队列表中的一个。
在上述基于数据库的数据消费方法的一个技术方案中,所述将所述消息数据加载在数据加载器中,包括:
调用依赖jar包或者调用依赖jar包和Elastic-Job;
生成第二配置文件,所述第二配置文件包括加载重试机制;
根据所述第二配置文件将消息数据加载在数据加载器中。
在上述基于数据库的数据消费方法的一个技术方案中,所述工作线程池根据所述执行结果更新所述数据库中的消息数据的状态,包括:
当所述执行结果为处理成功时,向所述消息队列表反馈处理成功的数据处理状态信息,以使所述消息队列表将所述消息数据删除;
当所述执行结果为处理失败时,向所述消息队列表反馈处理失败的数据处理状态信息,以使所述消息队列表修改所述消息数据的状态,并根据所述重试机制重试将消息数据加载在数据加载器中;
当重新尝试的重试次数大于预设的重试次数阈值时,则将所述消息数据存入所述失败队列表中作为备份。
在上述基于数据库的数据消费方法的一个技术方案中,所述根据所述重试机制重试将消息数据加载在数据加载器中,包括:
重试时间间隔随所述重试次数的增加而增长。
在上述基于数据库的数据消费方法的一个技术方案中,所述第二配置文件包括极速数据消费模式、正常数据消费模式和慢速数据消费模式;
所述将加载的消息数据加入至工作线程池,包括:
根据所选择的数据消费模式,将加载的消息数据加入至工作线程池。
在第二方面,提供一种控制装置,该控制装置包括处理器和存储装置,所述存储装置适于存储多条程序代码,所述程序代码适于由所述处理器加载并运行以执行上述基于数据库的数据消费方法的技术方案中任一项技术方案所述的基于数据库的数据消费方法。
在第三方面,提供一种计算机可读存储介质,该计算机可读存储介质其中存储有多条程序代码,所述程序代码适于由处理器加载并运行以执行上述基于数据库的数据消费方法的技术方案中任一项技术方案所述的基于数据库的数据消费方法。
本发明上述一个或多个技术方案,至少具有如下一种或多种有益效果:
在实施本发明的技术方案中,本发明中生产者将生产的业务数据对应的消息数据写入数据库的消息队列表中,且消息数据和业务数据被写入同一个数据库中,由同一事务进行管理,消费者从数据库中的消息队列表中加载消息数据进行消费。通过上述配置方式,本发明通过将业务数据和对应的消息数据写入同一数据库中,由同一事物进行管理,能够有效确保数据的强一致性,从而有效避免由于程序中断等各种原因造成的消息未能通知到消费者的情况,无需再额外设置补偿机制来解决上述问题。
附图说明
参照附图,本发明的公开内容将变得更易理解。本领域技术人员容易理解的是:这些附图仅仅用于说明的目的,而并非意在对本发明的保护范围组成限制。其中:
图1是根据本发明的一个实施例的基于数据库的数据消费方法的主要步骤流程示意图;
图2是根据本发明实施例的一个实施方式的基于数据库的数据消费方法主要架构示意图。
具体实施方式
下面参照附图来描述本发明的一些实施方式。本领域技术人员应当理解的是,这些实施方式仅仅用于解释本发明的技术原理,并非旨在限制本发明的保护范围。
在本发明的描述中,“模块”、“处理器”可以包括硬件、软件或者两者的组合。一个模块可以包括硬件电路,各种合适的感应器,通信端口,存储器,也可以包括软件部分,比如程序代码,也可以是软件和硬件的组合。处理器可以是中央处理器、微处理器、数字信号处理器或者其他任何合适的处理器。处理器具有数据和/或信号处理功能。处理器可以以软件方式实现、硬件方式实现或者二者结合方式实现。非暂时性的计算机可读存储介质包括任何合适的可存储程序代码的介质,比如磁碟、硬盘、光碟、闪存、只读存储器、随机存取存储器等等。术语“A和/或B”表示所有可能的A与B的组合,比如只是A、只是B或者A和B。术语“至少一个A或B”或者“A和B中的至少一个”含义与“A和/或B”类似,可以包括只是A、只是B或者A和B。单数形式的术语“一个”、“这个”也可以包含复数形式。
参阅附图1,图1是根据本发明的一个实施例的基于数据库的数据消费方法的主要步骤流程示意图。如图1所示,本发明实施例中的基于数据库的数据消费方法主要包括下列步骤S101-步骤S102。
步骤S101:生产者将消息数据写入数据库的消息队列表中,其中消息数据为生产者生产的业务数据对应的消息数据,消息数据和业务数据被写入同一数据库中,由同一事务进行管理。
在本实施例中,生产者可以将业务数据以及业务数据对应的消息数据写入同一数据库中,由同一事务进行管理。消息数据可以写入数据库的消息队列表中。
一个实施方式中,业务数据可以写入数据库中的业务数据表中。
一个实施方式中,数据库可以为MySQL数据库。
步骤S102:消费者从数据库中的消息队列表中加载消息数据进行消费。
在本实施例中,消费者可以从数据库中的消息队列表中加载消息数据,进行消费。
基于上述步骤S101-步骤S102,本发明实施例中生产者将生产的业务数据对应的消息数据写入数据库的消息队列表中,且消息数据和业务数据被写入同一个数据库中,由同一事务进行管理,消费者从数据库中的消息队列表中加载消息数据进行消费。通过上述配置方式,本发明实施例通过将业务数据和对应的消息数据写入同一数据库中,由同一事物进行管理,能够有效确保数据的强一致性,从而有效避免由于程序中断等各种原因造成的消息未能通知到消费者的情况,无需再额外设置补偿机制来解决上述问题。
在本发明实施例的一个实施方式中,本发明除了可以包括上述步骤S101和步骤S102外,还可以包括以下步骤S103:
步骤S103:在数据库中创建多个消息队列表和与其一一对应的失败队列表。
在本实施方式中,为保证数据的读写性能,还可以在数据库中创建多个消息队列表以及与消息队列表一一对应的失败队列表。其中,消息队列表和与之对应的失败队列表具有相同的表名前缀。如果表名有冲突,消息队列表名前缀及失败队列表名前缀都可以进行修改。
一个实施方式中,在业务量较大的情况下,除了通过分表的形式实现水平扩展外,还可以通过分库的形式再进行水平扩展,即,将数据存入多个数据库中。且由于生产者和消费者的分库分表规则是解耦的,生产者和消费者互相独立,不需要保持一致。
一个例子,以MySQL数据库为例,可以创建3个消息队列表:queue_0、queue_1、queue_2,表名前缀是:queue_;与之对应的建了3张失败队列表:bad_queue_0、bad_queue_1、bad_queue_2,表名前缀是:bad_queue_,数据(data)类型可以根据实际情况调整。
下面对步骤S101和步骤S102作进一步地说明。
在本发明实施例的一个实施方式中,步骤S101可以进一步包括以下步骤S1011至步骤S1013:
步骤S1011:调用依赖jar包。
在本实施方式中,在生产者将消息数据写入数据库的消息队列表时,可以先调用依赖jar包。其中,依赖jar包为基于数据库的消息队列功能的jar包。
一个示例,可以根据以下程序语句来调用依赖jar包:
compile("com.suixingpay.starter:suixingpay-starter-db-queue:xxx")
步骤S1012:生成第一配置文件,第一配置文件包括配置使用spring管理器进行事务管理。
在本实施方式中,使用spring管理器进行事务管理,能够进一步确保数据的强一致性。
步骤S1013:根据第一配置文件将消息数据写入数据库的消息队列表中。
在本实施方式中,步骤S1013可以进一步被配置为:
通过SQL语句根据第一配置文件将消息数据写入数据库的消息队列表中。
一个示例,可以根据以下SQL语句来将消息数据写入消息队列表中:
insert into queue_x(type,data,last_time,create_time)values('test','string data',now(),now())
一个实施方式中,当消息数据需要通知给多个消费者时,通过SQL语句中的类型属性(type)对多个消费者进行区分。
在本实施方式中,如果同一消息数据需要通知给多个消费者,则可以在消息队列表中插入多条记录,通过上述示例中的type(类型属性)来区分消费者,这样就能够并行提升消费能力,也能够避免由于个别消费者故障而影响其他消费者,同时也能够针对个别消费者设置重试推送机制。
一个示例,可以根据以下程序语句实现生产者将消息数据写入数据库的消息队列表中:
配置说明
suixingpay:
dbqueue:
#数据源的bean name,如果不设置此值的话,会使用默认的数据源;
#注意:在多数据源情况下,可能需要注意设置bean name的顺序。
#如果是生产者的话需要根据ProducerDatasourceSelector的实现算法,按顺序设置数据源的bean name(请参考默认的实现DefaultProducerDatasourceSelector)
#dataSources:dataSource1,dataSource2
queueTableCount:3#消息队列表个数,默认值为3
queueTableName:queue_#队列表名前缀,默认值queue_
badQueueTableName:bad_queue_#失败队列表名前缀,默认值bad_queue_
producer:
enabled:true#是否开启生产者,默认true
database-type:my_sql#数据库类型,默认mysql
#sequence-name:seq#用于自动成功id的sequence,当database-type为oracle且auto-gen-id true时,必须要设置
useSpringManagedTransaction:true#是否必须使用Spring事务管理器,以保证数据的强一致性,默认值true
ProducerQueueDAO:
public interface ProducerQueueDAO{
/**
*保存队列
*
*@param selectDatasourceKey在多数据源的情况下,用于选择数据源,如果已经知道使用的DataSource,那么也可以直接传入DataSource的实例
*@param selectTableKey
*@param queues
*/
void save(Object selectDatasourceKey,Object selectTableKey,Queue...queues)throws Exception;
}
默认的分库分表规则:
public class DefaultProducerDatasourceSelector implementsProducerDatasourceSelector{
private static final int MAX=Integer.MAX_VALUE-100000;
private final LongAdder dataSourceAdder;
private final LongAdder tableAdder;
private final DataSource[]dataSources;
private final DbQueueProperties properties;
public DefaultProducerDatasourceSelector(DataSource[]dataSources,DbQueueProperties properties){
this.dataSources=dataSources;
this.properties=properties;
if(dataSources.length>1){
dataSourceAdder=new LongAdder();
}else{
dataSourceAdder=null;
}
tableAdder=new LongAdder();
}
protected int objectToCode(Object object){
int code;
if(object instanceof Integer){
code=((Integer)object).intValue();
}else if(object instanceofLong){
code=((Long)object).intValue();
}else{
String tmp=String.valueOf(object);
code=tmp.hashCode();
}
return Math.abs(code);
}
private DataSource getDataSourceByCode(int code){
int datasourceIndex=code%dataSources.length;
return dataSources[datasourceIndex];
}
private int getDataSourceCode(){
if(dataSourceAdder.intValue()>=MAX){
synchronized(this){
if(dataSourceAdder.intValue()>=MAX){
dataSourceAdder.reset();
}
}
}
dataSourceAdder.increment();
return dataSourceAdder.intValue();
}
private int getTableCode(){
if(tableAdder.intValue()>=MAX){
synchronized(this){
if(tableAdder.intValue()>=MAX){
tableAdder.reset();
}
}
}
tableAdder.increment();
return tableAdder.intValue();
}
@Override
public DataSource selectDataSource(Object selectDatasourceKey){
if(null==selectDatasourceKey){
if(dataSources.length==1){
return dataSources[0];
}
return getDataSourceByCode(getDataSourceCode());
}
if(selectDatasourceKey instanceof DataSource){
return(DataSource)selectDatasourceKey;
}
return getDataSourceByCode(objectToCode(selectDatasourceKey));
}
@Override
public String selectTableName(String queueTableName,ObjectselectTableKey){
int code;
if(null==selectTableKey){
code=getTableCode();
}else{
code=objectToCode(selectTableKey);
}
int dataSourceCount=dataSources.length;
int tableCount=properties.getQueueTableCount();
int step=tableCount/dataSourceCount;
int tableInd=code%step;
return queueTableName+tableInd;
}
}
也可以通过实现ProducerDatasourceSelector接口进行定制。
示例:
@Service
public class SaveQueueService{
@Autowired
private ProducerQueueDAO producerQueueDAO;
@Transactional(rollbackFor=Throwable.class)
public String test()throws Exception{
String orderId=String.valueOf(System.currentTimeMillis());
String[]types={"a","b","c"};
Queue[]queues=new Queue[types.length];
for(int i=0;i<types.length;i++){
queues[i]=new Queue(types[i],"test"+i);
}
producerQueueDAO.save(null,orderId,queues);
Stringjson="...";
producerQueueDAO.save(null,null,new Queue(json));
return"OK";
}
}
其中,ProducerQueueDAO可以获取当前上下文中的Spring事务中的Connection(关联性),所以能保证数据的强一致性,但如果不在Spring事务上下文中被调用,那就会新开启事务,并不能保证数据的强一致性,如果只是想用此框架的定时重试机制,不需要保证强一致性,可以将suixingpay.dbqueue.producer.useSpringManagedTransaction设置为false。
在本发明实施例的一个实施方式中,步骤S102可以进一步包括以下步骤S1021至步骤S1023:
步骤S1021:将消息数据加载在数据加载器中。
在本实施方式中,可以先将消息数据加载在数据加载器中,这样工作线程池就不需要直接从数据库中读取消息数据,能够减少读取的资源负担。
一个实施方式中,数据记载器可以为java虚拟机内存。
一个实施方式中,步骤S1021可以进一步被配置为执行以下步骤:
在消费者中设置多个数据加载器并且消息队列表为多个消息队列表的情况下,多个数据加载器中的每个数据加载器只加载多个消息队列表中的一个。
在本实施方式中,如果消费者中设置了多个数据加载器且消息队列表中有多个消息队列表时,每个数据加载器只加载多个消息队列表的其中一个。这样能够避免同一时刻消费同一条消费数据的问题。
一个实施方式中,步骤S1021可以进一步包括以下步骤S10211至步骤S10213:
步骤S10211:调用依赖jar包或者调用依赖jar包和Elastic-Job。
在本实施方式中,可以先调用依赖jar包;如果需要分布式部署,在调用依赖jar包的基础上还需要引入Elastic-Job。其中,Elastic-Job为基于quartz二次开发的弹性分布式任务调度系统,功能丰富强大,采用zookeeper实现分布式协调,实现任务高可用以及分片。
一个调用依赖jar包的程序示例为:
compile("com.suixingpay.starter:suixingpay-starter-db-queue:xxx")
一个调用Elastic-Job的程序示例为:
compile("com.suixingpay.starter:suixingpay-starter-elastic-job:xxx")
步骤S10212:生成第二配置文件,第二配置文件包括加载重试机制。
在本实施方式中,可以生成第二配置文件,其中第二配置文件中设置了数据加载器加载消息数据的加载重试机制。
一个实施方式中,加载重试机制的重试时间随重试次数的增加而增加。
步骤S10213:根据第二配置文件将消息数据加载在数据加载器中。
在本实施方式中,可以根据第二配置文件将消息数据加载到数据加载器中。
一个实施方式中,第二配置文件包括极速数据消费模式(FASTEST)、正常数据消费模式(NORMAL)和慢速数据消费模式(SLOW)。其中,极速数据消费模式是指数据加载器一直加载数据,并提交给工作线程池来处理,直到工作线程队列满或没有数据会等1秒后再尝试;正常数据消费模式是指数据加载器加载一批数据,然后提交给工作线程池来处理,直到这批所有数据处理完才会加载下一批数据,如果工作线程队列满或没有数据会等1秒后再尝试;慢速数据消费模式是指数据加载器加载一批数据后,并由数据加载器所在的线程一条条消息进行消费。
一个第二配置文件的程序示例为:
suixingpay:
dbqueue:
#数据源的bean name,如果不设置此值的话,会使用默认的数据源;
#注意:在多数据源情况下,可能需要注意设置bean name的顺序。
#消息者默认DefaultConsumerDatasourceSelector可以不需要关心数据源的配置顺序
#dataSources:dataSource1,dataSource2
queueTableCount:3#消息队列表个数,默认值为3
queueTableName:queue_#队列表名前缀,默认值queue_
badQueueTableName:bad_queue_#失败队列表名前缀,默认值bad_queue_
consumer:
enabled:true
retryTimesLimit:3#重试次数限制,达到重试次数后,会将数据移到失败队列中,默认值5
#延迟重试时间(单位秒),延迟重试时间间隔计算公式:retryDelayTime*retryTimes。默认值60
#如果retryDelayTime=60,那么第1次失败后的60*1=60秒进行重试;第2次失败后的60*2=120秒进行重试;第3次失败后的60*3=180秒进行重试;
#如果retryTimesLimit=3那么60+120+180=360秒,那么6分钟没有完成,则会将消息移到失败队列。
#此重试时间一定要大于业务的超时间,否则可能会出现在同一时刻处理同一条消息的情况
retryDelayTime:30
loadDataLimit:200#每次加载数据的条数,默认值200
consumerModeType:FASTEST#消费模式:极速模式(FASTEST)、正常模式(NORMAL)、慢速模式(SLOW),默认值FASTEST
deployment-mode-type:standalone#部署模式:standalone(默认值)单机模式;distributed分布式模式(基于suixingpay-starter-elastic-job),注意:这个key和value都必须小写
#工作线程池配置,当consumerModeType值为SLOW时不会生效
worker-thread-pool:
coreSize:20#最小线程数,默认值20
maxSize:200#最大线程数,默认值200
keepAlive:120#最大空闲时间,单位秒,默认值120
queueCapacity:5000#队列最大容量,默认值5000
job:#当deployment-mode-type值为distributed时才生效
name:db-queue-job#作业名称,默认值${spring.application.name}+-db-queue-job
failover:false#是否开启任务执行失效转移,开启表示如果作业在一次任务执行中途宕机,允许将该次未完成的任务在另一作业节点上补偿执行
misfire:false#是否开启错过任务重新执行
#description:作业描述信息
overwrite:false
monitorExecution:true#监控作业运行时状态
monitorPort:-1#作业监控端口
maxTimeDiffSeconds:-1#允许的本机与注册中心的时间最大误差秒数
reconcileIntervalMinutes:10#修复作业服务器不一致状态服务调度间隔时间,配置为小于1的任意值表示不执行修复,单位:分钟
disabled:false#作业是否禁止启动,可用于部署作业时,先禁止启动,部署结束后统一启动
#startedTimeoutMilliseconds:Long.MAX_VALUE#最后一个作业执行前的执行方法的超时时间,单位:毫秒
#completedTimeoutMilliseconds:Long.MAX_VALUE#最后一个作业执行后的执行方法的超时时间,单位:毫秒
其中,在生产环境需要考虑高可用性和高性能时,需要使用分布式部署,那么就需要将deployment-mode-type设置为distributed,并且需要引用suixingpay-starter-elastic-job。
步骤S1022:将加载的消息数据加入至工作线程池,从而由处理器进行处理并返回执行结果至工作线程池。
在本实施方式中,可以将加载的消息数据加入至工作线程池,有处理器对消息数据进行处理,并把执行结果返回至工作线程池。
一个实施方式中,可以根据第二配置文件中设置的数据消费模式,将加载的消息数据计入至工作线程池。
步骤S1023:工作线程池根据执行结果更新数据库中的消息数据的状态。
在本实施方式中,步骤S1023可以进一步包括以下步骤S10231至步骤S10233:
步骤S10231:当执行结果为处理成功时,向消息队列表反馈处理成功的数据处理状态信息,以使消息队列表将业务数据对应的消息数据删除。
步骤S10232:当执行结果为处理失败时,向消息队列表反馈处理失败的数据处理状态信息,以使消息队列表修改消息数据的状态,并根据重试机制重试将消息数据加载在数据加载器中。
步骤S10233:当重新尝试的重试次数大于预设的重试次数阈值时,则将消息数据存入失败队列表中作为备份。
在本实施方式中,工作线程池可以根据执行结果以及加载重试机制来更新数据库中消息数据的状态。当执行结果为处理成功时,消息队列表将对应的消息数据删除;当执行结果为处理失败时,向消息队列表反馈信息,以使消息队列表修改对应的消息数据的状态,并根据加载重试机制重新将消息数据加载到数据加载器中;当重试次数大于重试次数阈值时,则将对应的消息数据存储失败队列表中作为备份。
一个实施方式中,可以根据所选择的数据消费模式,将加载的消息数据加入至工作线程池。
一个实施方式中,消费者端可以单独设置分库分表规则,每个数据库平均分配消息队列表,消费者端的分库分表规则与生产者端彻底解耦,消费者端不需要关心生产者端的分库分表规则。
一个示例,比如有9张消息队列表,3个数据库,那么每个库有3张表,表名都是:queue_0、queue_1、queue_2、bad_queue_0、bad_queue_1、bad_queue_2;DefaultConsumerDatasourceSelector的代码实现如下所示,其中ConsumerDatasourceSelector为数据源选择器:
public class DefaultConsumerDatasourceSelector implementsConsumerDatasourceSelector{
private final DataSource[]dataSources;
private final DbQueueProperties properties;
public DefaultConsumerDatasourceSelector(DataSource[]dataSources,DbQueueProperties properties){
if(null==dataSources||dataSources.length==0){
throw new IllegalArgumentException("dataSources不能为空!");
}
this.dataSources=dataSources;
this.properties=properties;
}
/**
*每个数据源中表的个数是一样多的<br/>
*比如3个数据源,总共9张表,每个数据源3张表,那么第0,1,2号表在第0个数据源中;第3,4,5号表在第1个数据源中;第6,7,8号表在第2个数据源中;<br/>
*
*@param tableIndex
*@return DataSource
*/
@Override
public DataSource select(int tableIndex){
int dataSourceCount=dataSources.length;
int tableCount=properties.getQueueTableCount();
int step=tableCount/dataSourceCount;
int datasourceIndex=tableIndex/step;
return dataSources[datasourceIndex];
}
/**
*每个数据源中表的个数是一样多的,且名称也一样<br/>
*比如3个数据源,总共9张表,每个数据源3张表,那么每个数据源的表名都是:xxx0,xxx1,xxx2(xxx就是queueTableName的值);<br/>
*
*@param queueTableName表名前缀
*@param tableIndex
*@return String
*/
@Override
public String getTableName(String queueTableName,int tableIndex){
int dataSourceCount=dataSources.length;
int tableCount=properties.getQueueTableCount();
int step=tableCount/dataSourceCount;
int tableInd=tableIndex%step;
return queueTableName+tableInd;
}
}
一个实施方式中,也可以实现ConsumerDatasourceSelector接口的定制。
一个实施方式中,可以参阅附图2,图2是根据本发明实施例的一个实施方式的基于数据库的数据消费方法主要架构示意图。如图2所示,生产者将消息数据写入数据库中消息队列表中,为了确保数据的一致性,消息数据与其对应的业务数据由同一事务管理;通过数据加载器将数据库中的消息队列表中的消息数据加载至数据加载器中,将数据加载器加载的消息数据加入到工作线程池中,业务处理器从工作线程池中获取消息数据并进行业务处理,并将业务处理的执行结果返回至工作线程池;工作线程池根据执行结果删除消息队列表中的消息数据或更改消息数据的状态。其中,一个数据加载器只加载一张消息队列表中的数据,这样能够避免同一时刻消费同一条消费数据的问题。同时也能够通过分库分表来实现水平扩容,提升消息数据的读写效率。消费者可以通过远程接口来完成业务功能。
需要指出的是,尽管上述实施例中将各个步骤按照特定的先后顺序进行了描述,但是本领域技术人员可以理解,为了实现本发明的效果,不同的步骤之间并非必须按照这样的顺序执行,其可以同时(并行)执行或以其他顺序执行,这些变化都在本发明的保护范围之内。
本领域技术人员能够理解的是,本发明实现上述一实施例的方法中的全部或部分流程,也可以通过计算机程序来指令相关的硬件来完成,所述的计算机程序可存储于一计算机可读存储介质中,该计算机程序在被处理器执行时,可实现上述各个方法实施例的步骤。其中,所述计算机程序包括计算机程序代码,所述计算机程序代码可以为源代码形式、对象代码形式、可执行文件或某些中间形式等。所述计算机可读存储介质可以包括:能够携带所述计算机程序代码的任何实体或装置、介质、U盘、移动硬盘、磁碟、光盘、计算机存储器、只读存储器、随机存取存储器、电载波信号、电信信号以及软件分发介质等。需要说明的是,所述计算机可读存储介质包含的内容可以根据司法管辖区内立法和专利实践的要求进行适当的增减,例如在某些司法管辖区,根据立法和专利实践,计算机可读存储介质不包括电载波信号和电信信号。
进一步,本发明还提供了一种控制装置。在根据本发明的一个控制装置实施例中,控制装置包括处理器和存储装置,存储装置可以被配置成存储执行上述方法实施例的基于数据库的数据消费方法的程序,处理器可以被配置成用于执行存储装置中的程序,该程序包括但不限于执行上述方法实施例的基于数据库的数据消费方法的程序。为了便于说明,仅示出了与本发明实施例相关的部分,具体技术细节未揭示的,请参照本发明实施例方法部分。该控制装置可以是包括各种电子设备形成的控制装置设备。
进一步,本发明还提供了一种计算机可读存储介质。在根据本发明的一个计算机可读存储介质实施例中,计算机可读存储介质可以被配置成存储执行上述方法实施例的基于数据库的数据消费方法的程序,该程序可以由处理器加载并运行以实现上述基于数据库的数据消费方法。为了便于说明,仅示出了与本发明实施例相关的部分,具体技术细节未揭示的,请参照本发明实施例方法部分。该计算机可读存储介质可以是包括各种电子设备形成的存储装置设备,可选的,本发明实施例中计算机可读存储介质是非暂时性的计算机可读存储介质。
进一步,应该理解的是,由于各个模块的设定仅仅是为了说明本发明的装置的功能单元,这些模块对应的物理器件可以是处理器本身,或者处理器中软件的一部分,硬件的一部分,或者软件和硬件结合的一部分。因此,图中的各个模块的数量仅仅是示意性的。
本领域技术人员能够理解的是,可以对装置中的各个模块进行适应性地拆分或合并。对具体模块的这种拆分或合并并不会导致技术方案偏离本发明的原理,因此,拆分或合并之后的技术方案都将落入本发明的保护范围内。
至此,已经结合附图所示的优选实施方式描述了本发明的技术方案,但是,本领域技术人员容易理解的是,本发明的保护范围显然不局限于这些具体实施方式。在不偏离本发明的原理的前提下,本领域技术人员可以对相关技术特征作出等同的更改或替换,这些更改或替换之后的技术方案都将落入本发明的保护范围之内。
Claims (13)
1.一种基于数据库的数据消费方法,其特征在于,所述方法包括:
生产者将消息数据写入数据库的消息队列表中,其中所述消息数据为所述生产者生产的业务数据对应的消息数据,所述消息数据和所述业务数据被写入同一数据库中,由同一事务进行管理;
消费者从所述数据库中的消息队列表中加载消息数据进行消费。
2.根据权利要求1所述的方法,其特征在于,所述方法还包括:
在所述数据库中创建多个消息队列表和与其一一对应的失败队列表。
3.根据权利要求2所述的方法,其特征在于,所述生产者将消息数据写入数据库的消息队列表中,包括:
调用依赖jar包;
生成第一配置文件,所述第一配置文件包括配置使用spring管理器进行事务管理;
根据所述第一配置文件将消息数据写入数据库的消息队列表中。
4.根据权利要求3所述的方法,其特征在于,所述根据所述第一配置文件将消息数据写入数据库的消息队列表中,包括:
通过SQL语句根据所述第一配置文件将消息数据写入数据库的消息队列表中。
5.根据权利要求4所述的方法,其特征在于,当所述消息数据需要通知给多个消费者时,通过所述SQL语句中的类型属性对所述多个消费者进行区分。
6.根据权利要求2-5中任一项所述的方法,其特征在于,所述消费者从所述数据库中的消息队列表中加载消息数据进行消费,包括:
将所述消息数据加载在数据加载器中;
将加载的消息数据加入至工作线程池,从而由处理器进行处理并返回执行结果至所述工作线程池;
所述工作线程池根据所述执行结果更新所述数据库中的消息数据的状态。
7.根据权利要求6所述的方法,其特征在于,所述将所述消息数据加载在数据加载器中,包括:
在消费者中设置多个数据加载器并且所述消息队列表为多个消息队列表的情况下,所述多个数据加载器中的每个数据加载器只加载所述多个消息队列表中的一个。
8.根据权利要求6所述的方法,其特征在于,所述将所述消息数据加载在数据加载器中,包括:
调用依赖jar包或者调用依赖jar包和Elastic-Job;
生成第二配置文件,所述第二配置文件包括加载重试机制;
根据所述第二配置文件将消息数据加载在数据加载器中。
9.根据权利要求8所述的方法,其特征在于,所述工作线程池根据所述执行结果更新所述数据库中的消息数据的状态,包括:
当所述执行结果为处理成功时,向所述消息队列表反馈处理成功的数据处理状态信息,以使所述消息队列表将所述消息数据删除;
当所述执行结果为处理失败时,向所述消息队列表反馈处理失败的数据处理状态信息,以使所述消息队列表修改所述消息数据的状态,并根据所述重试机制重试将消息数据加载在数据加载器中;
当重新尝试的重试次数大于预设的重试次数阈值时,则将所述消息数据存入所述失败队列表中作为备份。
10.根据权利要求9所述的方法,其特征在于,所述根据所述重试机制重试将消息数据加载在数据加载器中,包括:
重试时间间隔随所述重试次数的增加而增长。
11.根据权利要求8所述的方法,其特征在于,
所述第二配置文件包括极速数据消费模式、正常数据消费模式和慢速数据消费模式;
所述将加载的消息数据加入至工作线程池,包括:
根据所选择的数据消费模式,将加载的消息数据加入至工作线程池。
12.一种控制装置,包括处理器和存储装置,所述存储装置适于存储多条程序代码,其特征在于,所述程序代码适于由所述处理器加载并运行以执行权利要求1至11中任一项所述的方法。
13.一种计算机可读存储介质,其中存储有多条程序代码,其特征在于,所述程序代码适于由处理器加载并运行以执行权利要求1至11中任一项所述的方法。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202211117619.1A CN115563226A (zh) | 2022-09-14 | 2022-09-14 | 基于数据库的数据消费方法、控制装置及可读存储介质 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202211117619.1A CN115563226A (zh) | 2022-09-14 | 2022-09-14 | 基于数据库的数据消费方法、控制装置及可读存储介质 |
Publications (1)
Publication Number | Publication Date |
---|---|
CN115563226A true CN115563226A (zh) | 2023-01-03 |
Family
ID=84741844
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202211117619.1A Pending CN115563226A (zh) | 2022-09-14 | 2022-09-14 | 基于数据库的数据消费方法、控制装置及可读存储介质 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN115563226A (zh) |
Cited By (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN116108110A (zh) * | 2023-04-17 | 2023-05-12 | 南方电网数字电网研究院有限公司 | 一种Kafka消息消费补偿方法、系统和介质 |
-
2022
- 2022-09-14 CN CN202211117619.1A patent/CN115563226A/zh active Pending
Cited By (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN116108110A (zh) * | 2023-04-17 | 2023-05-12 | 南方电网数字电网研究院有限公司 | 一种Kafka消息消费补偿方法、系统和介质 |
CN116108110B (zh) * | 2023-04-17 | 2023-08-15 | 南方电网数字电网研究院有限公司 | 一种Kafka消息消费补偿方法、系统和介质 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN110569305B (zh) | 区块同步方法、装置、介质和计算设备 | |
US7502843B2 (en) | Server queuing system and method | |
US7698602B2 (en) | Systems, methods and computer products for trace capability per work unit | |
US10691712B2 (en) | System and method for merging a mainframe data file to a database table for use by a mainframe rehosting platform | |
CN110968603B (zh) | 一种数据访问方法及装置 | |
US8843581B2 (en) | Live object pattern for use with a distributed cache | |
CN109614167B (zh) | 一种管理插件的方法和系统 | |
US20090063807A1 (en) | Data redistribution in shared nothing architecture | |
US9852220B1 (en) | Distributed workflow management system | |
US10452387B2 (en) | System and method for partition-scoped patching in an application server environment | |
CN107016016B (zh) | 一种数据处理的方法及装置 | |
CN110413428B (zh) | 对账数据的处理方法、电子设备及存储介质 | |
CN104065636A (zh) | 数据处理方法和系统 | |
US20170206119A1 (en) | System and method for achieving specific behaviors by intercepting file access calls in a mainframe rehosting platform | |
CN113672350B (zh) | 一种应用处理方法、装置及相关设备 | |
CN111258742A (zh) | 一种数据同步的方法、系统、计算设备及存储介质 | |
US9207966B2 (en) | Method and system for providing a high-availability application | |
CN115563226A (zh) | 基于数据库的数据消费方法、控制装置及可读存储介质 | |
EP3146430A1 (en) | System and method for supporting a distributed data structure in a distributed data grid | |
CN103309696B (zh) | 一种Java卡扩展库更新方法、装置和Java卡 | |
CN102597995B (zh) | 同步数据库和非数据库资源 | |
CN111414356A (zh) | 数据存储方法、装置、非关系数据库系统及存储介质 | |
CN113835625B (zh) | 一种基于子路径的数据存储方法、装置、设备及存储介质 | |
CN106055322A (zh) | 一种流程调度方法及装置 | |
CN111930475B (zh) | 启动ett运行的方法及装置 |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination |