go-memdb

基于不可改变的 radix 树的 Golang 内存数据库。「Golang in-memory database built on immutable radix trees」

  • Owner: hashicorp/go-memdb
  • Platform: Linux, Mac, Windows
  • License:: Mozilla Public License 2.0
  • Category::
  • Topic:
  • Like:
    0
      Compare:

Github stars Tracking Chart

go-memdb

提供 memdb 包,它实现了一个建立在不可改变的 radix 树上的简单内存数据库。该数据库提供原子性、一致性和与 ACID 隔离。由于是内存数据库,它不提供耐久性。数据库被实例化时有一个模式,该模式指定了存在的表和索引,并允许执行事务。

数据库提供了以下功能:

  • 多版本并发控制(MVCC)-- 通过利用不可变的 radix 树,数据库能够支持任何数量的并发读取器,而不需要锁定,并允许写入器取得进展。
  • 事务支持 -- 数据库允许丰富的事务,其中插入、更新或删除多个对象。事务可以跨越多个表,并以原子方式应用。数据库在ACID术语中提供了原子性和隔离性,因此在提交之前,更新是不可见的。
  • 丰富的索引 -- 表可以支持任意数量的索引,可以是简单的如单字段索引,也可以是更高级的复合字段索引。某些类型,如UUID,可以有效地从字符串压缩成字节索引,以减少存储需求。
  • 监视 -- 调用者可以填充一个监视集作为查询的一部分,它可以用来检测何时对数据库进行了影响查询结果的修改。这让调用者可以很容易地以一种非常通用的方式观察数据库的变化。

关于底层的不可改变的 radix 树,请参见 go-immutable-radix

文档

完整的文档可以在 Godoc 上找到。

例子

下面是一个简单的使用实例

// Create a sample struct
type Person struct {
    Email string
    Name  string
    Age   int
}

// Create the DB schema
schema := &memdb.DBSchema{
    Tables: map[string]*memdb.TableSchema{
        "person": &memdb.TableSchema{
            Name: "person",
            Indexes: map[string]*memdb.IndexSchema{
                "id": &memdb.IndexSchema{
                    Name:    "id",
                    Unique:  true,
                    Indexer: &memdb.StringFieldIndex{Field: "Email"},
                },
                "age": &memdb.IndexSchema{
                    Name:    "age",
                    Unique:  false,
                    Indexer: &memdb.IntFieldIndex{Field: "Age"},
                },
            },
        },
    },
}

// Create a new data base
db, err := memdb.NewMemDB(schema)
if err != nil {
    panic(err)
}

// Create a write transaction
txn := db.Txn(true)

// Insert some people
people := []*Person{
    &Person{"joe@aol.com", "Joe", 30},
    &Person{"lucy@aol.com", "Lucy", 35},
    &Person{"tariq@aol.com", "Tariq", 21},
    &Person{"dorothy@aol.com", "Dorothy", 53},
}
for _, p := range people {
    if err := txn.Insert("person", p); err != nil {
        panic(err)
    }
}

// Commit the transaction
txn.Commit()

// Create read-only transaction
txn = db.Txn(false)
defer txn.Abort()

// Lookup by email
raw, err := txn.First("person", "id", "joe@aol.com")
if err != nil {
    panic(err)
}

// Say hi!
fmt.Printf("Hello %s!\n", raw.(*Person).Name)

// List all the people
it, err := txn.Get("person", "id")
if err != nil {
    panic(err)
}

fmt.Println("All the people:")
for obj := it.Next(); obj != nil; obj = it.Next() {
    p := obj.(*Person)
    fmt.Printf("  %s\n", p.Name)
}

// Range scan over people with ages between 25 and 35 inclusive
it, err = txn.LowerBound("person", "age", 25)
if err != nil {
    panic(err)
}

fmt.Println("People aged 25 - 35:")
for obj := it.Next(); obj != nil; obj = it.Next() {
    p := obj.(*Person)
    if p.Age > 35 {
        break
    }
    fmt.Printf("  %s is aged %d\n", p.Name, p.Age)
}
// Output:
// Hello Joe!
// All the people:
//   Dorothy
//   Joe
//   Lucy
//   Tariq
// People aged 25 - 35:
//   Joe is aged 30
//   Lucy is aged 35


Main metrics

Overview
Name With Ownerhashicorp/go-memdb
Primary LanguageGo
Program languageGo (Language Count: 1)
PlatformLinux, Mac, Windows
License:Mozilla Public License 2.0
所有者活动
Created At2015-06-16 22:54:29
Pushed At2025-04-16 09:58:47
Last Commit At
Release Count16
Last Release Namev1.3.5 (Posted on )
First Release Namev1.0.0 (Posted on )
用户参与
Stargazers Count3.3k
Watchers Count337
Fork Count215
Commits Count169
Has Issues Enabled
Issues Count59
Issue Open Count34
Pull Requests Count65
Pull Requests Open Count12
Pull Requests Close Count35
项目设置
Has Wiki Enabled
Is Archived
Is Fork
Is Locked
Is Mirror
Is Private

go-memdb CircleCI

Provides the memdb package that implements a simple in-memory database
built on immutable radix trees. The database provides Atomicity, Consistency
and Isolation from ACID. Being that it is in-memory, it does not provide durability.
The database is instantiated with a schema that specifies the tables and indices
that exist and allows transactions to be executed.

The database provides the following:

  • Multi-Version Concurrency Control (MVCC) - By leveraging immutable radix trees
    the database is able to support any number of concurrent readers without locking,
    and allows a writer to make progress.

  • Transaction Support - The database allows for rich transactions, in which multiple
    objects are inserted, updated or deleted. The transactions can span multiple tables,
    and are applied atomically. The database provides atomicity and isolation in ACID
    terminology, such that until commit the updates are not visible.

  • Rich Indexing - Tables can support any number of indexes, which can be simple like
    a single field index, or more advanced compound field indexes. Certain types like
    UUID can be efficiently compressed from strings into byte indexes for reduced
    storage requirements.

  • Watches - Callers can populate a watch set as part of a query, which can be used to
    detect when a modification has been made to the database which affects the query
    results. This lets callers easily watch for changes in the database in a very general
    way.

For the underlying immutable radix trees, see go-immutable-radix.

Documentation

The full documentation is available on Godoc.

Example

Below is a simple example of usage

// Create a sample struct
type Person struct {
	Email string
	Name  string
	Age   int
}

// Create the DB schema
schema := &memdb.DBSchema{
	Tables: map[string]*memdb.TableSchema{
		"person": &memdb.TableSchema{
			Name: "person",
			Indexes: map[string]*memdb.IndexSchema{
				"id": &memdb.IndexSchema{
					Name:    "id",
					Unique:  true,
					Indexer: &memdb.StringFieldIndex{Field: "Email"},
				},
				"age": &memdb.IndexSchema{
					Name:    "age",
					Unique:  false,
					Indexer: &memdb.IntFieldIndex{Field: "Age"},
				},
			},
		},
	},
}

// Create a new data base
db, err := memdb.NewMemDB(schema)
if err != nil {
	panic(err)
}

// Create a write transaction
txn := db.Txn(true)

// Insert some people
people := []*Person{
	&Person{"joe@aol.com", "Joe", 30},
	&Person{"lucy@aol.com", "Lucy", 35},
	&Person{"tariq@aol.com", "Tariq", 21},
	&Person{"dorothy@aol.com", "Dorothy", 53},
}
for _, p := range people {
	if err := txn.Insert("person", p); err != nil {
		panic(err)
	}
}

// Commit the transaction
txn.Commit()

// Create read-only transaction
txn = db.Txn(false)
defer txn.Abort()

// Lookup by email
raw, err := txn.First("person", "id", "joe@aol.com")
if err != nil {
	panic(err)
}

// Say hi!
fmt.Printf("Hello %s!\n", raw.(*Person).Name)

// List all the people
it, err := txn.Get("person", "id")
if err != nil {
	panic(err)
}

fmt.Println("All the people:")
for obj := it.Next(); obj != nil; obj = it.Next() {
	p := obj.(*Person)
	fmt.Printf("  %s\n", p.Name)
}

// Range scan over people with ages between 25 and 35 inclusive
it, err = txn.LowerBound("person", "age", 25)
if err != nil {
	panic(err)
}

fmt.Println("People aged 25 - 35:")
for obj := it.Next(); obj != nil; obj = it.Next() {
	p := obj.(*Person)
	if p.Age > 35 {
		break
	}
	fmt.Printf("  %s is aged %d\n", p.Name, p.Age)
}
// Output:
// Hello Joe!
// All the people:
//   Dorothy
//   Joe
//   Lucy
//   Tariq
// People aged 25 - 35:
//   Joe is aged 30
//   Lucy is aged 35