
离线 TA的专栏
- 打卡等级:无名新人
- 打卡总天数:1
- 打卡月天数:0
- 打卡总奖励:15
- 最近打卡:2024-09-18 11:53:47
|
目录
面试内容:
- 支持设定过期时间,精度到秒
- 支持设定最大内存,当内存超出时做出合适的处理
- 支持并发安全
- 要求按照以下接口实现
- 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 cacheimport "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 内存缓存系统内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:  进行删除处理。
4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
|