func InitConsistent(storePath string, persistImpl Persistence, initBP bool) (c *Consistent, err error) {
	var BPNodes []proto.Node
	if initBP {
		if conf.GConf == nil {
			log.Fatal("must call conf.LoadConfig first")
		}
		BPNodes = conf.GConf.SeedBPNodes
	}
	c = &Consistent{
		NumberOfReplicas: 20,
		circle:           make(map[proto.NodeKey]*proto.Node),
		persist:          persistImpl,
	}
	err = c.persist.Init(storePath, BPNodes)
	if err != nil {
		log.WithError(err).Error("init persist BP nodes failed")
		return
	}
	nodes, err := c.persist.GetAllNodeInfo()
	if err != nil {
		log.WithError(err).Error("get all node id failed")
		return
	}
	log.Debugf("c.persist.GetAllNodeInfo: %#v", nodes)
	_, isKMSStorage := c.persist.(*KMSStorage)
	if isKMSStorage {
		for _, n := range nodes[:] {
			c.Add(n)
		}
	} else {
		for _, n := range nodes[:] {
			c.AddCache(n)
		}
	}
	return
}
InitConsistent creates a new Consistent object with a default setting of 20 replicas for each entry.
package consistent
import (
	"errors"
	"expvar"
	"sort"
	"strconv"
	"sync"
	mw "github.com/zserge/metric"
	"github.com/SQLess/SQLess/conf"
	"github.com/SQLess/SQLess/crypto/hash"
	"github.com/SQLess/SQLess/proto"
	"github.com/SQLess/SQLess/utils/log"
)
type NodeKeys []proto.NodeKey
func (x NodeKeys) Len() int { return len(x) }
func (x NodeKeys) Less(i, j int) bool { return x[i].Less(&x[j]) }
func (x NodeKeys) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
var (
	ErrEmptyCircle = errors.New("empty circle")
	ErrKeyNotFound = errors.New("node key not found")
)
const (
	mwKeyDHTNodeCount = "service:DHT:NodeCount"
)
func init() {
	expvar.Publish(mwKeyDHTNodeCount, mw.NewGauge("1M1h"))
}
type Consistent struct {
	circle map[proto.NodeKey]*proto.Node
	sortedHashes     NodeKeys
	NumberOfReplicas int
	persist          Persistence
	cacheLock        sync.RWMutex
	sync.RWMutex
}