The origin of Bitcask is tied to the history of the Riak distributed database. In a Riak key/value cluster, each node uses pluggable local storage; nearly anything k/v-shaped can be used as the per-host storage engine. This pluggability allowed progress on Riak to be parallelized such that storage engines could be improved and tested without impact on the rest of the codebase. NOTE: All project specifications and usage are mentioned in this Official Bitcask Design Paper
Function | Description |
---|---|
func Open(directoryPath string, config ...Config) (*Bitcask, error) |
Open a new or an existing bitcask datastore |
func (bc *Bitcask) Put(key []byte, value []byte) error |
Stores a key and a value in the bitcask datastore |
func (bc *Bitcask) Get(key []byte) ([]byte, error) |
Reads a value by key from a datastore |
func (bc *Bitcask) Delete(key []byte) error |
Removes a key from the datastore |
func (bc *Bitcask) Close() |
Close a bitcask data store and flushes all pending writes to disk |
func (bc *Bitcask) ListKeys() [][]byte |
Returns list of all keys |
func (bc *Bitcask) Sync() error |
Force any writes to sync to disk |
func (bc *Bitcask) Merge() error |
Merge several data files within a Bitcask datastore into a more compact form. Also, produce hintfiles for faster startup. |
func (bc *Bitcask) Fold(fun func([]byte, []byte, any) any, acc any) any |
Fold over all K/V pairs in a Bitcask datastore.→ Acc Fun is expected to be of the form: F(K,V,Acc0) → Acc |
package main
import (
"bitcask"
"fmt"
"path"
)
func main() {
bc, err := bitcask.Open(path.Join("bitcask"), bitcask.RWsyncConfig)
if err != nil {
fmt.Println(err.Error())
return
}
for { }
bc.Close()
}
package main
import (
"bitcask"
"fmt"
"path"
)
func main() {
bc, err := bitcask.Open(path.Join("bitcask"), bitcask.RWsyncConfig)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("***** append 100 item *****")
for i := 0; i < 100; i++ {
key := "key" + fmt.Sprintf("%d", i)
value := "value" + fmt.Sprintf("%d", i)
bc.Put([]byte(key), []byte(value))
}
fmt.Println("****** merge old files *******")
bc.Merge()
fmt.Println("****** Get some items ********")
val2, err := bc.Get([]byte("key2"))
fmt.Printf("value of key2 is: %s\n", string(val2))
if err != nil {
fmt.Println(err)
}
val15, err := bc.Get([]byte("key15"))
fmt.Printf("value of key15 is: %s\n", string(val15))
if err != nil {
fmt.Println(err)
}
val77, err := bc.Get([]byte("key77"))
if err != nil {
fmt.Println(err)
}
fmt.Printf("value of key77 is: %s\n", string(val77))
fmt.Println("****** close bitcask *******")
bc.Close()
}
$ go run demos/demo_writer/writer.go
***** append 100 item *****
****** merge old files *******
****** Get some items ********
value of key2 is: value2
value of key15 is: value15
value of key77 is: value77
****** close bitcask *******
$ go run demos/demo_writer/writer.go
there is another process that locked this bitcask
package main
import (
"bitcask"
"fmt"
"path"
)
func main() {
bc, err := bitcask.Open(path.Join("bitcask"))
if err != nil {
fmt.Println(err.Error())
return
}
for { }
bc.Close()
}
package main
import (
"bitcask"
"fmt"
"path"
)
func main() {
bc, err := bitcask.Open(path.Join("bitcask"))
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("****** Get some items ********")
val2, _ := bc.Get([]byte("key2"))
fmt.Printf("value of key2 is: %s\n", string(val2))
val15, _ := bc.Get([]byte("key15"))
fmt.Printf("value of key15 is: %s\n", string(val15))
val77, _ := bc.Get([]byte("key77"))
fmt.Printf("value of key77 is: %s\n", string(val77))
fmt.Println("****** close bitcask *******")
bc.Close()
}
$ go run demos/demo_reader/reader.go
****** Get some items ********
value of key2 is:
value of key15 is:
value of key77 is:
****** close bitcask *******
$ go run demos/demo_reader/reader.go
there is another process that locked this bitcask
$ go run demos/demo_reader/reader.go
****** Get some items ********
value of key2 is:
value of key15 is:
value of key77 is:
****** close bitcask *******