gocache

package module
v0.0.0-...-873dfe5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2021 License: Apache-2.0 Imports: 12 Imported by: 1

README

分布式缓存

用go语言实现的一个分布式缓存

TODO
  • LRU缓存淘汰策略
  • 单机并发缓存
  • http客户端及请求支持
  • 实现一致性哈希算法
  • 利用一致性哈希算法,从单一节点走向分布式
  • 缓存击穿,缓存雪崩问题
  • 缓存穿透问题
  • Protobuf通信
  • 支持统计信息展示
  • 其他问题
  • 缓存雪崩:缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。缓存雪崩通常因为缓存服务器宕机、缓存的 key 设置了相同的过期时间等引起。

    解决:不支持过期时间,只维护了一个最近使用的缓存队列,暂时无法解决雪崩问题

  • 缓存击穿:一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到 DB ,造成瞬时DB请求量大、压力骤增。

    解决:使用sync.WaitGroup锁来避免重入,保证并发的时候只有一个请求在工作,详见singlereq/single_req.go的Do()

  • 缓存穿透:查询一个不存在的数据,因为不存在则不会写到缓存中,所以每次都会去请求 DB,如果瞬间流量过大,穿透到 DB,导致宕机。

    解决:布隆过滤器,存一个短期的空值

项目结构 创建流程

脚本测试

运行 /demo 文件下的 run.sh bash run.sh 会编译运行main.go 为可执行文件并执行

#!/bin/zsh
trap "rm server;kill 0" EXIT

go build -o server

./server -port=8001 &
./server -port=8002 &
./server -port=8003 -api=1 &

sleep 2
echo ">>> start test"
curl "http://localhost:9999/api?key=Tom" &
curl "http://localhost:9999/api?key=Tom" &
curl "http://localhost:9999/api?key=Tom" &

wait

然后浏览器访问 http://localhost:9999/api?key=Tom 连接

日志结果如下

2021/01/30 18:51:08 gocache is running at http://localhost:8002
2021/01/30 18:51:08 gocache is running at http://localhost:8001
2021/01/30 18:51:08 gocache is running at http://localhost:8003
2021/01/30 18:51:08 fontend server is running at http://localhost:9999
>>> start test
2021/01/30 18:51:10 http_pool.go:50: [Server http://localhost:8003] pick node http://localhost:8001
2021/01/30 18:51:10 http_pool.go:50: [Server http://localhost:8001] GET /_cache/scores/Tom -- group=scores key=Tom
2021/01/30 18:51:10 main.go:22: [SlowDB] search key Tom
6306306302021/01/30 18:51:46 http_pool.go:50: [Server http://localhost:8003] pick node http://localhost:8001
2021/01/30 18:51:46 http_pool.go:50: [Server http://localhost:8001] GET /_cache/scores/Tom -- group=scores key=Tom
2021/01/30 18:51:46 gocache.go:81: read from local cache 0xc00000e6a0

仅用于学习

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ByteView

type ByteView struct {
	// contains filtered or unexported fields
}

A ByteView holds an immutable view of bytes.

func (ByteView) ByteSlice

func (b ByteView) ByteSlice() []byte

ByteSlice returns a copy of the data as a byte slice.

func (ByteView) Len

func (b ByteView) Len() int

Len returns the view's length

func (ByteView) String

func (b ByteView) String() string

String returns the data as a string, making a copy if necessary.

type DataGetter

type DataGetter interface {
	Get(key string) ([]byte, error)
}

DataGetter 对外回调函数接口 A Getter loads data from DB or etc. for a key.

type GetterFunc

type GetterFunc func(string) ([]byte, error)

定义一个函数类型 F,并且实现接口 A 的方法,然后在这个方法中调用自己。 这是 Go 语言中将其他函数(参数返回值定义与 F 一致)转换为接口 A 的常用技巧。 A GetterFunc implements DataGetter with a function.

func (GetterFunc) Get

func (g GetterFunc) Get(key string) ([]byte, error)

Get implements DataGetter interface function

type Group

type Group struct {
	// contains filtered or unexported fields
}

一个group可以被认为一个缓存的命名空间 每一个group拥有一个唯一的name,这样可以创建多个group

func GetGroup

func GetGroup(name string) *Group

func NewGroup

func NewGroup(name string, cacheBytes int64, getter DataGetter) *Group

func (*Group) Get

func (g *Group) Get(key string) (ByteView, error)

func (*Group) GetCacheBytes

func (g *Group) GetCacheBytes(key string) int64

getLocally 从自定义的回调函数中获取缓存中没有的资源

func (*Group) RegisterPicker

func (g *Group) RegisterPicker(picker NodePicker)

将实现了 NodePicker 接口的 节点选择器 注入到 Group 中

type HTTPPool

type HTTPPool struct {
	// contains filtered or unexported fields
}

HTTPPool implements PeerPicker for a pool of HTTP peers.

func NewHTTPPool

func NewHTTPPool(selfAddr string) *HTTPPool

func (*HTTPPool) Logf

func (p *HTTPPool) Logf(format string, v ...interface{})

print the Log of HTTPPool

func (*HTTPPool) PickNode

func (p *HTTPPool) PickNode(key string) (NodeGetter, bool)

PickNode method picks a node according to key 具体的 key,选择节点,返回节点对应的HTTP处理器(NodeGetter)。

func (*HTTPPool) ServeHTTP

func (p *HTTPPool) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP handle all http requests

func (*HTTPPool) SetNodes

func (p *HTTPPool) SetNodes(nodeKeys ...string)

Set the pool's list of nodes' key. example: key=http://10.0.0.1:9305

type NodeGetter

type NodeGetter interface {
	// 用于从对应 group 查找对应key的缓存值
	HTTPGet(group, key string) ([]byte, error)
	Get(*pb.Request, *pb.Response) error
}

NodeGetter 节点处理器

type NodePicker

type NodePicker interface {
	// 利用一致性哈希算法,根据传入的 key 选择相应节点
	// 并返回节点处理器NodeGetter。
	PickNode(key string) (NodeGetter, bool)
}

NodePicker 节点选择器

Directories

Path Synopsis
demo module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL