redis 缓存策略
配置项:
maxmemory <bytes>
maxmemory-policy noeviction

触发时机:每次执行命令(processCommand)的时候会检测

while 循环条件是 (mem_freed < mem_tofree),每次选择一个 bestkey 进行删除。

1. 确定 dict
如果是 MAXMEMORY_ALLKEYS_LRU, MAXMEMORY_ALLKEYS_RANDOM
使用 dict 键空间
否则使用 expires 空间

2. 确定 bestkey
如果是 MAXMEMORY_ALLKEYS_RANDOM 或 MAXMEMORY_VOLATILE_RANDOM
随机选取一个 key 作为 bestkey

如果是 MAXMEMORY_ALLKEYS_LRU 或 MAXMEMORY_VOLATILE_LRU
随机取 maxmemory_samples 个键,选一个 idletime 最长的键作为 bestkey

如果是 MAXMEMORY_VOLATILE_TTL
随机取 maxmemory_samples 个键,选一个过期时间最小的键作为 bestkey

int freeMemoryIfNeeded(void) {
size_t mem_used, mem_tofree, mem_freed;
int slaves = listLength(server.slaves);
mstime_t latency, eviction_latency; /* Remove the size of slaves output buffers and AOF buffer from the
* count of used memory. */
mem_used = zmalloc_used_memory();
if (slaves) {
listIter li;
listNode *ln; listRewind(server.slaves,&li);
while((ln = listNext(&li))) {
client *slave = listNodeValue(ln);
unsigned long obuf_bytes = getClientOutputBufferMemoryUsage(slave);
if (obuf_bytes > mem_used)
mem_used = ;
else
mem_used -= obuf_bytes;
}
}
if (server.aof_state != AOF_OFF) {
mem_used -= sdslen(server.aof_buf);
mem_used -= aofRewriteBufferSize();
} /* Check if we are over the memory limit. */
if (mem_used <= server.maxmemory) return C_OK; if (server.maxmemory_policy == MAXMEMORY_NO_EVICTION)
return C_ERR; /* We need to free memory, but policy forbids. */ /* Compute how much memory we need to free. */
mem_tofree = mem_used - server.maxmemory;
mem_freed = ;
latencyStartMonitor(latency);
while (mem_freed < mem_tofree) {
int j, k, keys_freed = ; for (j = ; j < server.dbnum; j++) {
long bestval = ; /* just to prevent warning */
sds bestkey = NULL;
dictEntry *de;
redisDb *db = server.db+j;
dict *dict; if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_LRU ||
server.maxmemory_policy == MAXMEMORY_ALLKEYS_RANDOM)
{
dict = server.db[j].dict;
} else {
dict = server.db[j].expires;
}
if (dictSize(dict) == ) continue; /* volatile-random and allkeys-random policy */
if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_RANDOM ||
server.maxmemory_policy == MAXMEMORY_VOLATILE_RANDOM)
{
de = dictGetRandomKey(dict);
bestkey = dictGetKey(de);
} /* volatile-lru and allkeys-lru policy */
else if (server.maxmemory_policy == MAXMEMORY_ALLKEYS_LRU ||
server.maxmemory_policy == MAXMEMORY_VOLATILE_LRU)
{
struct evictionPoolEntry *pool = db->eviction_pool; while(bestkey == NULL) {
evictionPoolPopulate(dict, db->dict, db->eviction_pool);
/* Go backward from best to worst element to evict. */
for (k = MAXMEMORY_EVICTION_POOL_SIZE-; k >= ; k--) {
if (pool[k].key == NULL) continue;
de = dictFind(dict,pool[k].key); /* Remove the entry from the pool. */
sdsfree(pool[k].key);
/* Shift all elements on its right to left. */
memmove(pool+k,pool+k+,
sizeof(pool[])*(MAXMEMORY_EVICTION_POOL_SIZE-k-));
/* Clear the element on the right which is empty
* since we shifted one position to the left. */
pool[MAXMEMORY_EVICTION_POOL_SIZE-].key = NULL;
pool[MAXMEMORY_EVICTION_POOL_SIZE-].idle = ; /* If the key exists, is our pick. Otherwise it is
* a ghost and we need to try the next element. */
if (de) {
bestkey = dictGetKey(de);
break;
} else {
/* Ghost... */
continue;
}
}
}
} /* volatile-ttl */
else if (server.maxmemory_policy == MAXMEMORY_VOLATILE_TTL) {
for (k = ; k < server.maxmemory_samples; k++) {
sds thiskey;
long thisval; de = dictGetRandomKey(dict);
thiskey = dictGetKey(de);
thisval = (long) dictGetVal(de); /* Expire sooner (minor expire unix timestamp) is better
* candidate for deletion */
if (bestkey == NULL || thisval < bestval) {
bestkey = thiskey;
bestval = thisval;
}
}
} /* Finally remove the selected key. */
if (bestkey) {
long long delta; robj *keyobj = createStringObject(bestkey,sdslen(bestkey));
propagateExpire(db,keyobj);
/* We compute the amount of memory freed by dbDelete() alone.
* It is possible that actually the memory needed to propagate
* the DEL in AOF and replication link is greater than the one
* we are freeing removing the key, but we can't account for
* that otherwise we would never exit the loop.
*
* AOF and Output buffer memory will be freed eventually so
* we only care about memory used by the key space. */
delta = (long long) zmalloc_used_memory();
latencyStartMonitor(eviction_latency);
dbDelete(db,keyobj);
latencyEndMonitor(eviction_latency);
latencyAddSampleIfNeeded("eviction-del",eviction_latency);
latencyRemoveNestedEvent(latency,eviction_latency);
delta -= (long long) zmalloc_used_memory();
mem_freed += delta;
server.stat_evictedkeys++;
notifyKeyspaceEvent(NOTIFY_EVICTED, "evicted",
keyobj, db->id);
decrRefCount(keyobj);
keys_freed++; /* When the memory to free starts to be big enough, we may
* start spending so much time here that is impossible to
* deliver data to the slaves fast enough, so we force the
* transmission here inside the loop. */
if (slaves) flushSlavesOutputBuffers();
}
}
if (!keys_freed) {
latencyEndMonitor(latency);
latencyAddSampleIfNeeded("eviction-cycle",latency);
return C_ERR; /* nothing to free... */
}
}
latencyEndMonitor(latency);
latencyAddSampleIfNeeded("eviction-cycle",latency);
return C_OK;
}

redis 缓存策略的更多相关文章

  1. 转:Redis 缓存策略

    转:http://api.crap.cn/index.do#/web/article/detail/web/ARTICLE/7754a002-6400-442d-8dc8-e76e72d948ac 目 ...

  2. Redis缓存策略设计及常见问题

    Redis缓存设计及常见问题 缓存能够有效地加速应用的读写速度,同时也可以降低后端负载,对日常应用的开发至关重要.下面会介绍缓存使用技巧和设计方案,包含如下内容:缓存的收益和成本分析.缓存更新策略的选 ...

  3. mysql+redis缓存策略常见的错误

    什么时候应该更新缓存 应该是从数据库读取数据后,再更新缓存,从缓存读取到数据,就不需要再重新写缓存了,一个常见的错误是,每次访问接口都更新缓存,这样的话,如果接口一直有流量,那么db中的数据,就一直没 ...

  4. Redis缓存策略

    常用策略有“求留余数法”和“一致性HASH算法” redis存储的是key,value键值对 一.求留余数法 使用HASH表数据长度对HASHCODE求余数,余数作为索引,使用该余数,直接设置或访问缓 ...

  5. 在Window系统中使用Redis缓存策略

    Redis是一个用的比较广泛的Key/Value的内存数据库,新浪微博.Github.StackOverflow 等大型应用中都用其作为缓存,Redis的官网为http://redis.io/. 最近 ...

  6. Redis的缓存策略和主键失效机制

    作为缓存系统都要定期清理无效数据,就需要一个主键失效和淘汰策略. >>EXPIRE主键失效机制 在Redis当中,有生存期的key被称为volatile,在创建缓存时,要为给定的key设置 ...

  7. 浅谈一下缓存策略以及memcached 、redis区别

    缓存策略三要素:缓存命中率   缓存更新策略  最大缓存容量.衡量一个缓存方案的好坏标准是:缓存命中率.缓存命中率越高,缓存方法设计的越好. 三者之间的关系为:当缓存到达最大的缓存容量时,会触发缓存更 ...

  8. redis 缓存用户账单策略

    最近项目要求分页展示用户账单列表,为提高响应使用redis做缓存,用到的缓存策略和大家分享一下. 需求描述:展示用户账单基本信息以时间倒序排序,筛选条件账单类型(所有,订单收入.提现.充值...). ...

  9. 缓存策略:redis缓存之springCache

    最近通过同学,突然知道服务器的缓存有很多猫腻,这里通过网上查询其他人的资料,进行记录: 缓存策略 比较简单的缓存策略: 1.失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放 ...

随机推荐

  1. 新建DataTable添加列添加行

    新建空Table添加行和列 DataTable dt = new DataTable(); //创建空DataTable 1.添加列 dt.Columns.Add("序号", ty ...

  2. 【BZOJ】1832: [AHOI2008]聚会

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1832 省选出出了CF的感觉..... 显然一发贪心,如果两个点显然就是他们的$LCA$(不 ...

  3. 将.db文件导入SQLServer2008数据库

    最近要做一个项目,需要连接数据库,给我的数据文件是sqlite,我需要将数据导入到SQLServer数据库 需要借助一个软件:DBDBMigration 页面最上方的选择框内,先选择数据文件类型,这里 ...

  4. PostMan做接口自动化测试

    try{ var jsonData = pm.response.json(); } catch (e) { console.log("No body"); } pm.environ ...

  5. CentOS6.5下搭建Samba服务实现与Windows系统之间共享文件资源

    FTP文件传输服务确实可以让主机之间的文件传输变得简单方便,但是FTP协议的本质是传输文件,而非共享文件,因此要想通过客户端直接在服务器上修改文件内容还是一件比较麻烦的事情. 1987年,微软公司和英 ...

  6. python web py安装与简单使用

    web.py是一个轻量级的python web框架,简单而且功能强大.相对flask和Django,web.py更适合初学者来学习和了解web开发的基础知识.   安装: pip install we ...

  7. SpringBoot整合Graylog3.0

    Graylog简介 Graylog是一个开源的完整的日志管理工具,功能和ELK类似,安装部署更方便. 官方网站 https://www.graylog.org 搭建 使用docker快速搭建 参考 h ...

  8. python入门知识点(上)

    1.硬件系统: 主机部分: 1.中央处理器(CPU): 电脑的大脑 运算器: 数值计算和逻辑判断 控制器: 可以电脑中的各个部件协同工作 2.内部存储器: 随机存储器:内存条 使用电信号表示数据; 特 ...

  9. C语言流控制命令的总结

    C语言流控制命令的总结 基本概念: C语言中,自顶向下的的代码的流程叫做程序流. 能够改变程序流顺序的语句叫做流控制命令. 我为什么要写这篇文章 在学习C语言的过程中,经常会用到条件语句和循环语句这些 ...

  10. Struts2框架之类型转换 --Struts2框架

    Struts2框架实现了大多数常见的用于类型转换的转换器,开发人员不用自己编写类型转换代码,就可以实现数据类型的转换.下面一个Struts2框架类型转换的简单事例, 本例可在使用validate()方 ...