Go重写Redis中间件 - Go实现内存数据库

GO实现内存数据库

前面我们实现了一个简单的回发Redis,这里我们要实现一个真正的Redis内核

实现底层Dict数据结构

新建一个datastruct文件夹,放一些我们要用的数据结构,比如Redis的核心起始就是一个map,再新建一个包实现这个map或者叫字典,字典的底层使用的就是map

dict.go

写一个Dict接口定义一些map要实现的功能,注意ForEach方法的入参是一个方法,把这个方法施加到全部k-v,和Range方法类似

// Consumer is used to traversal dict, if it returns false the traversal will be break
type Consumer func(key string, val interface{}) bool

// Dict is interface of a key-value data structure
type Dict interface {
	Get(key string) (val interface{}, exists bool)        //返回相应key对应的value和key是否存在
	Len() int                                             //字典中有多少个key - value键值对
	Put(key string, val interface{}) (result int)         //将key - value存进dict,存进去回复1,没有存进去回复0
	PutIfAbsent(key string, val interface{}) (result int) //如果没有则存进对应的key - value
	PutIfExists(key string, val interface{}) (result int) //如果有则修改对应的key - value
	Remove(key string) (result int)                       //从字典中删除key - value
	ForEach(consumer Consumer)                            //遍历整个字典,传入的是一个方法
	Keys() []string                                       //列出所有的key
	RandomKeys(limit int) []string                        //随机列一定数量的键
	RandomDistinctKeys(limit int) []string                //随机返回一定数据量不重复的key
	Clear()                                               //清空字典
}

然后就是实现刚才写的接口

sync_dict.go

首先是SyncDict结构体,他的成员只有一个就是sync.Map,然后写一个New方法,RandomKeys方法和RandomDistinctKeys方法实现逻辑上的区别是RandomKeys方法是在for循环里调用Range方法,Range方法里return false,每次for循环只调用一次Range方法,有可能遍历到相同的key,而RandomDistinctKeys方法是return true,直到计数器变量增加到limit时return false,Clear方法不用遍历map一个个删掉,只需要Make一个新的SyncDict,旧的SyncDict由GC做垃圾回收即可

// SyncDict wraps a map, it is not thread safe
type SyncDict struct {
	m sync.Map
}

// MakeSyncDict makes a new map
func MakeSyncDict() *SyncDict {
	return &SyncDict{}
}

// Get returns the binding value and whether the key is exist
func (dict *SyncDict) Get(key string) (val interface{}, exists bool) {
	val, ok := dict.m.Load(key) //Load方法是sync.map的Get方法
	return val, ok
}

// Len returns the number of dict
func (dict *SyncDict) Len() int {
	lenth := 0
	dict.m.Range(func(k, v interface{}) bool {
		lenth++
		return true
	})
	return lenth
}

// Put puts key value into dict and returns the number of new inserted key-value
func (dict *SyncDict) Put(key string, val interface{}) (result int) {
	_, existed := dict.m.Load(key)
	dict.m.Store(key, val)
	if existed {
		return 0 //仅修改,没有插入新的kv
	}
	return 1 //插入新的kv
}

// PutIfAbsent puts value if the key is not exists and returns the number of updated key-value
func (dict *SyncDict) PutIfAbsent(key string, val interface{}) (result int) {
	_, existed := dict.m.Load(key)
	if existed {
		return 0
	}
	dict.m.Store(key, val)
	return 1
}

// PutIfExists puts value if the key is exist and returns the number of inserted key-value
func (dict *SyncDict) PutIfExists(key string, val interface{}) (result int) {
	_, existed := dict.m.Load(key)
	if existed {
		dict.m.Store(key, val)
		return 1
	}
	return 0
}

// Remove removes the key and return the number of deleted key-value
func (dict *SyncDict) Remove(key string) (result int) {
	_, existed := dict.m.Load(key)
	dict.m.Delete(key)
	if existed {
		return 1
	}
	return 0
}

// Keys returns all keys in dict
func (dict *SyncDict) Keys() []string {
	result := make([]string, dict.Len())
	i := 0
	dict.m.Range(func(key, value interface{}) bool {
		result[i] = key.(string)
		i++
		return true
	})
	return result
}

// ForEach traversal the dict
func (dict *SyncDict) ForEach(consumer Consumer) {
	di

你可能感兴趣的:(Go,数据库,redis,中间件)