redis 缓存策略
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 缓存策略的更多相关文章
- 转:Redis 缓存策略
转:http://api.crap.cn/index.do#/web/article/detail/web/ARTICLE/7754a002-6400-442d-8dc8-e76e72d948ac 目 ...
- Redis缓存策略设计及常见问题
Redis缓存设计及常见问题 缓存能够有效地加速应用的读写速度,同时也可以降低后端负载,对日常应用的开发至关重要.下面会介绍缓存使用技巧和设计方案,包含如下内容:缓存的收益和成本分析.缓存更新策略的选 ...
- mysql+redis缓存策略常见的错误
什么时候应该更新缓存 应该是从数据库读取数据后,再更新缓存,从缓存读取到数据,就不需要再重新写缓存了,一个常见的错误是,每次访问接口都更新缓存,这样的话,如果接口一直有流量,那么db中的数据,就一直没 ...
- Redis缓存策略
常用策略有“求留余数法”和“一致性HASH算法” redis存储的是key,value键值对 一.求留余数法 使用HASH表数据长度对HASHCODE求余数,余数作为索引,使用该余数,直接设置或访问缓 ...
- 在Window系统中使用Redis缓存策略
Redis是一个用的比较广泛的Key/Value的内存数据库,新浪微博.Github.StackOverflow 等大型应用中都用其作为缓存,Redis的官网为http://redis.io/. 最近 ...
- Redis的缓存策略和主键失效机制
作为缓存系统都要定期清理无效数据,就需要一个主键失效和淘汰策略. >>EXPIRE主键失效机制 在Redis当中,有生存期的key被称为volatile,在创建缓存时,要为给定的key设置 ...
- 浅谈一下缓存策略以及memcached 、redis区别
缓存策略三要素:缓存命中率 缓存更新策略 最大缓存容量.衡量一个缓存方案的好坏标准是:缓存命中率.缓存命中率越高,缓存方法设计的越好. 三者之间的关系为:当缓存到达最大的缓存容量时,会触发缓存更 ...
- redis 缓存用户账单策略
最近项目要求分页展示用户账单列表,为提高响应使用redis做缓存,用到的缓存策略和大家分享一下. 需求描述:展示用户账单基本信息以时间倒序排序,筛选条件账单类型(所有,订单收入.提现.充值...). ...
- 缓存策略:redis缓存之springCache
最近通过同学,突然知道服务器的缓存有很多猫腻,这里通过网上查询其他人的资料,进行记录: 缓存策略 比较简单的缓存策略: 1.失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放 ...
随机推荐
- C语言 深入学习
浮点数: x = Mx*2^Ex为一个规格化浮点数,Mx为x的尾数,Ex为x的阶码. 1e-6:表示1 * 10 ^ (-6). 编译时执行: sizeof是运算符(而非函数),在编译时执行,不会导致 ...
- 33 Python 详解命令解析 - argparse--更加详细--转载
https://blog.csdn.net/lis_12/article/details/54618868 Python 详解命令行解析 - argparse Python 详解命令行解析 - arg ...
- 语法对照表ES5VSES6
模块 导入 在ES5里面,如果使用CommonJS的标准,引入包一般是使用require来的 //ES5 js var React = require("react") var { ...
- mysql / sqlserver / oracle 常见数据库分页
空闲时间里用着mysql学习开发测试平台和测试用具, 在公司里将可用的测试平台部署,将数据库换成sqlserver 巴望着能去用oracle的公司 mysql中的分页 limit是mysql的语法se ...
- php格式化数字输出number_format
<?php $num = 4999.944444; $formattedNum = number_format($num).PHP_EOL; echo $formattedNum; $forma ...
- ashx和aspx的区别
1. ashx是一般处理程序,一般返回的数据有两种,一种是html页面,一种是只返回一个字符串. 2. aspx是web窗体程序,每次新建都回自带一个界面和一个后台处理程序. 3. 根据以上两点,可以 ...
- [转]xml解析工具的效率比较QDomDocument、TinyXml-2、RapidXml、PugiXml
转自:http://www.itdaan.com/blog/2017/02/20/301ad47832f4.html 由于windows环境下测试不稳定,博主选择在linux下进行的测试! Qt - ...
- Spark之standalone模式
standalone hdfs:namenode是主节点进程,datanode是从节点进程 yarn:resourcemanager是主节点进程,nodemanager是从节点进程 hdfs和yarn ...
- python Scrapy 常见问题记录
ImportError: No module named win32api 处理办法 windows系统上出现这个问题的解决需要安装Py32Win模块,但是直接通过官网链接装exe会出现几百个错误,更 ...
- Python全栈开发-Day7-面向对象编程2
本节内容: 1.面向对象高级语法部分 1)静态方法.类方法.属性方法 3)类的特殊方法 4)反射 2.异常处理 3.动态导入模块 静态方法 通过@staticmethod装饰器即可把其装饰的方法变为一 ...