广告位联系
返回顶部
分享到

go实现一个内存缓存系统的代码

Golang 来源:互联网 作者:佚名 发布时间:2024-10-18 22:38:01 人浏览
摘要

面试内容: 支持设定过期时间,精度到秒 支持设定最大内存,当内存超出时做出合适的处理 支持并发安全 要求按照以下接口实现 1 2 3 4 5 6 7 SetMemory(size string) bool Set(key string, val interface{}, ex

面试内容:

  • 支持设定过期时间,精度到秒
  • 支持设定最大内存,当内存超出时做出合适的处理
  • 支持并发安全
  • 要求按照以下接口实现

1

2

3

4

5

6

7

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

下面为具体实现代码:

接口

1

2

3

4

5

6

7

8

9

10

11

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

}

实现类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

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

//}

工具类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

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

}

代理类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

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 方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

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()

 

}


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • golang并发编程使用Select语句的实现介绍
    在 Go 语言中,select语句是一种控制结构,允许一个 Goroutine 同时等待多个通道操作。select语句会阻塞,直到其中的一个case可以继续执行,然
  • go语言time.After()的作用介绍
    time.After是一个非常实用的函数,它返回一个用于读取的单向通道(-chan time.Time),这个通道会在指定的时间间隔之后发送当前时间。这个机
  • go实现一个内存缓存系统的代码
    面试内容: 支持设定过期时间,精度到秒 支持设定最大内存,当内存超出时做出合适的处理 支持并发安全 要求按照以下接口实现 1 2 3 4
  • Golang Map简介以及底层原理介绍
    在Go语言中提供了map数据结构来存储键值对数据。map的数据类型为map[K]V,其中K为键的类型,V为值的类型。map的键类型必须支持==操作符,用
  • Go语言中的switch高级用法介绍
    最近翻开源代码的时候看到了一种很有意思的switch用法,分享一下。 注意这里讨论的不是typed switch,也就是case语句后面是类型的那种。 直
  • Go语言sync.Map介绍及使用场景
    在 Go 语言中,sync.Map是一个并发安全的映射结构,专门用于在高并发场景下处理键值对数据。它的并发安全是通过内部实现机制来保证的,
  • 怎么使用工具自动监测SSL证书有效期并发送提醒
    自从云厂商的免费ssl证书改成3个月,而且证书数量还是20个之后,自己网站的ssl证书就换成了其它免费方案。但是免费方案不会提醒证书过
  • Go语言字符串处理库strings包介绍

    Go语言字符串处理库strings包介绍
    Golang字符串处理库strings 在Go语言中,strings包是一个非常重要且功能丰富的标准库,它提供了一系列用于操作字符串的函数。从基本的字符串
  • Go语言中的指针的使用介绍
    1、Go 语言中指针的介绍 1.1、什么是指针? 指针是一种变量,它存储了另一个变量的内存地址。在 Go 中,你可以通过取地址操作符获取变量
  • Go环境变量配置,及GOROOT、GOPATH的区别

    Go环境变量配置,及GOROOT、GOPATH的区别
    一、安装Go go下载地址: https://golang.google.cn/dl/ windows下载安装,有两种方式。解压和直接安装 方式一:直接下载安装包。以.msi结尾的文件。
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计