// key顺序扫描,常用于数据导出、附近搜索 // 返回的key是面向用户的key,而非内部结构的raw_key func (l *LevelRedis) KeyEnumerate(seek []byte, direction IterDirection, fn func(i int, key, keytype, value []byte, quit *bool)) { var iter *gorocks.Iterator if l.snap != nil { iter = l.db.NewIterator(l.ro) } else { ro := gorocks.NewReadOptions() ro.SetFillCache(false) defer ro.Close() iter = l.db.NewIterator(ro) } defer iter.Close() minkey := joinStringBytes(KEY_PREFIX, SEP_LEFT, string(seek)) maxkey := []byte{MAXBYTE} prefix := joinStringBytes(KEY_PREFIX, SEP_LEFT) l.Enumerate(iter, minkey, maxkey, direction, func(i int, key, value []byte, quit *bool) { if !bytes.HasPrefix(key, prefix) { *quit = true return } left := bytes.Index(key, []byte(SEP_LEFT)) right := bytes.LastIndex(key, []byte(SEP_RIGHT)) if left == -1 || right == -1 { return // just skip } fn(i, key[left+1:right], key[right+1:], value, quit) }) }
// snapshot,快照模式 func NewLevelRedis(db *gorocks.DB, snapshot bool) (l *LevelRedis) { l = &LevelRedis{} l.db = db l.ro = gorocks.NewReadOptions() if snapshot { l.snap = l.db.NewSnapshot() //必须调用Close()释放snap l.ro.SetSnapshot(l.snap) l.ro.SetFillCache(false) l.wo = nil // snapshot模式下禁止写入数据 } else { l.wo = gorocks.NewWriteOptions() } l.counters = map[string]int64{"get": 0, "set": 0, "batch": 0, "del": 0, "enum": 0, "lru_hit": 0, "lru_miss": 0} l.lstring = NewLevelString(l) l.g = newGlobal(l) l.lruCache = lru.NewLRUCache(lruCacheSize) l.mus = make([]sync.Mutex, objCacheCreateThread) // 初始化最大的key,对于Enumerate从后面开始扫描key非常重要 // 使iter.Seek(key)必定Valid=true if !snapshot { maxkey := []byte{MAXBYTE} l.RawSet(maxkey, nil) } return }
func (l *LevelRedis) RangeEnumerate(min, max []byte, direction IterDirection, fn func(i int, key, value []byte, quit *bool)) { var iter *gorocks.Iterator if l.snap != nil { iter = l.db.NewIterator(l.ro) } else { ro := gorocks.NewReadOptions() ro.SetFillCache(false) defer ro.Close() iter = l.db.NewIterator(ro) } defer iter.Close() l.Enumerate(iter, min, max, direction, fn) }