{"id":13411749,"url":"https://github.com/iwanbk/bcache","last_synced_at":"2025-05-05T11:30:57.145Z","repository":{"id":57496841,"uuid":"163194803","full_name":"iwanbk/bcache","owner":"iwanbk","description":"Eventually consistent distributed in-memory  cache Go library","archived":false,"fork":false,"pushed_at":"2023-01-13T09:48:31.000Z","size":36,"stargazers_count":157,"open_issues_count":4,"forks_count":20,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-21T21:44:58.211Z","etag":null,"topics":["cache","crdt","eventually-consistent","golang","gossip-protocol","in-memory-caching","lru-cache"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iwanbk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-12-26T15:45:16.000Z","updated_at":"2024-12-15T14:10:21.000Z","dependencies_parsed_at":"2023-02-09T15:31:10.132Z","dependency_job_id":null,"html_url":"https://github.com/iwanbk/bcache","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iwanbk%2Fbcache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iwanbk%2Fbcache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iwanbk%2Fbcache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iwanbk%2Fbcache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iwanbk","download_url":"https://codeload.github.com/iwanbk/bcache/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252488918,"owners_count":21756236,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache","crdt","eventually-consistent","golang","gossip-protocol","in-memory-caching","lru-cache"],"created_at":"2024-07-30T20:01:16.487Z","updated_at":"2025-05-05T11:30:56.859Z","avatar_url":"https://github.com/iwanbk.png","language":"Go","readme":"# bcache\n\n[![godoc](https://godoc.org/github.com/iwanbk/bcache?status.svg)](http://godoc.org/github.com/iwanbk/bcache)\n[![Build Status](https://travis-ci.org/iwanbk/bcache.svg?branch=master)](https://travis-ci.org/iwanbk/bcache)\n[![codecov](https://codecov.io/gh/iwanbk/bcache/branch/master/graph/badge.svg)](https://codecov.io/gh/iwanbk/bcache)\n[![Go Report Card](https://goreportcard.com/badge/github.com/iwanbk/bcache)](https://goreportcard.com/report/github.com/iwanbk/bcache)\n[![Maintainability](https://api.codeclimate.com/v1/badges/0535095fdd215f2e22ad/maintainability)](https://codeclimate.com/github/iwanbk/bcache/maintainability)\n\nA Go Library to create distributed in-memory cache inside your app.\n\n## Features\n\n- LRU cache with configurable maximum keys\n- Eventual Consistency synchronization between peers\n- Data are replicated to all nodes\n- 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)\n\n## Why using it\n\n- if extra network hops needed by external caches like `redis` or `memcached` is not acceptable for you\n- you only need cache with simple `Set`, `Get`, and `Delete` operation\n- you have enough RAM to hold the cache data\n\n## How it Works\n\n1. Nodes find each other using [Gossip Protocol](https://en.wikipedia.org/wiki/Gossip_protocol)\n\nOnly need to specify one or few nodes as bootstrap nodes, and all nodes will find each other using gossip protocol\n\n2. When there is cache `Set` and `Delete`, the event will be propagated to all of the nodes.\n\nSo, all of the nodes will eventually have synced data.\n\n\n\n## Cache filling\n\nCache filling mechanism is provided in [GetWithFiller](https://godoc.org/github.com/iwanbk/bcache#Bcache.GetWithFiller) func.\n\nWhen the cache for the given key is not exists:\n- it will call the provided `Filler`\n- set the cache using value returned by the `Filler`\n\nEven there are many goroutines which call `GetWithFiller`, the given `Filler` func\nwill only called once for each of the key.\nCache stampede could be avoided this way.\n\n## Quick Start\n\nIn server 1\n```go\nbc, err := New(Config{\n\t// PeerID:     1, // leave it, will be set automatically based on mac addr\n\tListenAddr: \"192.168.0.1:12345\",\n\tPeers:      nil, // it nil because we will use this node as bootstrap node\n\tMaxKeys:    1000,\n\tLogger:     logrus.New(),\n})\nif err != nil {\n    log.Fatalf(\"failed to create cache: %v\", err)\n}\nbc.Set(\"my_key\", \"my_val\",86400)\n```\n\nIn server 2\n```go\nbc, err := New(Config{\n\t// PeerID:     2, // leave it, will be set automatically based on mac addr\n\tListenAddr: \"192.168.0.2:12345\",\n\tPeers:      []string{\"192.168.0.1:12345\"},\n\tMaxKeys:    1000,\n\tLogger:     logrus.New(),\n})\nif err != nil {\n    log.Fatalf(\"failed to create cache: %v\", err)\n}\nbc.Set(\"my_key2\", \"my_val2\", 86400)\n```\n\nIn server 3\n```go\nbc, err := New(Config{\n\t// PeerID:     3,// will be set automatically based on mac addr\n\tListenAddr: \"192.168.0.3:12345\",\n\tPeers:      []string{\"192.168.0.1:12345\"},\n\tMaxKeys:    1000,\n\tLogger:     logrus.New(),\n})\nif err != nil {\n    log.Fatalf(\"failed to create cache: %v\", err)\n}\nval, exists := bc.Get(\"my_key2\")\n```\n\n### GetWithFiller example\n\n```go\nc, err := New(Config{\n\tPeerID:     3,\n\tListenAddr: \"192.168.0.3:12345\",\n\tPeers:      []string{\"192.168.0.1:12345\"},\n\tMaxKeys:    1000,\n})\nif err != nil {\n    log.Fatalf(\"failed to create cache: %v\", err)\n}\nval, exp,err  := bc.GetWithFiller(\"my_key2\",func(key string) (string, error) {\n        // get value from database\n         .....\n         //\n\t\treturn value, 0, nil\n}, 86400)\n```\n\n## Credits\n\n- [weaveworks/mesh](https://github.com/weaveworks/mesh) for the gossip library\n- [groupcache](https://github.com/golang/groupcache) for the inspiration","funding_links":[],"categories":["Uncategorized","Database","Generators","数据库","Data Integration Frameworks","数据库  `go语言实现的数据库`"],"sub_categories":["Advanced Console UIs","Caches","缓存","标准 CLI"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiwanbk%2Fbcache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiwanbk%2Fbcache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiwanbk%2Fbcache/lists"}