High-performant, easy-to-use data replication tool. Replicate data from any source to any destination with ease (Homogeneous or Heterogeneous).
- Source transformation: Modify, rename, delete fields
- Auto Resuming: Resume from the last successful position - if failed
- Batch Migration: Process migration in batches
- Parallel Migration: Break data into chunks and load in parallel
- Continuous Replication: Watch for new changes and replicate them; A.K.A Change Data Capture (CDC)
- Import & Export: Load or Save data from/to CSV & Parquet file
| Datasource | Status | Read | Write | Stream (CDC) |
|---|---|---|---|---|
Memory |
✅ | ✅ | ✅ | ✅ |
MongoDB |
✅ | ✅ | ✅ | ✅ (with change streams) |
Redis |
✅ | ✅ | ✅ | ✅ (with keyspace notifications) |
Postgres |
✅ | ✅ | ✅ | ✅ (with logical replication) |
MySQL |
✅ | ✅ | ✅ | ✅ (with binlog replication) |
MariaDB |
✅ | ✅ | ✅ | ✅ (with binlog replication) |
<More> |
Soon | TBC | TBC | TBC |
| Store | Status |
|---|---|
Memory |
✅ |
File |
✅ |
Redis |
✅ |
go get github.com/sagadana/migratorpackage main
import (
"github.com/sagadana/migrator/datasources"
"github.com/sagadana/migrator/pipelines"
"github.com/sagadana/migrator/states"
)
func main() {
ctx, cancel := context.WithCancel(context.TODO())
defer cancel()
// Create the `From` datasource _(Memory Data Source in this example)_
fromDs := datasources.NewMemoryDatasource("test-from", "id")
// Load data from a CSV if needed
err := fromDs.Import(&ctx, datasources.DatasourceImportRequest{
Type: datasources.DatasourceImportTypeCSV,
Source: datasources.DatasourceImportSourceFile,
Location: "./tests/sample-100.csv",
BatchSize: 10,
})
if err != nil {
panic(err)
}
// Create the `To` datasource _(Memory Data Source in this example)_
toDs := datasources.NewMemoryDatasource("test-to", "id")
// Initialize Pipeline
pipeline := pipelines.Pipeline{
ID: "test-pipeline-1",
From: fromDs,
To: toDs,
Store: states.NewFileStateStore("./tests", "state"),
}
// Start Migration Only
err = pipeline.Start(&ctx, pipelines.PipelineConfig{
MigrationParallelWorkers: 5,
MigrationBatchSize: 10,
OnMigrationStart: func(state states.State) { /* Add your logic. E.g extra logs */ },
OnMigrationProgress: func(state states.State, count pipelines.DatasourcePushCount) { /* Add your logic. E.g extra logs */ },
OnMigrationError: func(state states.State, data datasources.DatasourcePushRequest, err error) { /* Add your logic. E.g extra logs */ },
OnMigrationStopped: func(state states.State) { /* Add your logic. E.g extra logs */ },
}, /*with replication*/ false)
if err != nil {
panic(err)
}
}func main() {
// .... (init codes)
// Start Migration + Replication
err = pipeline.Start(&ctx, pipelines.PipelineConfig{
MigrationParallelWorkers: 5,
MigrationBatchSize: 10,
ReplicationBatchSize: 20,
ReplicationBatchWindowSecs: 1,
OnMigrationStart: func(state states.State) { /* Add your logic. E.g extra logs */ },
OnMigrationProgress: func(state states.State, count pipelines.DatasourcePushCount) { /* Add your logic. E.g extra logs */ },
OnMigrationError: func(state states.State, data datasources.DatasourcePushRequest, err error) { /* Add your logic. E.g extra logs */ },
OnMigrationStopped: func(state states.State) { /* Add your logic. E.g extra logs */ },
OnReplicationStart: func(state states.State) { /* Add your logic. E.g extra logs */ },
OnReplicationProgress: func(state states.State, count pipelines.DatasourcePushCount) { /* Add your logic. E.g extra logs */ },
OnReplicationError: func(state states.State, data datasources.DatasourcePushRequest, err error) { /* Add your logic. E.g extra logs */ },
OnReplicationStopped: func(state states.State) { /* Add your logic. E.g extra logs */ },
}, /*with replication*/ true)
if err != nil {
panic(err)
}
}func main() {
// .... (init codes)
// Start Replication
err = pipeline.Stream(&ctx, pipelines.PipelineConfig{
ReplicationBatchSize: 20,
ReplicationBatchWindowSecs: 1,
OnReplicationStart: func(state states.State) { /* Add your logic. E.g extra logs */ },
OnReplicationProgress: func(state states.State, count pipelines.DatasourcePushCount) { /* Add your logic. E.g extra logs */ },
OnReplicationError: func(state states.State, data datasources.DatasourcePushRequest, err error) { /* Add your logic. E.g extra logs */ },
OnReplicationStopped: func(state states.State) { /* Add your logic. E.g extra logs */ },
})
if err != nil {
panic(err)
}
}Run this to catch lint issues
docker compose --env-file ./tests/.env.dev up lintdocker compose --env-file ./tests/.env.dev up tester-statedocker compose --env-file ./tests/.env.dev up tester-dsdocker compose --env-file ./tests/.env.dev up tester-pipedocker compose --env-file ./tests/.env.dev up tester-helperSee CONTRIBUTING.md