import (
"fmt"
"github.com/allegro/bigcache"
"github.com/kooksee/usmint/cmn"
"github.com/pingcap/tidb/store/tikv"
"github.com/tendermint/tendermint/libs/log"
"os"
"time"
) var Name = "txs" var tdb *TikvStore func Init(logger log.Logger) {
tikv.MaxConnectionCount = 256 url := os.Getenv("TIKV")
if url == "" {
panic("please init tikv url")
} store, err := tikv.Driver{}.Open(fmt.Sprintf("tikv://%s/pd", url))
cmn.MustNotErr("TikvStore Init Error", err) cache, err := bigcache.NewBigCache(bigcache.DefaultConfig(30 * time.Minute))
if err != nil {
panic(fmt.Sprintf("init cache error: %s ", err.Error()))
} tdb = &TikvStore{
name: []byte(Name),
c: store,
cache: cache,
}
} func GetDb() *TikvStore {
if tdb == nil {
panic("please init usdb")
}
return tdb
} import (
"bytes"
"context"
"fmt"
"github.com/allegro/bigcache"
"github.com/kooksee/usmint/cmn"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/store/tikv"
"github.com/tendermint/tendermint/libs/db"
) type TikvStore struct {
db.DB
name []byte
c kv.Storage
cache *bigcache.BigCache
} func NewTikvStore(name, url string) *TikvStore {
tikv.MaxConnectionCount = 256 // tikv://etcd-node1:port,etcd-node2:port?cluster=1&disableGC=false
store, err := tikv.Driver{}.Open(fmt.Sprintf("tikv://%s/pd", url))
cmn.MustNotErr("NewTikvStore Error", err)
return &TikvStore{
name: []byte(name),
c: store,
}
} func (db *TikvStore) withPrefix(key []byte) []byte {
return append(db.name, key...)
} func (db *TikvStore) withTxn(fn func(txn kv.Transaction) error) {
txn, err := db.c.Begin()
cmn.MustNotErr("tikv store open tx error", err)
if err := fn(txn); err != nil && !kv.IsErrNotFound(fn(txn)) {
cmn.MustNotErr("tikv store exec tx error", err)
} cmn.MustNotErr("tikv store exec tx error", fn(txn))
defer txn.Rollback()
cmn.MustNotErr("tikv store commit tx error", txn.Commit(context.TODO()))
} func (db *TikvStore) getSnapshot() kv.Snapshot {
ss, err := db.c.GetSnapshot(kv.MaxVersion)
cmn.MustNotErr("tikv store GetSnapshot error", err)
return ss
} // Implements DB.
func (db *TikvStore) Get(key []byte) []byte {
k := db.withPrefix(key) rt, err := db.cache.Get(string(k))
if err == nil && len(rt) != 0 {
return rt
} ret, err := db.getSnapshot().Get(k)
if !kv.IsErrNotFound(err) {
cmn.MustNotErr("tikv store Get error", err)
} if err := db.cache.Set(string(k), ret); err != nil {
cmn.Log().Error("cache set error", "err", err)
} return ret
} // Implements DB.
func (db *TikvStore) Has(key []byte) bool {
ret, err := db.getSnapshot().Get(db.withPrefix(key))
return (!kv.IsErrNotFound(err)) && (len(ret) != 0)
} // Implements DB.
func (db *TikvStore) Set(key []byte, value []byte) {
k := db.withPrefix(key) db.withTxn(func(txn kv.Transaction) (err error) {
if err := db.cache.Set(string(k), value); err != nil {
cmn.Log().Error("cache error", "err", err)
}
return txn.Set(k, value)
})
} // Implements DB.
func (db *TikvStore) SetSync(key []byte, value []byte) {
db.Set(key, value)
} // Implements DB.
func (db *TikvStore) Delete(key []byte) {
db.withTxn(func(txn kv.Transaction) (err error) {
return txn.Delete(db.withPrefix(key))
})
} // Implements DB.
func (db *TikvStore) DeleteSync(key []byte) {
db.Delete(key)
} // Implements DB.
func (db *TikvStore) Close() {
cmn.MustNotErr("TikvStore Close Error", db.c.Close())
} // Implements DB.
func (db *TikvStore) Print() {
} // Implements DB.
func (db *TikvStore) Stats() map[string]string {
//keys := []string{
// "leveldb.num-files-at-level{n}",
// "leveldb.stats",
// "leveldb.sstables",
// "leveldb.blockpool",
// "leveldb.cachedblock",
// "leveldb.openedtables",
// "leveldb.alivesnaps",
// "leveldb.aliveiters",
//} return make(map[string]string)
} //----------------------------------------
// Batch // Implements DB.
func (db *TikvStore) NewBatch() db.Batch {
return &tikvStoreBatch{data: make(map[string][]byte), db: db}
} type tikvStoreBatch struct {
db *TikvStore
data map[string][]byte
} // Implements Batch.
func (m *tikvStoreBatch) Set(key, value []byte) {
m.data[string(key)] = value
} // Implements Batch.
func (m *tikvStoreBatch) Delete(key []byte) {
delete(m.data, string(key))
} // Implements Batch.
func (m *tikvStoreBatch) Write() {
m.db.withTxn(func(txn kv.Transaction) error {
for k, v := range m.data {
if err := txn.Set([]byte(k), v); err != nil {
return err
}
}
return nil
})
} // Implements Batch.
func (m *tikvStoreBatch) WriteSync() {
m.Write()
} //----------------------------------------
// Iterator
// NOTE This is almost identical to db/c_level_db.Iterator
// Before creating a third version, refactor. // Implements DB.
func (db *TikvStore) Iterator(start, end []byte) db.Iterator {
it, err := db.getSnapshot().Seek(db.withPrefix(start))
cmn.MustNotErr("TikvStore Iterator Error", err)
return newTikvStoreIterator(db.name, false, it, db.withPrefix(start), db.withPrefix(end))
} // Implements DB.
func (db *TikvStore) ReverseIterator(start, end []byte) db.Iterator {
it, err := db.getSnapshot().SeekReverse(db.withPrefix(start))
cmn.MustNotErr("TikvStore ReverseIterator Error", err)
return newTikvStoreIterator(db.name, true, it, db.withPrefix(start), db.withPrefix(end))
} type tikvStoreIterator struct {
db.Iterator name []byte
r kv.Iterator
reverse bool
start []byte
end []byte
} func newTikvStoreIterator(name []byte, reverse bool, r kv.Iterator, start, end []byte) *tikvStoreIterator {
return &tikvStoreIterator{
name: name,
r: r,
reverse: reverse,
start: start,
end: end,
}
} // Implements Iterator.
func (itr *tikvStoreIterator) Domain() ([]byte, []byte) {
return itr.start, itr.end
} // Implements Iterator.
func (itr *tikvStoreIterator) Valid() bool {
if !itr.r.Valid() {
return false
} if !itr.reverse {
if bytes.Compare(itr.r.Key(), itr.end) > 0 {
return false
}
} else {
if bytes.Compare(itr.r.Key(), itr.start) < 0 {
return false
}
} return true
} // Implements Iterator.
func (itr *tikvStoreIterator) Key() []byte {
return bytes.TrimPrefix(itr.r.Key(), itr.name)
} // Implements Iterator.
func (itr *tikvStoreIterator) Value() []byte {
return itr.r.Value()
} // Implements Iterator.
func (itr *tikvStoreIterator) Next() {
cmn.MustNotErr("tikvStoreIterator next error", itr.r.Next())
} // Implements Iterator.
func (itr *tikvStoreIterator) Close() {
itr.r.Close()
}

tendermint 跟tikv结合的更多相关文章

  1. TIKV副本一致性检查机制分析

    背景 TIKV使用raft协议来实现副本同步,任何时刻写入一个KEY-VAL键值对,都会基于RAFT协议复制到不同机器的三个副本上,raft协议本身能保证副本同步的强一致性,但是任何系统都可能存在BU ...

  2. PBFT概念与Go语言入门(Tendermint基础)

    Tendermint作为当前最知名且实用的PBFT框架,网上资料并不很多,而实现Tendermint和以太坊的Go语言,由于相对小众,也存在资料匮乏和模糊错漏的问题.本文简单介绍PBFT概念和Go语言 ...

  3. TiKV 源码解析系列文章(三)Prometheus(上)

    本文为 TiKV 源码解析系列的第三篇,继续为大家介绍 TiKV 依赖的周边库 rust-prometheus,本篇主要介绍基础知识以及最基本的几个指标的内部工作机制,下篇会介绍一些高级功能的实现原理 ...

  4. Tidb进行缩减扩容tikv节点

    这两天接到任务说是要进行测试缩减机器给集群带来的负面效果有哪些. 然后我就按照官方的教程将机器进行了缩减,主要是缩减tikv节点 我们先来看看官方的文章是怎么写的: 步骤都没有什么问题,就是进行到第二 ...

  5. Tidb缩减tikv机器

    生产环境下,如何缩减机器? 1.首先是检查出来那个tikv节点需要缩减 " -d store { ", "stores": [ { "store&qu ...

  6. tikv性能参数调优

    tiKV 最底层使用的是 RocksDB(tidb3.0版本中将使用tian存储引擎) 做为持久化存储,所以 TiKV 的很多性能相关的参数都是与 RocksDB 相关的.TiKV 使用了两个 Roc ...

  7. TiKV 源码解析系列——如何使用 Raft

    本系列文章主要面向 TiKV 社区开发者,重点介绍 TiKV 的系统架构,源码结构,流程解析.目的是使得开发者阅读之后,能对 TiKV 项目有一个初步了解,更好的参与进入 TiKV 的开发中. 需要注 ...

  8. TiKV 源码解析系列 - Raft 的优化

    本系列文章主要面向 TiKV 社区开发者,重点介绍 TiKV 的系统架构,源码结构,流程解析.目的是使得开发者阅读之后,能对 TiKV 项目有一个初步了解,更好的参与进入 TiKV 的开发中.本文是本 ...

  9. tikv 安装

    export HostIP="127.0.0.1" docker run -d -p 2379:2379 -p 2380:2380 --name pd pingcap/pd \ - ...

随机推荐

  1. iOS:通信录(完成)(18-01-18更)

    1.读取通信录 1).9.0以前:AddressBook 2).9.0以后:Contacts 2.调用通信录UI(不弄) 1).9.0以前:AddressBookUI 2).9.0以后:Contact ...

  2. iOS App占用太多磁盘空间

    问题:随着App的不断运行,发现所占磁盘空间越来越大 分析:应该是网络下载中的缓存,包括利用SDWebImage产生的.和下载单个文件被取消后的缓存 验证:查看App目录中的Tmp(系统存放未下载完成 ...

  3. 【leetcode】804

    import java.util.*; import java.lang.*; public class Test{ public static int fun_solve(String[] word ...

  4. vue+element 点击按钮后 导致 刷新页面 致url中拼接 ? 或者拼接参数

    https://blog.csdn.net/sinat_37255207/article/details/88917162 element 自己的<el-form></el-form ...

  5. $.trim() 去除空格方法 (验证使用)

  6. json数组按照日期先后排序

    var allMyApp = [ {"startDate": "2018-07-07 12:30:00",'name':'aa'}, {"startD ...

  7. decodeURI、decodeURIComponent 编码方法

    ——摘自<JavaScript高级程序设计> 编码: Global 对象的 encodeURI()和 encodeURIComponent()方法可以对 URI(Uniform Resou ...

  8. html表单相关标签及属性

    1.<form>标签 定义整体的表单区域 action属性 定义表单数据提交地址 method属性 定义表单提交的方式,一般有“get”方式和“post”方式 2.<label> ...

  9. JavaScript中使用比较多的两种创建对象的方式

    1.使用组合模式创建对象 原型模式创建对象适合封装方法,构造方法模式创建对象适合封装属性 组合方法缺点:将构造方法和原型分开写 <script type="text/javascrip ...

  10. 实现一个 RESTful API 服务器

    RESTful 是目前最为流行的一种互联网软件结构.因为它结构清晰.符合标准.易于理解.扩展方便,所以正得到越来越多网站的采用. 什么是 REST REST(REpresentational Stat ...