您的位置:首页 > 数据库 > Redis

Dogpile效应以及solution

2016-06-18 23:19 811 查看
Redis/Memcached高并发访问下的缓存失效时可能产生Dogpile效应(Cache
Stampede效应)。看代码:

# redis read-through cache
conn = redis.Redis()
data = conn.get('cachekey')
if not data:
# long-running process
data = generateData()
conn.setex('cachekey', data, 10)


Dogpile
产生情况:

generateData()是耗时的运算过程或者复杂的数据库操作。当缓存失效或者redis-server不可用(服务器宕机/网络原因),此时恰好有大量的请求涌入,会直接穿透cache层从而导致CPU使用率或者数据库操作数短时间急剧攀升,可能会引发数据库/web服务器故障。

Solution:

1.      使用独立的进程\线程更新cache

实践:web应用中启动调度线程;单独进程Job(spring-boot)

// every ten seconds

@Scheduled(cron = "*/10 * * * * *")

现在我们的应用就是基于这样的方案,可靠,经历618考验^_^。

2.      使用”锁”

实践:cache失效,单一请求,其余等待;单一请求cache失效前更新

# redis read-through cache
conn = redis.Redis()

def get(key):
data = conn.get(key)
if data:
return data
# try lock
if conn.setnx('lock:' + key, 'locked'):
# long-running process
data = generateData()
conn.setex(key, data, 10)
conn.delete('lock:' + key)
return data
else:
# 'waiting & try get'
loop = 10
while loop > 0:
time.sleep(0.1)
data = conn.get(key)
if data:
print 'found'
return data
loop -= 1
return None

或者是

# redis read-through cache
conn = redis.Redis()

def get(key):
recache = 2
data = conn.get(key)
ttl = conn.ttl(key)

if ttl < recache and conn.setnx('lock:' + key, 'locked'):
print 'recache'
# long-running process
data = generateData()
conn.setex(key, data, 10)
conn.delete('lock:' + key)
# normal return
return data


这两者各有优势,看具体业务选取。我们应用涉及到实时或者重定向的功能采用的是第一种锁。
另外:按照具体的使用确定是否要对锁的冲突和异常进行特殊处理,代码中没有实现。

参考(力荐):http://www.linuxidc.com/Linux/2013-07/86960.htm (关于这次项目的实践,上线后才看到这篇文章,相见恨晚。本文只做实践,详解看这篇推荐。)

618值班顺利
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  缓存 redis dogpile python