mgofencedlock

package module
v0.0.0-...-4ca8cef Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2020 License: MIT Imports: 10 Imported by: 0

README

mgofencedlock

Distributed locks using mongodb, with fencing

Build Status

Setup

Installing:

go get -u github.com/aarondwi/mgofencedlock

Run this script below in your mongo database:

db.lock.createIndex( { "Key": 1 }, { unique: true } )
db.lock.createIndex( { "last_seen": 1 }, { expireAfterSeconds: 600 } )

Notes

Unique index is required, to prevent multiple same keys from acquiring the lock in the database

ExpireAfterSeconds is not set to remove lock directly, but at much higher time than lock TTL

This is used to implement fencing token generation, and getting out of really small timing issue which restarts the version It is also for not bloating the storage, in case it is not deleted normally

You will need to the above function manually While doing that, you can also change default expiry to meet your use case

100ms before lock timeouts, it will refresh the lock automatically.

The time resolution for lock expiry time is 1 second, to reduce errors caused by NTP ~250ms bound

All of the read/write operation are using majority concern

Usage

m, err := New(connUrl, dbname, workerUniqueId, lockExpiryTimeSecond)
if err != nil {
  // handle the errors, failed creating connection to mongodb
}

// this lock will automatically refresh each (lockExpiryTimeSecond - 100ms)
mgolock, err := m.AcquireLock("some-key")
if err != nil {
  // failed acquiring lock, maybe some others have taken it
  // or there is some error in-between
}

if mgolock.IsValid() {
  // your code goes here
  // always need to check IsValid() before starting
  // to ensure the lock doesn't expire even before the code starts
  // can't do anything if the lock becomes invalid in the middle of your code
  // see https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html
}

// release the lock
// it returns nothing, as error may mean some other worker has taken it
m.DeleteLock(mgolock)

See main_test.go for examples

Queries use internally

acquire_lock:

db.lock.update({
  key: 'random-id', 
  $or: [
    {last_seen: null}, 
    {last_seen: {$lt: new Date() - expiryTimeSecond}}]
}, {
  $inc: {version: 1}, 
  $set:{'owner': 'me', last_seen: new Date()}}, 
{upsert: true})

get_lock_data:

db.lock.find({key: 'random-id', 'owner': 'me'}, {_id: 0})

delete_lock:

db.lock.remove({key: 'random-id', 'owner': 'me', version: 1})

refresh_lock:

db.lock.update(
  {key: 'random-id', 'owner': 'me', version: 1},
  {$set: {last_seen: new Date()}}
)

Document Schema

{
  "version": 1,
  "owner": "random id generated by each lock, or supplied",
  "key": "unique id for your resource",
  "last_seen": "to check for expiry (probably stale)"
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type MgoFencedLock

type MgoFencedLock struct {
	// contains filtered or unexported fields
}

MgoFencedLock is the core object to create by user

func New

func New(
	connectionURL string,
	dbname string,
	ownerID string,
	expiryTimeSecond int64) (*MgoFencedLock, error)

New creates our new MgoFencedLock

func (*MgoFencedLock) AcquireLock

func (m *MgoFencedLock) AcquireLock(key string) (*MgoLock, error)

AcquireLock creates lock records on mongodb and fetch the record to return to users

func (*MgoFencedLock) Close

func (m *MgoFencedLock) Close()

Close the connection to mongo

func (*MgoFencedLock) DeleteLock

func (m *MgoFencedLock) DeleteLock(mgolock *MgoLock)

DeleteLock removes the record lock from mongodb Returns nothing, as error may mean the lock has been taken by others

type MgoLock

type MgoLock struct {
	sync.Mutex
	Key     string
	Version int
	// contains filtered or unexported fields
}

MgoLock is the object users get after lock is acquired at mongodb

func (*MgoLock) IsValid

func (m *MgoLock) IsValid() bool

IsValid handle goroutine-safe checking of isValid

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL