synopsis

bbold是一个嵌入式的kv存储,作为主程序的lib库存在,提供简单可靠的get、set
github
boltdb当前api已经固定了,另外生产环境上一直在使用,数据存储量高达1T,所以值得信赖。另外代码量比较少(< 5k),适合用于研究。

基本操作

open

import bolt "go.etcd.io/bbolt"

db, err := bolt.Open(path, 0666, nil)
if err != nil {
  return err
}
defer db.Close()

db上的操作是goroutine safe的

transaction

//read-write transaction
err := db.Update(func(tx *bolt.Tx) error {
	...
	return nil
})
//read-only transaction
err = db.View(func(tx *bolt.Tx) error {
	...
	return nil
})

batch

err := db.Batch(func(tx *bolt.Tx) error {
	...
	return nil
})

Concurrent Batch calls are opportunistically combined into larger transactions. Batch is only useful when there are multiple goroutines calling it.
batch可以随机合并多个goroutine的update操作,避免每个update带来的sync开销
batch有可能重试,所以需要是放入batch执行的函数需要时幂等的

bucket

bucket相当于一个namespace,一个bucket内的值必须唯一

db.Update(func(tx *bolt.Tx) error {
	b, err := tx.CreateBucket([]byte("MyBucket"))
	if err != nil {
		return fmt.Errorf("create bucket: %s", err)
	}
	return nil
})

key/value pairs

db.Update(func(tx *bolt.Tx) error {
	b := tx.Bucket([]byte("MyBucket"))
	err := b.Put([]byte("answer"), []byte("42"))
	return err
})
db.View(func(tx *bolt.Tx) error {
	b := tx.Bucket([]byte("MyBucket"))
	v := b.Get([]byte("answer"))
	fmt.Printf("The answer is: %s\n", v)
	return nil
})

get返回的byte slice使用的底层数组可能会改变,如果需要保存get的结果,需要copy一份

iteration

db.View(func(tx *bolt.Tx) error {
	// Assume bucket exists and has keys
	b := tx.Bucket([]byte("MyBucket"))

	c := b.Cursor()

	for k, v := c.First(); k != nil; k, v = c.Next() {
		fmt.Printf("key=%s, value=%s\n", k, v)
	}

	return nil
})

During iteration, if the key is non-nil but the value is nil, that means the key refers to a bucket rather than a value. Use Bucket.Bucket() to access the sub-bucket.

bucket是可以嵌套的

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐