Gonsensus is a distributed consensus implementation, written in Go, using S3 conditional operations for leader election. It provides a simple, reliable way to coordinate distributed systems using any S3 compatible object storage as the backing store. Conditional writes are required. See RFC 7232 for more details about conditional requests in general.
See example_test.go for a fully fledged example use case for simple leader election.
See integration_test.go for an example use case for leader election with quorum.
- S3-based leader election with atomic operations
- Automatic failover and clean shutdown
- Configurable TTL, polling, and quorum settings
- Leader election and demotion callbacks
- Observer pattern with heartbeat monitoring
- Thread-safe operations with mutex protection
- Version control for consistency
- Minimal dependencies (AWS SDK only)
Gonsensus implements distributed consensus through S3:
- Nodes compete to create a lock file in S3 using atomic operations
- Winner becomes leader and maintains lock through periodic renewals
- Failed renewals trigger automatic failover
- When enabled, leader tracks observer nodes through heartbeats
- Configurable quorum size ensures consensus
- Can operate in simple leader-election mode without quorum
- Automatic failover on leader failure
- Version control prevents split-brain scenarios
- Grace periods handle clean transitions
go get github.com/thevilledev/gonsensus
package main
import (
"context"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/thevilledev/gonsensus"
)
func main() {
// Initialize AWS S3 client
cfg, _ := config.LoadDefaultConfig(context.Background())
s3Client := s3.NewFromConfig(cfg)
// Create consensus manager
manager, _ := gonsensus.NewManager(s3Client, "my-bucket", gonsensus.Config{
NodeID: "node-1",
LockPrefix: "consensus/",
})
// Set leader callbacks
manager.SetCallbacks(
func(ctx context.Context) error { /* on elected */ return nil },
func(ctx context.Context) { /* on demoted */ },
)
// Run manager
manager.Run(context.Background())
}
This project relies on the AWS S3 client default authentication mechanism. See AWS documentation for full reference on configuration and credentials presedence.
In short, if you want to use environment variables you may do it like this:
export AWS_ACCESS_KEY_ID=
export AWS_SECRET_ACCESS_KEY=
export AWS_ENDPOINT_URL_S3=
export AWS_ENDPOINT_URL_IAM=
export AWS_ENDPOINT_URL_STS=
export AWS_REGION=
# run acceptance tests
make test-acc
If your configuration is in a local AWS profile in ~/.aws/config
you may do it like this instead:
export AWS_PROFILE=xyz
# run acceptance tests
make test-acc
Note that acceptance tests require a bucket with the name of "my-bucket-1".
This project is licensed under the MIT License - see the LICENSE file for details.