Golang
主页 > 脚本 > Golang >

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

2024-10-18 | 佚名 | 点击:

面试内容:

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

 

}

原文链接:
相关文章
最新更新