Golang校招简历项目-简单的分布式缓存

前言

前段时间,校招投了golang岗位,可是没什么好的项目往简历上写,因而参考了许多网上资料,作了一个简单的分布式缓存项目。
如今闲下来了,打算整理下。html

github项目地址:https://github.com/Jun10ng/Gache
里面还有我整理的一些面试问题,给颗星吧。java


typora-root-url: ./git


Golang校招面试项目-类redis分布式缓存

实现一个分布式缓存,功能有:LRU淘汰策略,http调用,并发缓存,一致性哈希,分布式节点,防止缓存击穿github

实现LRU淘汰策略

LRU的数据结构大体以下,上层是一个map,key是数据对象的key值,而value值则是指向 下层双向链表的节点,在双向链表中,每一个节点存储的元素是完整的数据对象,包含key值和value。golang

  • get:存在->将元素所在节点提到最前面,不存在->返回失败
  • add:存在->更新,不存在->增长;将元素所在节点提到最前面,判断是否大于maxSize
  • removeOldest:删除链表最后方的节点

代码实现

具体代码实现看:https://github.com/Jun10ng/Gache/tree/master/lru面试

定义了三个数据结构redis

Value是golang中的接口类型,能够理解为java中的Object类,是一个能“兜底”全部数据结构的数据类型。数据库

entry是一个双向链表存储的数据结构缓存

Cache则是lru核心数据结构,包含一个哈希表和一个双向链表数据结构

type Value interface {

	//返回占用的内存大小
	Len() int
}

type entry struct {
	key string
	value Value
}

type Cache struct {
	//容许使用的最大内存
	maxBytes int64

	//当前已使用的内存
	nbytes int64


	ll *list.List

	cache map[string] *list.Element

	//某条记录被移除时的回调函数,能够是nil
	OnEvicted func(key string, value Value)

}

这里说一下OnEvicted成员,这是一个函数对象,他的做用是,在缓存中没有须要的数据对象时,咱们须要去原始数据源获取,(redis中没有,就须要去数据库中获取),可是数据源不惟一,有时候是数据库,有时候是磁盘,有时候是表格,他们的获取方式都不相同,因此OnEvicted成员传入的函数,就是自定义的获取方法。

实现单机并发

具体代码实现:https://github.com/Jun10ng/Gache/blob/master/cache.go

上文实现的LRU数据结构并不支持并发,须要加锁来实现并发,因此使用sync.Mutex,在LRU数据结构上封装,使之实现并发功能。

type cache struct {
	mu sync.Mutex
	lru *lru.Cache
	cacheBytes int64
}

cache并无new方法,由于采用的是延迟初始化 在add方法中,判断c.lru是否为nil,若是等于nil再建立 这种方法称为延迟初始化,一个对象的延迟初始化意味着该对象的 建立将会延迟至第一次使用该对象时。 这个方法在redis中很常见,由于能必定程度上提升性能

func (c *cache) add(key string, value ByteView){
	c.mu.Lock()
	defer c.mu.Unlock()
	if c.lru == nil{
		c.lru = lru.New(c.cacheBytes,nil)
	}
	c.lru.Add(key,value)
}

主体结构

具体代码实现:https://github.com/Jun10ng/Gache/blob/master/gache.go

本质上是再进行一次封装

难道一台机器就只有一个缓存表吗?你打开redis的可视化工具,能看到redis还有16个池呢,因此咱们要实现多个缓存表。怎么作?再加一层。试想一下:

//groups 实例集合表
groups = make(map[string]*Group)

咱们要实现的数据结构大体是这样的,是一个存储并发cache的表,这是本项目的核心结构

//这里的group是实例
type Group struct {
	name string
	getter Getter
	mainCache cache
}

http服务调用

具体代码实现:https://github.com/Jun10ng/Gache/blob/master/http.go

当请求URL具备前缀/_Gache/时,则认为该请求为缓存调用。

约定的请求URL为:http://XXX.com/_Gache/<groupname>/<key>

groupname字段为主体结构中groups中的某个元素的name值,由此调用。key字段为元素中的元素的key值,因此最后逻辑为

groups[groupname][key]

TODo

一致性哈希
分布式节点

主要参考资料:https://geektutu.com/post/geecache.html

相关文章
相关标签/搜索