Skip to content

Commit

Permalink
注释lru
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] committed May 25, 2020
1 parent cdffce3 commit 75f5c70
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 3 deletions.
2 changes: 1 addition & 1 deletion ReadMe_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ curl localhost:8080/color?name=red
+ consistenthash(提供一致性哈希算法的支持),
+ lru(提供了LRU方式清楚缓存的算法),
+ singleflight(保证了多次相同请求只去获取值一次,减少了资源消耗),
https://segmentfault.com/a/1190000018464029


### 参考资料
+ [《groupcache 设计原理剖析 》](https://www.dazhuanlan.com/2019/12/11/5df07fcb62cae/?__cf_chl_jschl_tk__=e5a47b230d1b9d89eb3887cab036b09f2e3ea621-1590370196-0-AYcPFk14NmbUvag0bCwvLEwPGpXssbJuZhDvEpan7iZiKQi123FXqUvH-LsRSQaov7ybpQtzh-615A-1ZEDC54TuWv_6ZTwsr3zoEwubtJbUbw2J8PTOnzfviGoQB4UWA9Y1ZVzP5QLQ2BCSNlSYxDlegJsosJAV1xJQf06FNkbXPBEAh0SCE29OAzUhpZx1qOKfiUjkI1NNltnexAUoGKVMymm9ocKiWwcq4y_CnUX3xNGz6wyOTmUjQ0RrS1qcQDN8Z-0Jrzn9z1VbzCbEc8R-bdwdkzo7hqaHZ3goA0AQMpxVWxzRjbsy4YIf7vHWEg)
Expand Down
28 changes: 27 additions & 1 deletion lru/lru.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,28 @@ package lru
import "container/list"

// Cache is an LRU cache. It is not safe for concurrent access.
// Cache结构用于实现LRU cache算法;并发访问不安全
type Cache struct {
// MaxEntries is the maximum number of cache entries before
// an item is evicted. Zero means no limit.
// 最大入口数,也就是缓存中最多存几条数据,超过了就触发数据淘汰;0表示没有限制
MaxEntries int

// OnEvicted optionally specifies a callback function to be
// executed when an entry is purged from the cache.
// 销毁前回调
OnEvicted func(key Key, value interface{})

ll *list.List
ll *list.List
// key为任意类型,值为指向链表一个结点的指针
cache map[interface{}]*list.Element
}

// A Key may be any value that is comparable. See http:https://golang.org/ref/spec#Comparison_operators
// 任意可比较类型
type Key interface{}

// 访问入口结构,包装键值
type entry struct {
key Key
value interface{}
Expand All @@ -44,6 +50,7 @@ type entry struct {
// New creates a new Cache.
// If maxEntries is zero, the cache has no limit and it's assumed
// that eviction is done by the caller.
// 初始化一个Cache类型实例
func New(maxEntries int) *Cache {
return &Cache{
MaxEntries: maxEntries,
Expand All @@ -53,36 +60,48 @@ func New(maxEntries int) *Cache {
}

// Add adds a value to the cache.
// 往缓存中增加一个值
func (c *Cache) Add(key Key, value interface{}) {
if c.cache == nil {
c.cache = make(map[interface{}]*list.Element)
c.ll = list.New()
}

// 如果key已经存在,则将记录前移到头部,然后设置value
if ee, ok := c.cache[key]; ok {
c.ll.MoveToFront(ee)
ee.Value.(*entry).value = value
return
}
// key不存在时,创建一条记录,插入链表头部,ele是这个Element的指针
// 这里的Element是一个*entry类型,ele是*list.Element类型
ele := c.ll.PushFront(&entry{key, value})
// cache这个map设置key为Key类型的key,value为*list.Element类型的ele
c.cache[key] = ele
// 链表长度超过最大入口值,触发清理操作
if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries {
c.RemoveOldest()
}
}

// Get looks up a key's value from the cache.
// 链表长度超过最大入口值,触发清理操作
func (c *Cache) Get(key Key) (value interface{}, ok bool) {
if c.cache == nil {
return
}
// 如果存在
if ele, hit := c.cache[key]; hit {
// 将这个Element移动到链表头部
c.ll.MoveToFront(ele)
// 返回entry的值
return ele.Value.(*entry).value, true
}
return
}

// Remove removes the provided key from the cache.
// 如果key存在,调用removeElement删除链表and缓存中的元素
func (c *Cache) Remove(key Key) {
if c.cache == nil {
return
Expand All @@ -93,6 +112,7 @@ func (c *Cache) Remove(key Key) {
}

// RemoveOldest removes the oldest item from the cache.
// 删除最旧的元素
func (c *Cache) RemoveOldest() {
if c.cache == nil {
return
Expand All @@ -104,15 +124,20 @@ func (c *Cache) RemoveOldest() {
}

func (c *Cache) removeElement(e *list.Element) {
// 链表中删除一个element
c.ll.Remove(e)
// e.Value本质是*entry类型,entry结构体就包含了key和value2个属性
// Value本身是interface{}类型,通过类型断言转成*entry类型
kv := e.Value.(*entry)
// 删除cache这个map中key为kv.key这个元素;也就是链表中删了之后缓存中也得删
delete(c.cache, kv.key)
if c.OnEvicted != nil {
c.OnEvicted(kv.key, kv.value)
}
}

// Len returns the number of items in the cache.
// 返回缓存中的item数,通过链表的Len()方法获取
func (c *Cache) Len() int {
if c.cache == nil {
return 0
Expand All @@ -121,6 +146,7 @@ func (c *Cache) Len() int {
}

// Clear purges all stored items from the cache.
// 删除缓存中所有条目,如果有回调函数OnEvicted(),则先调用所有回调函数,然后置空
func (c *Cache) Clear() {
if c.OnEvicted != nil {
for _, e := range c.cache {
Expand Down
4 changes: 3 additions & 1 deletion singleflight/singleflight.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ import "sync"
// call is an in-flight or completed Do call
// 包装一个key获取值锁需要的一些参数
type call struct {
wg sync.WaitGroup
wg sync.WaitGroup
// 实际请求函数
val interface{}
err error
}

// Group represents a class of work and forms a namespace in which
// units of work can be executed with duplicate suppression.
// 主要是用来组织已经存在的对某key的请求和对应的实际请求函数映射
type Group struct {
mu sync.Mutex // protects m
m map[string]*call // lazily initialized
Expand Down

0 comments on commit 75f5c70

Please sign in to comment.