面试内容:
- 支持设定过期时间,精度到秒
- 支持设定最大内存,当内存超出时做出合适的处理
- 支持并发安全
- 要求按照以下接口实现
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 内存缓存系统内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论