Boltdb-key-Value data warehouse exclusively in Go

A bolt receives a file lock in a data file, so several processes cannot open the same database at the same time. Opening an already open Bolt database will freeze until another process closes it.

How does this take place, is there a concept for pooling, for example, various clients that simultaneously connect and access the database.? Is this possible in boltdb? As at the same time, there are different reads and writes of connections in the database. How can this be implemented?

+5
source share
2 answers

The Bolt database is usually embedded in a large program and is not used over the network, as is the case with shared databases (I think SQLite vs. MySQL). Using Bolt is a bit like constant map[[]byte][]byte , if possible. Depending on what you are doing, you might just use something like Redis.

However, if you need to use Bolt in this way, it is not very difficult to wrap a simple server. Below is an example that writes / reads keys from a bolt database through HTTP. You can use Keep-Alive to pool pools.

Code at: https://github.com/skyec/boltdb-server

 package main import ( "flag" "fmt" "io/ioutil" "log" "net/http" "time" "github.com/boltdb/bolt" "github.com/gorilla/mux" ) type server struct { db *bolt.DB } func newServer(filename string) (s *server, err error) { s = &server{} s.db, err = bolt.Open(filename, 0600, &bolt.Options{Timeout: 1 * time.Second}) return } func (s *server) Put(bucket, key, contentType string, val []byte) error { return s.db.Update(func(tx *bolt.Tx) error { b, err := tx.CreateBucketIfNotExists([]byte(bucket)) if err != nil { return err } if err = b.Put([]byte(key), val); err != nil { return err } return b.Put([]byte(fmt.Sprintf("%s-ContentType", key)), []byte(contentType)) }) } func (s *server) Get(bucket, key string) (ct string, data []byte, err error) { s.db.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(bucket)) r := b.Get([]byte(key)) if r != nil { data = make([]byte, len(r)) copy(data, r) } r = b.Get([]byte(fmt.Sprintf("%s-ContentType", key))) ct = string(r) return nil }) return } func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) if vars["bucket"] == "" || vars["key"] == "" { http.Error(w, "Missing bucket or key", http.StatusBadRequest) return } switch r.Method { case "POST", "PUT": data, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } err = s.Put(vars["bucket"], vars["key"], r.Header.Get("Content-Type"), data) w.WriteHeader(http.StatusOK) case "GET": ct, data, err := s.Get(vars["bucket"], vars["key"]) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Add("Content-Type", ct) w.Write(data) } } func main() { var ( addr string dbfile string ) flag.StringVar(&addr, "l", ":9988", "Address to listen on") flag.StringVar(&dbfile, "db", "/var/data/bolt.db", "Bolt DB file") flag.Parse() log.Println("Using Bolt DB file:", dbfile) log.Println("Listening on:", addr) server, err := newServer(dbfile) if err != nil { log.Fatalf("Error: %s", err) } router := mux.NewRouter() router.Handle("/v1/buckets/{bucket}/keys/{key}", server) http.Handle("/", router) log.Fatal(http.ListenAndServe(addr, nil)) } 
+9
source

Boltdb lacks the concept of joining connections, since there is no connection. It is not a client / server database, it is an embedded database (e.g. sqlite or Berkeley-DB).

Boltdb is designed so that multiple gotoutines of the same process can access the database at the same time (using different transactions). The model is a single writer, several readers. Boltdb is not intended to support access from multiple processes.

If you need a Go program to use a built-in database that supports access to several processes at the same time, you might want to take a look at the wrappers on top of LMDB, for example:

+4
source

All Articles