同步复制
使用时间感知型两阶段提交协议的同步复制是默认模式。因此,对于 C/C++ 主应用程序来说,只需调用:
mco_HA_master_params_t MasterParams;
mco_HA_master_params_init( &MasterParams );
mco_HA_set_master_params( db, &MasterParams );
在 C# 和 Java 应用程序中:
MasterConnection.Parameters MParams = new MasterConnection.Parameters();
con.SetReplicationMode( MParams );
SmartEDB 高可用性运行时在 C/C++ 主应用程序中于 mco_HA_attach_replica() 调用期间执行初始同步,而所有其他复制操作均在调用 mco_trans_commit() 期间进行;在 C# 和 Java 应用程序中则分别在 MasterConnection.AttachReplica() 和 MasterConnection.CommitTransaction() 方法期间进行。
在副本端,SmartEDB 高可用性运行时在 mco_HA_attach_master() 中管理 C/C++ 应用程序的初始复制。当调用 mco_HA_attach_master() 时,控制权将传递给 SmartEDB 高可用性运行时,它会管理副本数据库的初始同步,然后等待并处理主节点在调用 mco_trans_commit() 期间发送的事务数据。在 C# 和 Java 副本应用程序中,初始同步和后续事务复制由 SmartEDB 高可用性运行时在 ReplicaConnection.AttachMaster() 方法期间管理。

实施
大多数使用 SmartEDB 高可用性的 C/C++ 应用程序将仅使用协议层 API 中的以下函数:
MCO_RET mco_HA_start();
void mco_HA_master_params_init();
MCO_RET mco_HA_set_master_params();
MCO_RET mco_HA_attach_replica();
void mco_HA_replica_params_init();
MCO_RET mco_HA_attach_master();
MCO_RET mco_HA_stop();
同样,大多数使用eXtremeDB高可用性的c#和Java应用程序将只使用以下API方法:
Database db = new Database();
db.Open();
MasterConnection con = new MasterConnection(db);
con.SetReplicationMode();
con.AttachReplica();
con.StopReplication();
ReplicaConnection con = new ReplicaConnection(db);
con.AttachMaster();
con.Disconnect();
db.Close();
在主节点侧使用 HA 接口 API:
要在主节点启动复制,应用程序必须执行以下步骤:
初始化高可用性运行时:
- 在 C/C++ 应用程序中调用 mco_HA_start()。
- 在 C# 和 Java 应用程序中实例化一个启用高可用性支持的 Database 对象,例如:
```csharp
Database db = new Database(new ExtremedbWrapper(), Database.Mode.HighAvailabilitySupport);
```初始化主参数结构:
- 在 C/C++ 应用程序中调用 mco_HA_master_params_init() 来初始化 mco_HA_master_params_t 结构(include/ha/mcoha.h)。
- 在 C# 和 Java 应用程序中实例化 MasterConnection.Parameters 对象。定义主模式和标志:
- 在 C/C++ 应用程序中填充 mco_HA_master_params_t 结构,并确保设置 MCO_MASTER_MODE 标志值。
- 在 C# 和 Java 应用程序中设置 MasterConnection.Parameters 对象的属性。设置主复制模式标志:
- 在 C/C++ 应用程序中调用 mco_HA_set_master_params()。
- 在 C# 和 Java 应用程序中调用 MasterConnection.SetReplicationMode() 方法。创建监听任务。
在监听线程中连接副本:
- 在 C/C++ 应用程序中调用 mco_HA_attach_replica()。
- 在 C# 和 Java 应用程序中调用 MasterConnection.AttachReplica() 方法。
要启动异步复制,还需执行额外的步骤(稍后讨论)。
以下代码片段展示了一个简单的 C/C++ 主节点实现。
void* ListenToReplicas ( void *p )
{
while ((! stop_flag ) {
ret = mco_HA_attach_replica(...);
if ( MCO_S_OK != ret )
// something went wrong, examine the return code
...
else
// replica is connected successfully
}
}
int main(int argc, char* argv[])
{
mco_HA_master_params_t MasterParams;
…
/* initialize HA subsystem */
mco_HA_start();
/* create the database */
rc = mco_db_open_dev( dbName, dbname_get_dictionary(),°
dev, n_dev, &db_params);
…
/* connect to the database, obtain a database handle */
rc = mco_db_connect( dbName, &db );
…
/* set MASTER mode */
mco_HA_master_params_init( &MasterParams );
mco_HA_set_master_params( db, &MasterParams );
/* create a ‘listener’ thread */
rc = pthread_create (&ConnThread, NULL,
(void*)ListenToReplicas, &ha);
/* Continue with the regular database processing */
while (master_has_some_work_to_do) {
rc = mco_trans_start( db, MCO_READ_WRITE,
MCO_TRANS_FOREGROUND, &t );
...
rc = mco_trans_commit(t);
}
/* Detach and close connections to replicas */
mco_HA_stop(db);
}
请注意,mco_HA_attach_replica() 是在一个单独的“监听器”任务的上下文中被调用的。在接收到连接请求后,此函数执行以下操作以“激活”副本:
- 等待副本连接
- 接受连接,创建通道
- 向副本传输初始同步数据
- 在高可用性运行时中注册副本
mco_HA_attach_replica() 函数在 API 参考部分有详细描述,但简而言之,其原型为:
mco_HA_attach_replica( mco_db_h db, char* masterport,
timer_unit timeout);
超时参数表示“接受连接”的超时时间。
如果主数据库是共享内存数据库且有多个进程访问它,那么只有其中一个进程(称为主主进程)处理与副本的连接。因此,只有主主进程可以调用诸如 mco_HA_keep_alive()、mco_HA_attach_replica() 等网络相关函数。
一个类似的简单的 C# 主实现看起来会像下面这样:
public void Listen() {
MasterConnection con = new MasterConnection(db);
while (listening) {
if (con.AttachReplica(PORT, ATTACH_TIMEOUT)) {
// Replica connected…
}
}
con.Disconnect();
}
Master()
{
Database.Parameters parameters = new Database.Parameters();
db = new Database(new ExtremedbWrapper(),
Database.Mode.HighAvailabilitySupport);
db.Open( dbName, parameters, DATABASE_SIZE);
MasterConnection con = new MasterConnection(db);
// set HA mode
MasterConnection.Parameters MParams = newMasterConnection.Parameters(
MasterConnection.MCO_HAMODE_HOTSYNCH );
con.SetReplicationMode( MParams );
MParams.listening = true;
// start listen thread
Thread listenThread = new Thread(new ThreadStart(Listen));
listenThread.Start();
// continue with the regular database processing
while (master_has_some_work_to_do) {
con.StartTransaction(Database.Transaction.ReadWrite);
...
con.CommitTransaction();
}
// stop thread
listening = false;
listenThread.Join();
con.Disconnect();
db.Close();
}
在副本端使用 HA 接口 API:
要在副本端启动复制,应用程序必须执行以下步骤:
初始化高可用性运行时:
- 在 C/C++ 应用程序中调用 mco_HA_start()。
- 在 C# 和 Java 应用程序中实例化一个启用高可用支持的 Database 对象,例如:
```csharp
Database db = new Database(new ExtremedbWrapper(), Database.Mode.HighAvailabilitySupport);
```创建并连接到数据库。
初始化副本模式标志:
- 在 C/C++ 应用程序中调用 mco_HA_replica_params_init()。
- 在 C# 和 Java 应用程序中设置 ReplicaConnection.Parameters 对象的属性。开始复制:
- 在 C/C++ 应用程序中调用 mco_HA_attach_master()。
- 在 C# 和 Java 应用程序中调用 ReplicaConnection.AttachMaster() 方法。
以下代码片段展示了一个简单的 C/C++ 副本实现。
int main(int argc, char* argv[])
{
int stopReason = 0;
mco_HA_replica_params_t ReplicaParams;
...
/* initialize HA subsystem */
mco_HA_start();
/* create the database */
rc = mco_db_open_dev( dbName, dbname_get_dictionary(),°
dev, n_dev, &db_params);
…
/* connect to the database, obtain a database handle */
rc = mco_db_connect( dbName, &db );
…
/* set replica params */
mco_HA_replica_params_init( &ReplicaParams );
rc = mco_HA_attach_master( &db, mastername,
&ReplicaParams,
&stopReason,
TM_CONNECTION_TIMEOUT);
return stopReason;
}
请注意,mco_HA_attach_master() 是一个阻塞调用。在此时,基本上所有的控制权都交给了 SmartEDB 高可用性运行时,由其管理初始同步,然后提交主节点发送的事务。该函数在 API 参考部分有详细描述,但简而言之,其原型为:
MCO_RET mco_HA_attach_master( mco_db_h db,
const char* conn_string,
const mco_HA_replica_params_t* params,
MCO_E_HA_REPLICA_STOP_REASON* stop_reason,
timer_unit timeout);
stop_reason 表示运行时将控制权交还给应用程序的原因(include/ha/mcoha.h)。当控制权交还给副本应用程序时,它应检查 stop_reason 并决定进一步的行动方案。例如,它可以自己成为主应用程序,或者直接终止。超时时间代表连接超时(副本在尝试连接主应用程序时等待的时间)。params 结构包含一组副本控制标志(include/ha/mcoha.h)。例如 MCO_HAMODE_REPLICA_NOTIFICATION 等。
一个类似的简单的 C# 复制品实现看起来会像下面这样:
public Slave()
{
Database.Parameters parameters = new Database.Parameters();
parameters.MemPageSize = PAGE_SIZE;
db = new Database(new ExtremedbWrapper(),
Database.Mode.HighAvailabilitySupport);
db.Open( dbName, parameters, DATABASE_SIZE );
// start working thread
running = true;
Thread inspectThread = new Thread(new ThreadStart(Run));
inspectThread.Start();
ReplicaConnection con = new ReplicaConnection(db);
ReplicaConnection.Parameters RParams = new ReplicaConnection.Parameters();
if (!con.AttachMaster("localhost:" + PORT, replParams, CONNECT_TIMEOUT)) {
Console.WriteLine("Failed to connect to master");
}
//stop working thread
running = false;
inspectThread.Join();
Console.WriteLine("Replica is terminated");
con.Disconnect();
db.Close();
}