WebAssembly 起初是为了解决 JavaScript 在浏览器上的一些性能瓶颈,目前已经不局限于浏览器, Wasi 规范使得其可以运行在更多的场景中,例如可信计算、边缘计算等。目前主流的语言基本都支持编译到 Wasm。ShardingSphere 的插件(SPI)只支持 Java 生态,把 Wasm 引入到 ShardingSphere 中可以进一步开放扩展,可以更加丰富其可插拔生态,吸引更多的社区开发者。
目前 Apache ShardingSphere 的可插拔架构使用 SPI 方式进行扩展,详见:ShardingSphere 开发者手册。
针对自定义分片场景,使用 WebAssembly 实现了自定义的分片 Demo。Demo 中演示了 sharding_count
为3
的自定义分片逻辑,实现步骤如下:
├── pom.xml
├── src
│ └── main
│ └── java
│ └── org
│ └── apache
│ └── shardingsphere
│ ├── infra
│ ├── sharding
WasmShardingAlgorithm
实例化 StandardShardingAlgorithm
, 运行自定义的分片逻辑并输出结果。// ...
StandardShardingAlgorithm<?> shardingAlgorithm = new WasmShardingAlgorithm();
// ...
#[link(wasm_import_module = "sharding")]
extern "C" {
fn poll_table(addr: i64, len: i32) -> i32;
}
// The value of sharding_count must be consistent with the value of the AvaliableTargetNames
const SHARDING_COUNT: u8 = 3;
#[no_mangle]
pub unsafe extern "C" fn do_work() -> i64 {
// ...
let sharding = column_value % SHARDING_COUNT;
// ...
std::ptr::copy_nonoverlapping(table_name.as_mut_ptr() as *const _, buf.as_mut_ptr().add(len as usize), table_name.len());
buf_ptr
}
src/main/java/org/apache/shardingsphere/sharding/
下创建 WasmShardingAlgorithm.java, 以和 Wasm 中的自定义分片逻辑通信并获得结果://...
public final class WasmShardingAlgorithm implements StandardShardingAlgorithm<Comparable<?>> {
// ...
private static final String WASM_PATH = "./wasm-sharding/target/wasm32-wasi/debug/wasm_sharding.wasm";
private String wasmDoSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<Comparable<?>> shardingValue) {
// ...
}
@Override
public String getType() {
return "WASM";
}
}
由于 ShardingSphere 定义分片规则只支持 Java 生态中的 Groovy 语法,通过 Wasm 用户可以使用自己熟悉的语言生态来定义分片逻辑。WASM-sharding-js 则演示了如何通过 JavaScript 定义 CRC32MOD 分片算法。
在当前 ShardingSphere 生态中,分片算法是通过 Groovy 的语法扩展的。为方便更多技术栈的用户使用,通过 Wasm 技术可以让用户使用自己熟悉的语言生态来定义分片逻辑,扩展分片算法。在 wasm-sharding-js 目录下提供了将 JavaScript 实现的分片算法编译成 Wasm 扩展的示例。
目录结构如下:
├── Cargo.lock
├── Cargo.toml
├── README.md
├── build.rs
├── lib
│ └── binding.rs
├── package-lock.json
├── package.json
├── sharding
│ ├── config.js
│ ├── crc32.js
│ ├── sharding.js
│ └── strgen.js
└── src
其中在 sharding/config.js
文件中,定义了两个分片的资源点表达式,分别为:t_order_00${0..2}
和 ms_ds00${crc32(field_id)}
。对于 t_order_00${0..2}
表达式,期望通过解析后,最终生成 t_order_000
、t_order_001
和 t_order_002
三个分片表。而对于 ms_ds00${crc32(field_id)}
表达式,期望对 field_id
字段进行 crc32
计算后进行分片:
export let cc = "t_order_00${0..2}"
export let cc_crc32 = "ms_ds00${crc32(field_id)}"
另外在 sharding/sharding.js
文件声明的pisa_crc32
函数中,展示了通过 JavaScript 代码实现的对上述两个表达式的解析:
//...
function pisa_crc32(str, mod) {
let c2 = crc32_str(str)
let m = c2 % mod
return m < 256 ? 0 : m < 512 ? 1: m<768 ? 2 : 3
}
//...
可以看到,通过 Wasm 用户不仅可以扩展 ShardingSphere 本身的功能,还可以扩展更多的技术栈。