這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
Go語言開發的基於DRH(Deep-Re-Hash)深度雜湊分割演算法的高效能高可用Key-Value嵌入式交易資料庫。
gkvdb是開源的,免費的,基於MIT協議進行分發,開源項目地址(gitee與github倉庫保持即時同步):
Gitee( https://gitee.com/johng/gkvdb ),Github( https://github.com/johng-cn/g... )
特點
- 基於純Go語言實現,具有優異的跨平台性;
- 資料庫檔案採用DRH演算法設計,提升對隨機資料的操作效能;
- 良好的IO複用設計,提升對底層資料庫檔案的操作效能;
- 良好的高可用設計,保證在任何異常情況下資料的完整性;
- 提供的基本操作介面:Set()、Get()、Remove();
- 提供的事務操作介面:Begin()、Commit()、Rollback();
- 提供的多表操作介面:Table()、SetTo()、GetFrom()、RemoveFrom();
- 支援原子操作、大量操作、事務操作、多表操作、多表事務、隨機遍曆等特性;
限制
- (預設)表名最長 255B;
- (預設)鍵名最長 255B;
- (預設)索引值最長 16MB;
- (預設)單表資料 1TB;
- 支援隨機遍曆,不支援範圍遍曆;
- 嵌入式資料庫,沒有內建C/S架構;
安裝
go get -u gitee.com/johng/gfgo get -u gitee.com/johng/gkvdb
使用
1、基本用法
import "gitee.com/johng/gkvdb/gkvdb"// 建立資料庫,指定資料庫存放目錄// gkvdb支援多表,預設資料表名稱為defaultdb, err := gkvdb.New("/tmp/gkvdb")if err != nil { fmt.Println(err)}key := []byte("name")value := []byte("john")// 插入資料if err := db.Set(key, value); err != nil { fmt.Println(err)}// 查詢資料fmt.Println(db.Get(key))// 刪除資料if err := db.Remove(key); err != nil { fmt.Println(err)}// 關閉資料庫連結,讓GC自動回收資料庫相關資源db.Close()
2、事務操作
// 開啟事務tx := db.Begin()// 事務寫入tx.Set(key, value)// 事務查詢fmt.Println(tx.Get(key))// 事務提交tx.Commit()// 事務刪除tx.Remove(key)// 交易回復tx.Rollback()
3、大量操作
// 大量操作需要使用事務來實現tx := db.Begin()// 批量寫入for i := 0; i < 100; i++ { key := []byte("k_" + strconv.Itoa(i)) value := []byte("v_" + strconv.Itoa(i)) tx.Set(key, value)}tx.Commit()// 大量刪除for i := 0; i < 100; i++ { key := []byte("k_" + strconv.Itoa(i)) tx.Remove(key)}tx.Commit()
4、多表操作
// 建立user表name := "user"tu, err := db.Table(name)if err != nil { fmt.Println(err)}// user表寫入資料tu.Set([]byte("user_0"), []byte("name_0"))// user表查詢資料fmt.Println(tu.Get([]byte("user_0")))// user表刪除資料tu.Remove([]byte("user_0"))// 通過db對象操作user表寫入資料db.SetTo([]byte("user_1"), []byte("name_1"), name)// 通過db對象操作user表查詢資料fmt.Println(db.GetFrom([]byte("user_1"), name))// 通過db對象操作user表刪除資料db.RemoveFrom([]byte("user_1"), name)// 手動關閉表,釋放表資源// 一般不用手動關閉,在資料庫關閉時會自動關閉所有的表tu.Close()
5、多表事務
// 兩張表name1 := "user1"name2 := "user2"// 建立事務對象tx := db.Begin()// 事務操作user表寫入資料tx.SetTo([]byte("user_1"), []byte("name_1"), name1)tx.SetTo([]byte("user_2"), []byte("name_2"), name2)// 事務操作user表查詢資料fmt.Println("tx get1:", tx.GetFrom([]byte("user_1"), name1))fmt.Println("tx get2:", tx.GetFrom([]byte("user_2"), name2))tx.Commit()fmt.Println("db get1:", db.GetFrom([]byte("user_1"), name1))fmt.Println("db get2:", db.GetFrom([]byte("user_2"), name2))// 事務操作user表刪除資料tx.RemoveFrom([]byte("user_1"), name1)tx.RemoveFrom([]byte("user_2"), name2)fmt.Println("tx removed1:",tx.GetFrom([]byte("user_1"), name1))fmt.Println("tx removed2:",tx.GetFrom([]byte("user_2"), name2))// 刪除操作將被復原tx.Rollback()// 重新查詢fmt.Println("tx get1:", tx.GetFrom([]byte("user_1"), name1))fmt.Println("tx get2:", tx.GetFrom([]byte("user_2"), name2))fmt.Println("db get1:", db.GetFrom([]byte("user_1"), name1))fmt.Println("db get2:", db.GetFrom([]byte("user_2"), name2))
6、隨機遍曆
// ======預設default表的遍曆=====// 隨機擷取10條資料fmt.Println(db.Items(10))// 擷取所有的索引值對資料fmt.Println(db.Items(-1))// 擷取所有的鍵鍵名fmt.Println(db.Keys(-1))// 擷取所有的鍵索引值fmt.Println(db.Values(-1))// ======指定表的遍曆=====t1, err := db.Table("user1")if err != nil { fmt.Println(err)}t2, err := db.Table("user2")if err != nil { fmt.Println(err)}for i := 0; i < 10; i++ { key := []byte("k_" + strconv.Itoa(i)) value := []byte("v_" + strconv.Itoa(i)) t1.Set(key, value)}for i := 10; i < 20; i++ { key := []byte("k_" + strconv.Itoa(i)) value := []byte("v_" + strconv.Itoa(i)) t2.Set(key, value)}fmt.Println(t1.Items(-1))fmt.Println(t2.Items(-1))
效能
john@workstation:~/gkvdb/gkvdb_test/benchmark_test$ go test *.go -bench=".*"goos: linuxgoarch: amd64BenchmarkSet-8 300000 5130 ns/opBenchmarkGet-8 1000000 9628 ns/opBenchmarkRemove-8 500000 4053 ns/opPASSok command-line-arguments 13.964s