Skip to content

Commit

Permalink
Add distrlock/README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
vasayxtx committed Feb 13, 2025
1 parent c269a10 commit d0a9701
Show file tree
Hide file tree
Showing 4 changed files with 447 additions and 71 deletions.
143 changes: 143 additions & 0 deletions distrlock/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# distrlock

[![GoDoc Widget]][GoDoc]

## Overview

`distrlock` is a Go package that implements distributed locking using SQL databases.
It allows multiple processes or services to coordinate access to shared resources by acquiring and releasing locks stored in a database.

### Features
- Distributed lock management using SQL databases (PostgreSQL, MySQL are supported now)
- Support for acquiring, releasing, and extending locks
- Configurable lock expiration times

## How It Works

`distrlock` uses a relational database to implement distributed locking. When a process acquires a lock, a record is inserted or updated in a designated table within the database. The lock entry includes a unique key, a token for verification, and an expiration time to handle failures or crashes. Other processes attempting to acquire the same lock must wait until it is released or expires. If required, the lock can be extended before expiration to prevent unintended release.

This approach ensures reliable concurrency control without requiring an external distributed coordination system like Zookeeper or etcd, making it lightweight and easy to integrate into existing systems that already use SQL databases.

## Usage

`distlock` provides a simple API for acquiring and releasing locks.

The following basic example demonstrates how to use `distrlock` to ensure exclusive execution of a critical section of code:

```go
package distrlock_test

import (
"context"
"database/sql"
"log"
"os"
"time"

"github.com/acronis/go-dbkit"
"github.com/acronis/go-dbkit/distrlock"
)

func ExampleDoExclusively() {
// Setup database connection
db, err := sql.Open("mysql", os.Getenv("MYSQL_DSN"))
if err != nil {
log.Fatal(err)
}
defer db.Close()

ctx := context.Background()

// Create "distributed_locks" table for locks.
createTableSQL, err := distrlock.CreateTableSQL(dbkit.DialectMySQL)
if err != nil {
log.Fatal(err)
}
_, err = db.ExecContext(ctx, createTableSQL)
if err != nil {
log.Fatal(err)
}

// Do some work exclusively.
const lockKey = "test-lock-key-1" // Unique key that will be used to ensure exclusive execution among multiple instances
err = distrlock.DoExclusively(ctx, db, dbkit.DialectMySQL, lockKey, func(ctx context.Context) error {
time.Sleep(10 * time.Second) // Simulate work.
return nil
})
if err != nil {
log.Fatal(err)
}
}
```

If you need more customization or/and control over the lock lifecycle, you can use `DBManager` and `DBLock` objects directly:

```go
package distrlock_test

import (
"context"
"database/sql"
"log"
"os"
"time"

"github.com/acronis/go-dbkit"
"github.com/acronis/go-dbkit/distrlock"
)

func ExampleNewDBManager() {
// Setup database connection
db, err := sql.Open("mysql", os.Getenv("MYSQL_DSN"))
if err != nil {
log.Fatal(err)
}
defer db.Close()

// Create DBManager
lockManager, err := distrlock.NewDBManager(dbkit.DialectMySQL,
distrlock.WithTableName("my_distributed_locks"))
if err != nil {
log.Fatal(err)
}

ctx := context.Background()

// Create table for locks.
_, err = db.ExecContext(ctx, lockManager.CreateTableSQL())
if err != nil {
log.Fatal(err)
}

const lockKey = "test-lock-key-2" // Unique key that will be used to ensure exclusive execution among multiple instances

// Create lock.
lock, err := lockManager.NewLock(ctx, db, lockKey)
if err != nil {
log.Fatal(err)
}

// Acquire lock, do some work and release lock.
const lockTTL = 10 * time.Second
if err = lock.Acquire(ctx, db, lockTTL); err != nil {
log.Fatal(err)
}
defer func() {
if err = lock.Release(ctx, db); err != nil {
log.Fatal(err)
}
}()

time.Sleep(10 * time.Second) // Simulate work
}
```

## License

Copyright © 2024 Acronis International GmbH.

Licensed under [MIT License](./../LICENSE).

[GoDoc]: https://pkg.go.dev/github.com/acronis/go-dbkit/distrlock
[GoDoc Widget]: https://godoc.org/github.com/acronis/go-dbkit/distrlock?status.svg

Loading

0 comments on commit d0a9701

Please sign in to comment.