面试内容:
- 支持设定过期时间,精度到秒
- 支持设定最大内存,当内存超出时做出合适的处理
- 支持并发安全
- 要求按照以下接口实现
SetMemory(size string) bool Set(key string, val interface{}, expire time.Duration) bool Get(key string) (interface{}, bool) Del(key string) bool Exists(key string) bool Flush() bool Keys() int64
下面为具体实现代码:
接口
package cache import "time" type Cache interface { SetMemory(size string) bool Set(key string, val interface{}, expire time.Duration) bool Get(key string) (interface{}, bool) Del(key string) bool Exists(key string) bool Flush() bool Keys() int64 }
实现类
package cache import ( "fmt" "sync" "time" ) type MemCache struct { //最大内存 maxMemorySize int64 // 当前已使用的内存 currMemorySize int64 // 最大内存字符串表示 maxMemorySizeStr string // 缓存键值对 values map[string]*memCacheValue // 读写锁 lock sync.RWMutex //设置清除过期缓存的时间间隔 clearExpireTime time.Duration } type memCacheValue struct { //value 值 val interface{} // 过期时间 expireTime time.Time //有效时间 expire time.Duration //value 大小 size int64 } func NewMemCache() Cache { mc := &MemCache{ clearExpireTime: time.Second * 10, values: make(map[string]*memCacheValue), } go mc.clearExpireItm() return mc } // SetMemory size 1KB 100KB 1M 2M 1GB func (mc *MemCache) SetMemory(size string) bool { mc.maxMemorySize, mc.maxMemorySizeStr = ParseSize(size) return true } // Set 设置缓存 func (mc *MemCache) Set(key string, val interface{}, expire time.Duration) bool { mc.lock.Lock() defer mc.lock.Unlock() v := &memCacheValue{val: val, expireTime: time.Now().Add(expire), expire: expire, size: GetValSize(val)} //mc.values[key] = v mc.del(key) mc.add(key, v) if mc.currMemorySize > mc.maxMemorySize { mc.del(key) panic(fmt.Sprintf("max memory size %d", mc.maxMemorySize)) } return true } func (mc *MemCache) get(key string) (*memCacheValue, bool) { val, ok := mc.values[key] return val, ok } func (mc *MemCache) del(key string) { tmp, ok := mc.get(key) if ok && tmp != nil { mc.currMemorySize -= tmp.size delete(mc.values, key) } } func (mc *MemCache) add(key string, val *memCacheValue) { mc.values[key] = val mc.currMemorySize += val.size } // Get 获取缓存值 func (mc *MemCache) Get(key string) (interface{}, bool) { mc.lock.RLock() defer mc.lock.RUnlock() mcv, ok := mc.get(key) if ok { if mcv.expire != 0 && mcv.expireTime.Before(time.Now()) { mc.del(key) return nil, false } return mcv.val, ok } return nil, false } // Del 删除缓存值 func (mc *MemCache) Del(key string) bool { mc.lock.Lock() defer mc.lock.Unlock() mc.del(key) return true } func (mc *MemCache) Exists(key string) bool { mc.lock.RLock() defer mc.lock.RUnlock() _, ok := mc.get(key) return ok } func (mc *MemCache) Flush() bool { mc.lock.Lock() defer mc.lock.Unlock() mc.values = make(map[string]*memCacheValue, 0) mc.currMemorySize = 0 return true } func (mc *MemCache) Keys() int64 { mc.lock.RLock() defer mc.lock.RUnlock() return int64(len(mc.values)) } func (mc *MemCache) clearExpireItm() { ticker := time.NewTicker(mc.clearExpireTime) defer ticker.Stop() for { select { case <-ticker.C: for key, v := range mc.values { if v.expire != 0 && time.Now().After(v.expireTime) { mc.lock.Lock() mc.del(key) mc.lock.Unlock() } } } } } // //var Cache = NewMemCache() // //func Set(key string, val interface{}) bool { // // return false //}
工具类
package cache import ( "log" "regexp" "strconv" "strings" ) const ( B = 1 << (iota * 10) KB MB GB TB PB ) func ParseSize(size string) (int64, string) { //默认大小为 100M re, _ := regexp.Compile("[0-9]+") unit := string(re.ReplaceAll([]byte(size), []byte(""))) num, _ := strconv.ParseInt(strings.Replace(size, unit, "", 1), 10, 64) unit = strings.ToUpper(unit) var byteNum int64 = 0 switch unit { case "B": byteNum = num break case "KB": byteNum = num * KB break case "MB": byteNum = num * MB break case "GB": byteNum = num * GB break case "TB": byteNum = num * TB break case "PB": byteNum = num * PB break default: num = 0 byteNum = 0 } if num == 0 { log.Println("ParseSize 仅支持B,KB,MB,GB,TB,PB") num = 100 * MB byteNum = num unit = "MB" } sizeStr := strconv.FormatInt(num, 10) + unit return byteNum, sizeStr } func GetValSize(val interface{}) int64 { return 0 }
代理类
package server import ( "go_lang_pro/cache" "time" ) type cacheServer struct { memCache cache.Cache } func NewMemoryCache() *cacheServer { return &cacheServer{ memCache: cache.NewMemCache(), } } func (cs *cacheServer) SetMemory(size string) bool { return cs.memCache.SetMemory(size) } func (cs *cacheServer) Set(key string, val interface{}, expire ...time.Duration) bool { expirets := time.Second * 0 if len(expire) > 0 { expirets = expire[0] } return cs.memCache.Set(key, val, expirets) } func (cs *cacheServer) Get(key string) (interface{}, bool) { return cs.memCache.Get(key) } func (cs *cacheServer) Del(key string) bool { return cs.memCache.Del(key) } func (cs *cacheServer) Exists(key string) bool { return cs.memCache.Exists(key) } func (cs *cacheServer) Flush() bool { return cs.memCache.Flush() } func (cs *cacheServer) Keys() int64 { return cs.memCache.Keys() }
main 方法
package main import ( "go_lang_pro/cache" "time" ) func main() { cache := cache.NewMemCache() cache.SetMemory("100MB") cache.Set("int", 1, time.Second) cache.Set("bool", false, time.Second) cache.Set("data", map[string]interface{}{"a": 1}, time.Second) cache.Get("int") cache.Del("int") cache.Flush() cache.Keys() }
到此这篇关于go实现一个内存缓存系统的示例代码的文章就介绍到这了,更多相关go 内存缓存系统内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!