2015-06-08 38 views
5

Bolt ottiene un blocco di file sul file di dati in modo che più processi non possano aprire lo stesso database allo stesso tempo. L'apertura di un database Bolt già aperto causerà il blocco fino a quando l'altro processo non lo chiude.Boltdb-key-Value Data Store puramente in Go

In questo caso, esiste un concetto di pooling di connessione come i vari client che si collegano e accedono al database contemporaneamente? Questo è possibile in boltdb? Come ci sono varie connessioni di lettura e scrittura nel database allo stesso tempo. Come può essere implementato?

+1

Essendo un DB basato su file, è improbabile che cambi a causa del modo in cui i blocchi di file di lavoro. Probabilmente questa è anche una domanda migliore sul repository Bolt piuttosto che su StackOverflow: https://github.com/boltdb/bolt – elithrar

risposta

9

database di un bullone è di solito incorporato in un programma più ampio e non viene utilizzato attraverso la rete come si farebbe con i database condivisi (si pensi SQLite vs MySQL). Usare Bolt è un po 'come avere un persistente map[[]byte][]byte se fosse possibile. A seconda di cosa stai facendo, potresti voler semplicemente usare qualcosa come Redis.

Detto questo, se è necessario utilizzare Bolt in questo modo, non è molto difficile eseguire il wrapping con un server semplice. Ecco un esempio che scrive/legge le chiavi da un Bolt DB su HTTP. È possibile utilizzare Keep-Alive per il pool di connessioni.

Codice: 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)) 
} 
+0

Grazie mille! Ho capito come sia diverso dagli altri database che sono condivisi sulla rete. Lo avrà in possesso di un processo che espone un'API attraverso la rete. –

+0

Sembra buono. Un vantaggio del wrapping di un motore di archiviazione come questo è che puoi costruire l'interfaccia per soddisfare le tue esigenze specifiche. Utilizzi solo chiavi di piccole dimensioni e valori in cui il throughput è importante? Rendilo un'interfaccia UDP. O forse l'interfaccia di protobuf è più adatta a te. Continuerò a armeggiare con questo codice come un progetto parallelo. Quindi probabilmente proverò ognuno di questi. Buona fortuna. – SkyeC

+0

Ci sono vari ID univoci e tutti stanno offrendo una quantità ad un tasso di millisecondi e devo conservarlo e aggiornare la spesa corrente (la somma totale delle offerte fino a quel momento) al più presto. Lo schema che sto usando è come - un bucket per ogni ID univoco e che memorizza l'ora come chiave e valore dell'offerta. - un bucket comune per tutti univoci e aggiornamento della spesa corrente in tale dove key = id univoco e value = ultima spesa corrente. Come in questo caso quale interfaccia preferirei. E come posso aumentare la velocità di aggiornamento del valore i.e. dovrei usare db.Update() o db.Batch() e come? –

4

Non c'è alcun concetto di pool di connessione in boltdb, perché non c'è connessione. Non è un database client/server, è un database incorporato (come sqlite o Berkeley-DB).

Boltdb è progettato in modo che più goroutine dello stesso processo possano accedere contemporaneamente al database (utilizzando transazioni diverse). La modella è single writer, più lettori. Boltdb non è progettato per supportare gli accessi da più processi.

Se avete bisogno di un programma di Go di utilizzare un database incorporato sostenere l'accesso da più processi allo stesso tempo, si consiglia di avere uno sguardo ai wrapper oltre LMDB, come ad esempio:

+0

Ok! Grazie. Qualcuno può creare un tag boltDB in modo che sia facile gestire ulteriori query. –

+0

tag boltb appena aggiunto. –

+0

Grazie per aver aggiunto! –