集群应用示例
SmartEDB 集群软件包包含一些示例应用程序,这些示例应用程序展示了基本的分布式数据库功能。
这些示例需要在同一台机器(节点)上以单独的进程运行多个实例(至少两个),或者在不同节点的网络中运行。
大多数示例都是通过命令行参数启动的,这些参数指定了集群的大小n_nodes以及此实例的 node_id。
所有示例可执行文件都构建在 target\bin 目录中。可以运行一个集群示例实例,并在开发系统调试器中运行另一个实例。
以下通用说明适用于所有集群示例。有关运行单个示例的说明,请参阅下面的“运行集群示例说明”。
单处理器示例
例如,要运行示例的两个实例,第一个实例将通过类似以下命令行启动:
cluster_sample 2 0这会以 node_id = 0作为两个节点中的第一个来启动应用程序。
然后,在一个单独的命令窗口中,以 node_id = 1 启动第二个实例:
cluster_sample 2 1在这种情况下,节点列表将自动填充 IP 地址和端口值:
127.0.0.1:20000
127.0.0.1:20100多处理器示例
在不同的网络节点上运行时,有必要指定一个节点列表。
这可以直接在命令行中使用 -nodelist 选项来完成,或者在节点描述文件中通过指定 –nodefile 选项来完成。
nodelist 参数的格式是:
<IP_address1> [: <port1>]; <IP_address2> [: <port2> ];....; <IP_addressN> [: <portN>]例如,要在网络节点 192.168.1.1 和 192.168.1.2 上运行 2 节点示例,应在指定节点上使用以下命令行参数:
192.168.1.1>:cluster_sample --nodelist "192.168.1.1:10000; 192.168.1.2:10000" 0
192.168.1.2>:cluster_sample --nodelist "192.168.1.1:10000; 192.168.1.2:10000" 1请注意
**nodelist 参数在所有节点上必须相同,**并且 node_id 必须与列表中节点的序列号相对应(从 0 开始)。
在上述情况中,192.168.1.1 是列表中的第一个节点,所以在节点 192.168.1.1 上指定 node_id 为 0;在节点 192.168.1.2 上,node_id 为 1。
节点文件示例
在文件中指定节点并使用 -nodefile 选项可能会更方便。
节点文件的条目指定了每个节点的 IP 地址和(可选的)端口号。例如,以下是一个包含两个节点的示例文件:
nodelist.txt:
192.168.1.1:10000
192.168.1.2:10000在这种情况下,将使用以下命令行来启动两个示例实例:
192.168.1.1>:cluster_sample --nodefile nodelist.txt 0
192.168.1.2>:cluster_sample --nodefile nodelist.txt 1其他命令行选项
以下其他选项可以在命令行中指定,以更改用于控制示例应用程序的 mco_cluster_params_t 结构中的默认值:
| 选项 | 说明 |
|---|---|
| --winlen N | (mco_cluster_params_t:: window::length): 事务中的最大窗口大小 |
| --winsz N | (mco_cluster_params_t:: window::bsize): 以字节为单位的最大窗口大小 |
| --winto N | (mco_cluster_params_ttimeout): 窗口超时值 |
| --sndbuf N | (mco_cluster_params_ttcp::so_sndbuf): 最大TCP套接字发送缓冲区大小(以字节为单位) |
| --rcvbuf N | (mco_cluster_params_ttcp::so_rcvbuf): 最大TCP套接字接收缓冲区大小(以字节为单位) |
| --connto N | (mco_cluster_params_ttcp::connect_timeout): 节点间连接超时阈值(以毫秒为单位) |
| --connint N | (mco_cluster_params_ttcp::connect_interval): 尝试连接到其他节点之间的时间间隔(以毫秒为单位) |
| --katime N | (mco_cluster_params_ttcp::keepalive_time): 保持活动消息之间的时间间隔(以毫秒为单位) |
| --kaprobes N | (mco_cluster_params_ttcp::keepalive_probes): 在节点断开连接之前发送的最大保活探测数 |
| --cpfact N | (mco_cluster_params_t::conn_pool_factor): 缓存连接的最大百分比 |
| --debug | (mco_cluster_params_t::mode_mask = MCO_CLUSTER_MODE_DEBUG_OUTPUT): 启用调试输出到标准输出(仅适用于 _debug 库版本) |
集群示例
请查看以下集群示例的描述和具体说明:
创建数据库
**这是最简单的集群示例。**该应用程序创建一个集群数据库,然后打印运行时信息并退出。
在控制台窗口中运行:
cluster_open 2 0在第二个控制台窗口中运行:
cluster_open 2 1基本性能
此示例展示了基本的集群性能。用户可以通过指定以下命令行参数来改变工作负载:
- -w <thread_num> - 写入线程的数量。通常线程越多,整体性能就越高
- -l <obj_size> - 对象大小(以字节为单位)(最小8字节)。更大的对象需要更多的网络带宽
- -r <max_rate> - 每个线程的最大事务速率(模拟部分负载)
- -n <trans_num> - 每个线程要处理的事务总数
- -c <conflict_rate> - 冲突的最大百分比
- -u <update_rate> - 插入/更新比率,以百分比表示(例如50)
- -t <max_time> - 以秒为单位的最大运行时间
- -u <update_rate> - 更新百分比
在控制台窗口中运行:
cluster_demo 2 0在第二个控制台窗口中运行:
cluster_demo 2 1节点重连
此示例演示了如何使用 mco_cluster_attach() 将节点重新附加到集群。
在控制台窗口中运行:
cluster_attach 2 0在第二个控制台窗口中运行:
cluster_attach 2 1相关代码:
/* 启用写入事务并在分离的数据库中创建对象 */
mco_cluster_detach(db);
{
mco_trans_h t;
Record rec;
mco_trans_start(db, MCO_READ_WRITE, MCO_TRANS_FOREGROUND, &t);
Record_new(t, &rec);
Record_key_put(&rec, N_OBJECTS * 100 + cl_info.node_id);
Record_value_put(&rec, 0);
mco_trans_commit(t);
}
print_database(db, "Database content after local modifications : ");
sample_sleep(1000);
/* 重新连接到集群 */
rc = mco_cluster_attach(db, &cl_params);
...
printf("Re-attached to cluster\n");
sample_start_connected_task(&listener_task, ClusterListener, db_name, 0); /* restart listener thread */
update_database(db, RUN_TIME / 2);
/* 停止集群,等待监听线程,打印数据库内容及统计信息 */
mco_cluster_stop(db);
sample_join_task(&listener_task);
mco_cluster_info(db, &cl_info);
print_database(db, "Database content after second mco_cluster_stop() (the same for all nodes) : ");
printf("Bytes sent %" INT8_FORMAT "u, received %" INT8_FORMAT "u\n", cl_info.bytes_sent, cl_info.bytes_recv);
...二进制转换
此示例展示了如何使用的二进制转换功能,在不同的集群节点上打开不同版本的数据库 cldb 。
请注意,模式文件 schema1.mco、schema2.mco 和 schema3.mco 的字段类型略有不同,并且在调用 mco_cluster_db_open() 之前,使用了元字典函数 mco_metadict_init() 和 mco_metadict_register() 来初始化元字典。
在控制台窗口中运行:
cluster_binev 2 0在第二个控制台窗口中运行:
cluster_binev 2 1获取节点列表
此示例演示了如何使用函数 mco_cluster_discover() 来确定活动节点的列表。
要运行此示例,请打开三个命令行窗口,并将安装根目录设置为当前工作目录。
在控制台窗口中运行:
cluster_demo -n 300000 2 05 秒内,在第二个控制台窗口中运行:
cluster_demo -n 300000 2 1这将启动集群并运行相当长的一段时间(选项-n 300000强制两个集群节点各执行 300,000个事务)。
10 秒内运行,在第三个控制台窗口中运行:
cluster_discover localhost:20000现在,示例将列出由 cluster_demo 创建的两个集群节点。
节点动态连接
此示例演示了如何动态将一个节点连接到集群。
在控制台窗口中运行:
cluster_dynamic <main_addr:main_port>在第二个控制台窗口中运行:
cluster_dynamic <main_addr:main_port> <own_addr:own_port>事件处理
此示例展示了在集群环境中同步和异步事件的使用。
该应用程序创建了一个集群数据库,注册了同步和异步事件处理程序,然后执行了 new()、update() 和 _delete() 操作。
请注意
删除操作是有可能会被拒绝,每个事件的处理程序都会在所有集群节点上被调用,因此只有当所有节点上的所有处理程序都返回 MCO_S_OK 时,操作才算成功完成。
在控制台窗口中运行:
cluster_events 2 0在第二个控制台窗口中运行:
cluster_events 2 1多监听线程
此示例展示了多个监听线程的使用方法。
对于那些具有“繁重”事务(即操作大量对象并需要更新多个索引等的事务)的应用程序来说,这种技术可能是明智之举。
在控制台窗口中运行:
cluster_mt 2 0在第二个控制台窗口中运行:
cluster_mt 2 1故障同步
此示例演示了集群中某个节点出现故障时的同步情况。
要查看同步是如何工作的,需要让在节点 0 上首次运行的 cluster_nodes 在几秒钟后退出,然后当在节点 0 和节点 1 上再次启动示例时,节点 0 上的实例将与节点 1 同步数据库内容。
在控制台窗口中运行:
cluster_nodes 2 0在第二个控制台窗口中运行:
cluster_nodes 2 1现在等待第一个实例退出,然后重新启动:
cluster_nodes 2 0请注意,节点 1 上的实例具有 rank=1,而节点 0 具有 rank=0。这是为了避免节点 0 断开连接时出现 MCO_E_CLUSTER_NOQUORUM 错误。
性能统计
此示例展示了基本的性能统计数据。
在控制台窗口中运行:
cluster_perf 2 0在第二个控制台窗口中运行:
cluster_perf 2 1仲裁回调
此示例演示了如何使用仲裁回调技术,而非标准的 qrank 机制。
在控制台窗口中运行:
cluster_quorum 2 0在第二个控制台窗口中运行:
cluster_quorum 2 1调整性能
此示例演示了如何针对每个线程调整读写工作负载。
对于每个线程,指定以下参数以调整性能:
node_id - 线程将在哪个节点上运行
write_percent - 写入/读取操作的比例
table_mask - 一个整数位掩码,用于指示要写入/读取的 8 个表(类)中的哪一个(使用值 0x1、0x2、...、0x40、0x80 分别表示类 T1、T2、...、T7、T8 等。有关表定义,请参阅 schema.mco。)
trans_len - 每次事务中要执行的操作数量
priority - 交易优先级
navigation - 要使用的导航方法:
SEARCH - 执行 _find() 以访问对象
SEQ_ASC - 使用 min_key、max_key 和 key_step 执行 _cursor_next() 操作
SEQ_DESC - 使用 min_key、max_key 和 key_step 执行 _cursor_prev() 操作
应用程序完成运行后,会打印出每个线程、每个节点以及总体的操作数量和操作速率。
在控制台窗口中运行:
cluster_rw 2 0在第二个控制台窗口中运行:
cluster_rw 2 1手动同步
此示例演示了如何使用分布式类以及 mco_cluster_scatter() 或 mco_cluster_gather() 调用在不同节点上手动同步数据库内容。
在控制台窗口中运行:
cluster_scatter 2 0在第二个控制台窗口中运行:
cluster_scatter 2 1共享内存
此示例展示了在集群环境中共享内存的使用方法。
请注意,可以在同一节点上运行多个进程。
在控制台窗口中运行:
cluster_shared 2 0节点 0 的此第一个进程将在共享内存中创建集群数据库。然后在第二个控制台窗口中运行:
cluster_shared 2 0对于节点 0 的第二个进程将连接到由第一个进程创建的数据库。然后在第三个控制台窗口中运行:
cluster_shared 2 1请注意,只有第一个进程(即创建数据库的进程)会打印出数据库的内容。
