Redis4.0新特性之-大KEY删除
接上一篇,我们得知了redis中存在大KEY,那么这个大KEY如何删除呢?本文将从源码角度分析Redis4.0带来的新特性。
在Redis中,对于大KEY的删除一直是个比较头疼的问题,为了不影响服务,我们通常需要自己实现工具来删除大KEY,或者在业务低峰期进行删除操作。
为了解决以上问题, Redis 4.0 新添加了 UNLINK 命令用于执行大KEY异步删除。那么这个异步删除的背后的逻辑是什么?
通过源码我们可以的得知以下信息:
当我们调用异步删除UNLINK命令时:
- 释放掉Expire Dicti 对 K-V 的引用
- 释放Main Dict 对 K-V 的引用,同时记录下这个K-V 的 Entry地址
- 计算释放掉这个V 所需要的代价,计算方法如下:
3.1 如果这个V 是一个 String 类型,则代价为 1
3.2 如果这个V 是一个复合类型,则代价为 该复合类型的长度,比如,list 则为 llen 的结果,hash 则为 hlen 的结果 … - 根据得到的代价值,和代价阈值比对,如果小于 64 则,可以直接释放掉K-V 内存空间;如果大于 64 则,把该V 放入lazyfree 队列中,同时启动一个BIO后台JOB进行删除
4.1 在后台线程对 V 进行删除时,也是根据不同类型的 V 做不同的操作
4.2 如果是 LIST 类型,则根据LIST 长度,则直接释放空间。
4.3 如果是 SET 类型,并且数据结构采用 HASH 表存储,那么遍历整个hash表,逐个释放 k,v空间;如果数据结构采用 intset,则直接释放空间即可
4.4 如果是 ZSET 类型,并且数据结构采用 SKIPLIST 存储,由于 SKIPLIST 底层采用 HASH + skiplist 存储,那么会先释放掉 SKIPLIST 中 hash 存储空间,再释放掉 SKIPLIST 中 skiplist 部分; 如果数据结构采用 ZIPLIST 存储,则直接释放空间。
4.5 如果是 HASH 类型,并且数据结构采用 HASH表存储,则遍历整个hash表,逐个释放 k,v空间;如果数据结构采用 ZIPLIST 存储,则直接释放空间。 - 设置 V 值等于NULL
- 释放掉 K-V 空间
异步删除代码如下 :
int dbAsyncDelete(redisDb *db, robj *key) {
/* */
if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr);
/* 在Main Dict 链表去掉引用,得到K-V entryDict */
dictEntry *de = dictUnlink(db->dict,key->ptr);
if (de) {
robj *val = dictGetVal(de);
size_t free_effort = lazyfreeGetFreeEffort(val);
/* 计算DEL key 的代价,根据代价决定是否采用异步删除方式 */
if (free_effort > LAZYFREE_THRESHOLD) {
atomicIncr(lazyfree_objects,1,lazyfree_objects_mutex);
bioCreateBackgroundJob(BIO_LAZY_FREE,val,NULL,NULL);
dictSetVal(db->dict,de,NULL);
}
}
/* 释放K-V空间,或者采用了异步删除方式,只需要释放Key空间 */
if (de) {
dictFreeUnlinkedEntry(db->dict,de);
if (server.cluster_enabled) slotToKeyDel(key);
return 1;
} else {
return 0;
}
}
/* 释放LIST 空间 */
void quicklistRelease(quicklist *quicklist) {
unsigned long len;
quicklistNode *current, *next;
current = quicklist->head;
len = quicklist->len;
while (len--) {
next = current->next;
zfree(current->zl);
quicklist->count -= current->count;
zfree(current);
quicklist->len--;
current = next;
}
zfree(quicklist);
}
/* 释放HASH表空间 */
static int _dictClear(dict *ht) {
unsigned long i;
for (i = 0; i < ht->size && ht->used > 0; i++) {
dictEntry *he, *nextHe;
if ((he = ht->table[i]) == NULL) continue;
while(he) {
nextHe = he->next;
dictFreeEntryKey(ht, he);
dictFreeEntryVal(ht, he);
free(he);
ht->used--;
he = nextHe;
}
}
free(ht->table);
_dictReset(ht);
return DICT_OK; /* never fails */
}
由于异步删除实际上是先在MAIN DICT 里边把 这个K,V 的引用关系去掉了,所以当我们再次查询这个Key 的时候是查不到的,然后在慢慢释放Value 所占用的内存空间。
我们发现在异步进行删除的时候,不管是删除 HASH也好,还是QUICKLIST 也罢,这部分其实并没有进行一个速度的控制,只是起了一个线程让他去删除,能跑多快就跑多快,这样可能会导致我们在进行删除的时候CPU飙高。
这个删除大KEY是在Master 上进行的,如果这个节点有Slave呢?slave 会进行怎样的操作?同样根据代码可以发现,我们在执行UNLINK操作时,实际上在 AOF 和 通知Slave的时候只是发送了一条DEL xxkey 命令,当slave 收到del命令时,会采取以上同样的判断对这个key进行删除。
notifyKeyspaceEvent(NOTIFY_GENERIC,"del",c->argv[j],c->db->id);
Redis4.0新特性之-大KEY删除的更多相关文章
- Redis4.0新特性
redis 4.0 新特性 Redis 4.0在2017年7月发布为GA.包含几个重大改进:更好的复制(PSYNC2),线程DEL / FLUSH,混合RDB + AOF格式,活动内存碎片整理,内存使 ...
- Redis4.0新特性(一)-Memory Command
Redis4.0版本增加了很多诱人的新特性,在redis精细化运营管理中都非常有用(猜想和antirez加入redislabs有很大关系):此系列几篇水文主要介绍以下几个新特性的使用和效果. Redi ...
- Redis4.0新特性 -Lazy Free
Redis4.0新增了非常实用的lazy free特性,从根本上解决Big Key(主要指定元素较多集合类型Key)删除的风险.笔者在redis运维中也遇过几次Big Key删除带来可用性和性能故障. ...
- 【特性】Redis4.0新特性
模块系统 Redis 4.0 发生的最大变化就是加入了模块系统, 这个系统可以让用户通过自己编写的代码来扩展和实现 Redis 本身并不具备的功能, 具体使用方法可以参考 antirez 的博文< ...
- Redis 6.0 新特性-多线程连环13问!
Redis 6.0 来了 在全国一片祥和IT民工欢度五一节假日的时候,Redis 6.0不声不响地于5 月 2 日正式发布了,吓得我赶紧从床上爬起来,学无止境!学无止境! 对于6.0版本,Redis之 ...
- redis5.0新特性
1. redis5.0新特性 1.1. 新的Stream类型 1.1.1. 什么是Stream数据类型 抽象数据日志 数据流 1.2. 新的Redis模块API:Timers and Cluster ...
- Day07 jdk5.0新特性&Junit&反射
day07总结 今日内容 MyEclipse安装与使用 JUnit使用 泛型 1.5新特性 自动装箱拆箱 增强for 静态导入 可变参数方法 枚举 反射 MyEclipse安装与使用(yes) 安装M ...
- [翻译] C# 8.0 新特性 Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南) 【由浅至深】redis 实现发布订阅的几种方式 .NET Core开发者的福音之玩转Redis的又一傻瓜式神器推荐
[翻译] C# 8.0 新特性 2018-11-13 17:04 by Rwing, 1179 阅读, 24 评论, 收藏, 编辑 原文: Building C# 8.0[译注:原文主标题如此,但内容 ...
- 【mysql】mysq8.0新特性
一.MySQL8.0简介 mysql8.0现在已经发布,2016-09-12第一个DM(development milestone)版本8.0.0发布.新的版本带来很多新功能和新特性,对性能也得到 ...
随机推荐
- stm32_DMA采集一个AD数据_并通过DMA向串口发送
这是以前学32的时候写的,那时候学了32之后感觉32真是太强大了,比51强的没影.关于dma网上有许多的资料,关于dma采集ad网上也有很多.亲们搜搜,这里只贴代码了,其实我也想详详细细地叙述一番,但 ...
- 所做更改会影响共用模板Normal.dotm。是否保存此更改
最近安装了Office 2010版本,但是发现个问题,每次在关闭word 2010时,都会提示所做更改会影响共用模板Normal.dotm …… 确实是烦恼,每次都需要点击是否保存,于是我在仔细研究了 ...
- 基于TLS证书手动部署kubernetes集群(上)
一.简介 Kubernetes是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,Kubernetes也叫K8S. K8S是Google内部一个叫Borg的容器集群管理系统衍生 ...
- 《基于Arm实验箱的国密算法应用》课程设计 结题报告
<基于Arm实验箱的国密算法应用>课程设计 结题报告 小组成员姓名:20155206赵飞 20155220吴思其 20155234昝昕明 指导教师:娄嘉鹏 设计方案 题目要求:基于Arm实 ...
- 一、InnoDB引擎
一.InnoDB的历史 MYSQL的5.1版本的时候还是使用旧的innoDB,当时orale公司推出的新的innoDB引擎, 但是需要以插件的形式编译,叫innoDB plugin : 知道MYSQL ...
- C语言学习之联合类型
前言 联合(union)是一种特殊的数据类型,和结构体很像,结构体各成员变量有自己独立的存储位置,而联合的成员变量共享同一片存储区域,因此联合变量再一个时刻只能保存它的某一个成员的值. 联合的定义和初 ...
- Spring Boot (十五): Spring Boot + Jpa + Thymeleaf 增删改查示例
这篇文章介绍如何使用 Jpa 和 Thymeleaf 做一个增删改查的示例. 先和大家聊聊我为什么喜欢写这种脚手架的项目,在我学习一门新技术的时候,总是想快速的搭建起一个 Demo 来试试它的效果,越 ...
- redis见解
http://blog.csdn.net/zhiguozhu/article/details/50517527Redis原生session与redis中的session区别原生session在服务器上 ...
- Python+opencv 图像拼接
1.http://www.cnblogs.com/skyfsm/p/7411961.html ,给出了很好地拼接算法实现 2.由于不是Python的,所以简单做了一些翻译转成Python+opencv ...
- Invalid AABB inAABB UnityEngine.Canvas:SendWillRenderCanvases()的解决办法
我遇到这个问题的情况是, 在Start()中直接使用WWW价值本地图片,可能是加载图片相对比较耗时,就出现了这个错误. 解决的办法是使用协程: // Use this for initializati ...