Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/iwanbk/bcache
Eventually consistent distributed in-memory cache Go library
https://github.com/iwanbk/bcache
cache crdt eventually-consistent golang gossip-protocol in-memory-caching lru-cache
Last synced: about 1 month ago
JSON representation
Eventually consistent distributed in-memory cache Go library
- Host: GitHub
- URL: https://github.com/iwanbk/bcache
- Owner: iwanbk
- License: mit
- Created: 2018-12-26T15:45:16.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2023-01-13T09:48:31.000Z (almost 2 years ago)
- Last Synced: 2024-07-31T20:48:45.115Z (5 months ago)
- Topics: cache, crdt, eventually-consistent, golang, gossip-protocol, in-memory-caching, lru-cache
- Language: Go
- Homepage:
- Size: 35.2 KB
- Stars: 150
- Watchers: 6
- Forks: 18
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-go - bcache - Eventually consistent distributed in-memory cache Go library. (Database / Caches)
- awesome-go-extra - bcache - memory cache Go library|90|13|4|2018-12-26T15:45:16Z|2019-05-01T02:01:34Z| (Generators / Caches)
README
# bcache
[![godoc](https://godoc.org/github.com/iwanbk/bcache?status.svg)](http://godoc.org/github.com/iwanbk/bcache)
[![Build Status](https://travis-ci.org/iwanbk/bcache.svg?branch=master)](https://travis-ci.org/iwanbk/bcache)
[![codecov](https://codecov.io/gh/iwanbk/bcache/branch/master/graph/badge.svg)](https://codecov.io/gh/iwanbk/bcache)
[![Go Report Card](https://goreportcard.com/badge/github.com/iwanbk/bcache)](https://goreportcard.com/report/github.com/iwanbk/bcache)
[![Maintainability](https://api.codeclimate.com/v1/badges/0535095fdd215f2e22ad/maintainability)](https://codeclimate.com/github/iwanbk/bcache/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](https://en.wikipedia.org/wiki/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](https://en.wikipedia.org/wiki/Gossip_protocol)
Only need to specify one or few nodes as bootstrap nodes, and all nodes will find each other using gossip protocol
2. 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](https://godoc.org/github.com/iwanbk/bcache#Bcache.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
```go
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
```go
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
```go
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
```go
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
- [weaveworks/mesh](https://github.com/weaveworks/mesh) for the gossip library
- [groupcache](https://github.com/golang/groupcache) for the inspiration