levelDB了解
标题1.挖矿的过程,前面利用Pow算法完成挖矿,分为以下几个大概步骤:
- Pow挖矿
- 将区块放到链中(链表)
- 数据持久化存储(levelDB)
- 在广域网中做广播(UDP)
LevleDB是什么?
- leveldb是google俩位工程师使用C++实现的单机版k-v存储系统。
- key和value是任意的字节数组,支持存储和持久化存储。
- 数据都是按照key排序,用户可以重写排序函数。
- 包含基本的数据操作接口,Put(key,value),Delete(key)
- 多操作可以当成一次原子操作。–支持事物
LevleDB的局限性
- leveldb是非关系型数据库,不支持SQL查询也不支持索引。
- 同一时间只支持单进程(支持多线程)访问db。
- 不支持客户端-服务器模式,用户需要自己封装。
LevleDB的工作流程
先存硬盘,保证数据不会丢失,再存内存中,便于高效读取数据
模拟写法
先创建leveldb.go
package txt2
import "fmt"
// DB的结构体
type DB struct {
//模拟真实的场景
//地址
path string
//数据
data map[string][]byte
}
// 模拟开启链接,通过地址开启
func New(path string) (*DB, error) {
self := DB{
path: path,
data: make(map[string][]byte),
}
return &self, nil
}
// 模拟关闭链接
func (self *DB) Close() error {
return nil
}
func (self *DB) Put(key []byte, value []byte) error {
self.data[string(key)] = value
return nil
}
func (self *DB) Get(key []byte) ([]byte, error) {
if v, ok := self.data[string(key)]; ok {
return v, nil
} else {
return nil, fmt.Errorf("NotFound")
}
}
func (self *DB) Del(key []byte) error {
if _, ok := self.data[string(key)]; ok {
delete(self.data, string(key))
return nil
} else {
return fmt.Errorf("NotFound")
}
}
// 模拟遍历取值
//func (self *DB) Iterator() Iterator {
//
//}
再写一个迭代器iterator.go
package txt2
import "fmt"
// 写个迭代器
type Iterator interface {
//判断是否有下一个值
Nxet() bool
//遍历键值
Key() []byte
Value() []byte
}
// 定义一个键值的结构体
type Pair struct {
Key []byte
Value []byte
}
// 迭代器的结构体
type DefaultIterator struct {
//键值对
data []Pair
//索引和长度
index int
length int
}
// 创建默认的迭代器
func NewDefaultIterator(data map[string][]byte) *DefaultIterator {
self := new(DefaultIterator)
self.index = -1
self.length = len(data)
for k, v := range data {
p := Pair{
Key: []byte(k),
Value: v,
}
//把遍历到的数据添加到data里面
self.data = append(self.data, p)
}
return self
}
func (self *DefaultIterator) Next() bool {
//判断是否有下一个
if self.index < self.length-1 {
self.index++
return true
}
return false
}
func (self *DefaultIterator) Key() []byte {
//做个判断
if self.index == -1 || self.index >= self.length {
panic(fmt.Errorf("IndexOutofBoundError"))
}
return self.data[self.index].Key
}
func (self *DefaultIterator) Value() []byte {
//做个判断
if self.index >= self.length {
panic(fmt.Errorf("IndexOutofBoundError"))
}
return self.data[self.index].Value
}
然后再写一个测试
package txt2
import (
"fmt"
"testing"
)
// 测试默认迭代器iterator_test.go
func TestNewDefaultIterator(t *testing.T) {
data := make(map[string][]byte)
data["K1"] = []byte("v1")
data["K2"] = []byte("v2")
data["K3"] = []byte("v3")
iter := NewDefaultIterator(data)
if iter.length != 3 {
t.Fatal()
}
for iter.Next() {
fmt.Printf("%s:%s\n", iter.Key(), string(iter.Value()))
}
}
测试结果:
创建leveldb_test.go
package txt2
import (
"bytes"
"fmt"
"testing"
)
func Test_leveldb(t *testing.T) {
//先测试链接
db, err := New("")
check(err)
err = db.Put([]byte("K1"), []byte("v1"))
check(err)
err = db.Put([]byte("K2"), []byte("v2"))
check(err)
err = db.Put([]byte("K3"), []byte("v3"))
check(err)
//俩个K重复,看看效果
err = db.Put([]byte("K1"), []byte("v11"))
check(err)
err = db.Put([]byte("K8"), []byte("v8"))
check(err)
//取数据测试
v, err := db.Get([]byte("K8"))
fmt.Printf("%s\n", v)
//如果取的值不是v8
if !bytes.Equal(v, []byte("v8")) {
t.Fatal()
}
v, err = db.Get([]byte("K1"))
//(v, []byte("v1")) 会捕获到,,实际上k1是获取到v11的
if !bytes.Equal(v, []byte("v11")) {
t.Fatal()
}
//删除
err = db.Del([]byte("K1"))
check(err)
iter := db.Iterator()
for iter.Nxet() {
fmt.Printf("%s - %s\n", string(iter.Key()), string(iter.Value()))
}
}
func check(err error) {
if err != nil {
panic(err)
}
}
后续代码补充:leveldb.go
package txt2
import "fmt"
// DB的结构体
type DB struct {
//模拟真实的场景
//地址
path string
//数据
data map[string][]byte
}
// 模拟开启链接,通过地址开启
func New(path string) (*DB, error) {
self := DB{
path: path,
data: make(map[string][]byte),
}
return &self, nil
}
// 模拟关闭链接
func (self *DB) Close() error {
return nil
}
func (self *DB) Put(key []byte, value []byte) error {
self.data[string(key)] = value
return nil
}
func (self *DB) Get(key []byte) ([]byte, error) {
if v, ok := self.data[string(key)]; ok {
return v, nil
} else {
return nil, fmt.Errorf("NotFound")
}
}
func (self *DB) Del(key []byte) error {
if _, ok := self.data[string(key)]; ok {
delete(self.data, string(key))
return nil
} else {
return fmt.Errorf("NotFound")
}
}
// 模拟遍历取值
func (self *DB) Iterator() Iterator {
return NewDefaultIterator(self.data)
}
补充:iterator_test.go
package txt2
import (
"fmt"
"testing"
)
// 测试默认迭代器
func TestNewDefaultIterator(t *testing.T) {
data := make(map[string][]byte)
data["K1"] = []byte("v1")
data["K2"] = []byte("v2")
data["K3"] = []byte("v3")
iter := NewDefaultIterator(data)
if iter.length != 3 {
t.Fatal()
}
for iter.Nxet() {
fmt.Printf("%s:%s\n", iter.Key(), string(iter.Value()))
}
}
运行leveldb_test.go结果
代码很多,不懂的建议用AI读一下,
简单来说就是实现一个简单的k-v存储,内存级的。