极客兔兔Gee-Cache Day6

+ `缓存雪崩`:缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。缓存雪崩通常因为缓存服务器宕机、缓存的 key 设置了相同的过期时间等引起。

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

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

+ `day6`实现`singleflight`,为了防止缓存穿透,这里采取的策略是只放一个请求去访问db,其他的请求被go的同步机制`(sync.waitGroup)`阻塞,`call`结构体用于描述单个请求,`Group`结构体管理所有的请求,最后将`singleflight`集成到`gee.Group`中,并在`load()`函数中使用

  + ```go
    package singleflight
    
    import "sync"
    
    // 请求结构体
    type call struct {
    	wg  sync.WaitGroup // 同步信号量
    	val interface{}    // 请求值
    	err error
    }
    
    // 管理所有的请求
    type Group struct {
    	mu sync.Mutex       // 互斥锁
    	m  map[string]*call // 管理每个key对应的请求
    }
    
    func (g *Group) Do(key string, fn func() (interface{}, error)) (interface{}, error) {
    	g.mu.Lock()
    	if g.m == nil {
    		g.m = make(map[string]*call)
    	}
    	if c, ok := g.m[key]; ok { // 当前对这个key的请求已经存在
    		g.mu.Unlock()
    		c.wg.Wait() // 其他的请求会被阻塞在这,等待第一个请求获取值
    		return c.val, c.err
    	}
    
    	c := new(call)
    	c.wg.Add(1)  // 同步信号量
    	g.m[key] = c // 绑定对这个key的请求
    	g.mu.Unlock()
    	c.val, c.err = fn()
    	c.wg.Done() // 已经获取数据,其他请求可以获取这个请求的值
    	g.mu.Lock() // 互斥
    	delete(g.m, key)
    	g.mu.Unlock()
    
    	return c.val, c.err
    }
    ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值