• lison
    2021-07-26
    老师,有幸听了您的集训班,想咨询下 后续章节是否有具体版本和编译工具的介绍,后续好和您保持同步

    作者回复: 咱们这次专栏阅读的源码版本是Redis 5.0.8,源码文件可以在 https://github.com/redis/redis/tree/5.0/src 上下载 编译可以就用gcc。 如果同步有问题,可以留言哈

    
    1
  • Leven
    2021-07-26
    请问老师,没有c语言基础适合吗

    作者回复: 建议要有些C语言的语法基础,例如基本数据类型、结构体、联合体、宏定义、控制分支、函数调用、指针等这些概念要有。 否则读起来会有些辛苦的

    
    
  • Kaito
    2021-07-28
    重新看了一下源码目录,结合这篇文章的内容,整理了一下代码分类(忽略.h头文件),这也更清晰一些: 数据类型: - String(t_string.c、sds.c、bitops.c) - List(t_list.c、ziplist.c) - Hash(t_hash.c、ziplist.c、dict.c) - Set(t_set.c、intset.c) - Sorted Set(t_zset.c、ziplist.c、dict.c) - HyperLogLog(hyperloglog.c) - Geo(geo.c、geohash.c、geohash_helper.c) - Stream(t_stream.c、rax.c、listpack.c) 全局: - Server(server.c、anet.c) - Object(object.c) - 键值对(db.c) - 事件驱动(ae.c、ae_epoll.c、ae_kqueue.c、ae_evport.c、ae_select.c、networking.c) - 内存回收(expire.c、lazyfree.c) - 数据替换(evict.c) - 后台线程(bio.c) - 事务(multi.c) - PubSub(pubsub.c) - 内存分配(zmalloc.c) - 双向链表(adlist.c) 高可用&集群: - 持久化:RDB(rdb.c、redis-check-rdb.c)、AOF(aof.c、redis-check-aof.c) - 主从复制(replication.c) - 哨兵(sentinel.c) - 集群(cluster.c) 辅助功能: - 延迟统计(latency.c) - 慢日志(slowlog.c) - 通知(notify.c) - 基准性能(redis-benchmark.c) 下面解答课后问题: Redis 从 4.0 版本开始,能够支持后台异步执行任务,比如异步删除数据,你能在 Redis 功能源码中,找到实现后台任务的代码文件么? 后台任务的代码在 bio.c 中。 Redis Server 在启动时,会在 server.c 中调用 bioInit 函数,这个函数会创建 3 类后台任务(类型定义在 bio.h 中): #define BIO_CLOSE_FILE 0 // 后台线程关闭 fd #define BIO_AOF_FSYNC 1 // AOF 配置为 everysec,后台线程刷盘 #define BIO_LAZY_FREE 2 // 后台线程释放 key 内存 这 3 类后台任务,已经注册好了执行固定的函数(消费者): - BIO_CLOSE_FILE 对应执行 close(fd) - BIO_AOF_FSYNC 对应执行 fsync(fd) - BIO_LAZY_FREE 根据参数不同,对应 3 个函数(freeObject/freeDatabase/freeSlowsMap) 之后,主线程凡是需要把一个任务交给后台线程处理时,就会调用 bio.c 的 bioCreateBackgroundJob 函数(相当于发布异步任务的函数),并指定该任务是上面 3 个的哪一类,把任务挂到对应类型的「链表」下(bio_jobs[type]),任务即发布成功(生产者任务完成)。 消费者从链表中拿到生产者发过来的「任务类型 + 参数」,执行上面任务对应的方法即可。当然,由于是「多线程」读写链表数据,这个过程是需要「加锁」操作的。 如果要找「异步删除数据」的逻辑,可以从 server.c 的 unlink 命令为起点,一路跟代码进去,就会看到调用了 lazyfree.c 的 dbAsyncDelete 函数,这个函数最终会调到上面提到的发布异步任务函数 bioCreateBackgroundJob,整个链条就串起来了。
    展开
    共 11 条评论
    151
  • 悟空聊架构
    2021-07-27
    回答每课一问: Redis 从 4.0 版本开始,能够支持后台异步执行任务,比如异步删除数据,你能在 Redis 功能源码中,找到实现后台任务的代码文件么? 我翻看了 3.0 的源码,发现 3.0 就支持后台任务了。在文件 src\bio.c 里面有一个后台任务的函数: bioProcessBackgroundJobs,支持两种后台任务:关闭文件和 AOF 文件的 fsync 也是放到后台执行的。 (fsync 就是执行命令后将命令写到日志中,提供了三种策略:Always,同步写回,Everysec,每秒写回,No,操作系统控制的写回。) 疑问:根据 3.0 源码,Redis 3.0 其实就已经有后台任务了,老师在文中说的 4.0 才开始支持后台任务,我没理解。 然后我又去翻了下 4.0 的源码,增加一种后台任务:BIO_LAZY_FREE。 当任务类型等于 BIO_LAZY_FREE 时,针对不同的传参,可以释放对象、数据库、跳跃表。 对于释放可以稍微说一下,释放的源码在这个文件里面:\src\lazyfree.c,相对 3.0 来说,这个文件是新增加的。 关于对象的释放,我们可以联想到 Java 的垃圾回收算法:可达性分析算法,但是 Redis 的垃圾回收算法用的是引用计数算法,另外 PHP 的垃圾回收算法用的也是引用计数(扩展下:用了多色标记的方式,来识别垃圾,详细参考这里:https://mp.weixin.qq.com/s/n6PGIgfZ8vXUZ1rkU5Otog),所以别再说引用计数不能用做垃圾回收了哦。 而对于 Redis 释放对象来说,会减少引用的次数,调用的是这个函数:decrRefCount(o); 根据函数的名字也容易理解。 吐槽下:Github 上下载源码总是下载失败,为了其他同学们方便下载,我整理了多套源码的下载地址,都是国内的网盘链接,只有几MB 大小,下载比较快的。 http://www.passjava.cn/#/12.Redis/00.DownloadRedis
    展开
    共 6 条评论
    14
  • Ethan New
    2021-07-28
    评论区也太强了吧,瑟瑟发抖
    
    9
  • 陌
    2021-07-29
    关于作业,如果一开始对 Redis 源码不熟悉的话,我们可以借用 GDB 工具来回答 Redis 有哪些后台任务: 1) 添加 -g 的编码参数,向编译文件中添加调试信息,以便使用 GDB: make CFLAGS="-g -O0" 2) cd src && gdb redis-server 3) 在 aeMain 函数处打一个断点,然后再使得程序运行至此处: break aeMain run 4) 查看线程信息: info threads 这时候我们就能够看到 4 个线程的相关信息,分别是 redis-server、bio_close_file、bio_aof_fsync、bio_lazy_free,然后就可以按线程名称再去源码中查找了。
    共 1 条评论
    8
  • 可怜大灰狼
    2021-07-26
    我的第一反应应该是从unlink命令入手查找。首先肯定是server.c中redisCommandTable[]中的unlinkCommand,找到了lazyfree.c中dbAsyncDelete方法,然后找到了bio.c中bioCreateBackgroundJob方法,很显然bio.h中加了一种后台IO任务类型:BIO_LAZY_FREE=2。我记得我看3.0代码还只有BIO_CLOSE_FILE和BIO_AOF_FSYNC
    
    5
  • Darren
    2021-07-26
    bio.c 在5.x的源码中,后台异步执行又3个子线程 #define BIO_NUM_OPS 3 #define BIO_CLOSE_FILE 0 /* Deferred close(2) syscall. */ #define BIO_AOF_FSYNC 1 /* Deferred AOF fsync. */ #define BIO_LAZY_FREE 2 /* Deferred objects freeing. */ bioInit方法中通过pthread_create创建BIO_NUM_OPS子线程,不同线程的任务在static list *bio_jobs[BIO_NUM_OPS]中存储。
    
    5
  • Kang
    2021-07-26
    请问下老师,各个源码目录的作用是从那里获取到的,mysql的话也会有相应解释吗
    共 1 条评论
    3
  • 小五
    2021-07-27
    1 Redis 支持 3 大类型的后台任务,它们定义在 bio.h 文件中: /* Background job opcodes 后台作业操作码 * 1 处理关闭文件 * 2 AOF 异步刷盘 * 3 lazyfree */ #define BIO_CLOSE_FILE 0 /* Deferred close(2) syscall. */ #define BIO_AOF_FSYNC 1 /* Deferred AOF fsync. */ #define BIO_LAZY_FREE 2 /* Deferred objects freeing. */ 在 Redis 服务器启动时,会创建以上三类后台线程,然后阻塞等待任务的到来。处理关闭文件和 AOF 异步刷盘异步任务比较好理解,lazyfree 类型的异步任务场景就比较多了,比如下面几种情况: 1)删除数据:配置 lazyfree_lazy_user_del ,使用 unlink , 都可能将删除封装成任务放到 bio_jobs 任务队列中 2) 定期删除时,如果配置 lazyfree_lazy_expire ,那么可能将删除封装成任务放到 bio_jobs 任务队列中 2 后台创建的以上三种 bio 后台线程会不断轮询 bio_jobs 任务队列中的任务,并分门别类的处理对应的任务。逻辑操作定义在 bio.c 文件中 3 在 Redis 6.0 中增加了 io 多线程,在 networking.c 中定义了 io 线程的任务队列,以及创建 io_threads_num 个 io 线程,这些 io 线程会不断轮询 IO 读写任务。
    展开
    
    2