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. 测试驱动android

    测试驱动android开发 在安卓模拟器或者真机上跑测试用例速度很慢.构建.部署.启动app,通常需要花费一分钟或者更久.这不是TDD(测试驱动开发)模式.Robolectric提供一种更好的方式. ...

  2. File类文件的常见操作

    boolean exists() 判断文件或者目录是否存在 boolean isFile()  判断是否是文件 boolean isDirectory() 判断是否是目录 String getPath ...

  3. mesh合并

    [风宇冲]Unity3D性能优化:DrawCall优化 (2013-03-05 15:39:27) 转载▼ 标签: it unity unity3d unity3d教程 分类: Unity3d之优化 ...

  4. Windows下pipenv将虚环境文件的位置设置在项目根目录下

    在windows下使用pipenv shell时,虚拟环境文件夹会在C:\Users\Administrator\.virtualenvs\目录下默认创建,为了方便管理,将这个虚环境的文件的位置更改一 ...

  5. 主动触发事件 自定义事件 trigger 及其用法

    1. 触发自定义事件方式 js.jq 2. jq 触发 2.1 默认支持的事件 $('#h').on('click',function(){ $(this).append('<p>p< ...

  6. MYSQL去除"/r/n"

    #去除回车符号/r/n UPDATE t_week_power_line_loss SET `line_loss_rate` = REPLACE( REPLACE( `line_loss_rate` ...

  7. boostrapt的二级下拉菜单

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <meta conte ...

  8. 安卓自动化测试——rf

    ${a} Get Text //android.widget.TextView[contains(@text,"历史位置")]/../../../android.widget.Li ...

  9. 如何在windows下安装与配置Appium

    appium是一款open source 移动自动化测试框架,既支持Android 也支持IOS 工具/原料 JDK adt-bundle-windows node python appium rob ...

  10. Python pickle使用

    2019-01-15 10:04:32 用于序列化的两个模块 json:用于字符串和Python数据类型间进行转换 pickle: 用于python特有的类型和python的数据类型间进行转换 jso ...