bcache

package module
v0.0.0-...-9e37d77 Latest Latest
Warning

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

Go to latest
Published: Oct 2, 2024 License: MIT Imports: 10 Imported by: 0

README

bcache

godoc Build Status codecov Go Report Card Maintainability

A Go Library to create distributed in-memory cache inside your app.

Features

  • LRU cache with configurable maximum keys
  • Eventual Consistency synchronization between peers
  • Data are replicated to all nodes
  • cache filling mechanism. When the cache of the given key is not exist, bcache coordinates cache fills such that only one call populates the cache to avoid thundering herd or cache stampede

Why using it

  • if extra network hops needed by external caches like redis or memcached is not acceptable for you
  • you only need cache with simple Set, Get, and Delete operation
  • you have enough RAM to hold the cache data

How it Works

  1. Nodes find each other using Gossip Protocol

Only need to specify one or few nodes as bootstrap nodes, and all nodes will find each other using gossip protocol

  1. When there is cache Set and Delete, the event will be propagated to all of the nodes.

So, all of the nodes will eventually have synced data.

Cache filling

Cache filling mechanism is provided in GetWithFiller func.

When the cache for the given key is not exists:

  • it will call the provided Filler
  • set the cache using value returned by the Filler

Even there are many goroutines which call GetWithFiller, the given Filler func will only called once for each of the key. Cache stampede could be avoided this way.

Quick Start

In server 1

bc, err := New(Config{
	// PeerID:     1, // leave it, will be set automatically based on mac addr
	ListenAddr: "192.168.0.1:12345",
	Peers:      nil, // it nil because we will use this node as bootstrap node
	MaxKeys:    1000,
	Logger:     logrus.New(),
})
if err != nil {
    log.Fatalf("failed to create cache: %v", err)
}
bc.Set("my_key", "my_val",86400)

In server 2

bc, err := New(Config{
	// PeerID:     2, // leave it, will be set automatically based on mac addr
	ListenAddr: "192.168.0.2:12345",
	Peers:      []string{"192.168.0.1:12345"},
	MaxKeys:    1000,
	Logger:     logrus.New(),
})
if err != nil {
    log.Fatalf("failed to create cache: %v", err)
}
bc.Set("my_key2", "my_val2", 86400)

In server 3

bc, err := New(Config{
	// PeerID:     3,// will be set automatically based on mac addr
	ListenAddr: "192.168.0.3:12345",
	Peers:      []string{"192.168.0.1:12345"},
	MaxKeys:    1000,
	Logger:     logrus.New(),
})
if err != nil {
    log.Fatalf("failed to create cache: %v", err)
}
val, exists := bc.Get("my_key2")
GetWithFiller example
c, err := New(Config{
	PeerID:     3,
	ListenAddr: "192.168.0.3:12345",
	Peers:      []string{"192.168.0.1:12345"},
	MaxKeys:    1000,
})
if err != nil {
    log.Fatalf("failed to create cache: %v", err)
}
val, exp,err  := bc.GetWithFiller("my_key2",func(key string) (string, error) {
        // get value from database
         .....
         //
		return value, 0, nil
}, 86400)

Credits

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNilFiller returned when GetWithFiller called with nil
	// filler func
	ErrNilFiller = errors.New("nil filler")
)

Functions

This section is empty.

Types

type Bcache

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

Bcache represents bcache struct

func New

func New(cfg Config) (*Bcache, error)

New creates new bcache from the given config

func (*Bcache) Close

func (b *Bcache) Close() error

Close closes the cache, free all the resource

func (*Bcache) Delete

func (b *Bcache) Delete(key string)

Delete the given key.

func (*Bcache) Get

func (b *Bcache) Get(key string) (interface{}, bool)

Get gets value for the given key.

It returns the value and true if the key exists

func (*Bcache) GetWithFiller

func (b *Bcache) GetWithFiller(key string, filler Filler, ttl int) (interface{}, error)

GetWithFiller gets value for the given key and fill the cache if the given key is not exists.

`filler` will be used to fill(Set) the cache when the given key is not exist. Even there are many goroutines which call `GetWithFiller`, the given `Filler` func will only called once for each of the key.

It useful to avoid cache stampede to the underlying database

func (*Bcache) Set

func (b *Bcache) Set(key string, val interface{}, ttl int)

Set sets value for the given key with the given ttl in second. if ttl <= 0, the key will expired instantly

type Config

type Config struct {
	// PeerID is unique ID of this bcache
	// if PeerID = 0, it will be set using mac address
	PeerID uint64

	// ListenAddr is listen addr of this bcache peer.
	// used to communicate with other peers
	ListenAddr string

	// Peers is the address of the known peers.
	// we don't need to know all of the other peers,
	// gossip protocol will find the other peers
	Peers []string

	// MaxKeys defines max number of keys in this cache
	MaxKeys int

	// Logger to be used
	// leave it nil to use default logger which do nothing
	Logger Logger

	// DeletionDelay adds delay before actually delete the key,
	// it is used to handle temporary network connection issue,
	// which could prevent data syncing between nodes.
	// Leave it to 0 make it use default value: 100 seconds.
	DeletionDelay int
}

Config represents bcache configuration

type Filler

type Filler func(key string) (val string, err error)

Filler defines func to be called when the given key is not exists

type Logger

type Logger interface {
	Errorf(format string, v ...interface{})
	Printf(format string, v ...interface{})
	Debugf(format string, v ...interface{})
}

Logger defines interface that must be implemented by the logger of bcache

Jump to

Keyboard shortcuts

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