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

相關文章
相關標籤/搜索