文章目录
-
- 写在文章开头
- 为什么想尝试用go复刻redis
- 复刻redis的心路历程
- 程序员对于舒适区的一点看法
- 关于mini-redis的一些展望
- 结语
写在文章开头
在程序员的技术生涯长河中,我们常常会在熟悉的领域中建立起自己的“舒适区”。于我而言,Java 就是这片承载了多年奋斗与成果的舒适天地。在过去的时光里,我凭借 Java 技术,在项目开发中如鱼得水,解决了一个又一个难题,收获了无数的经验与成绩。
然而,技术的浪潮滚滚向前,不进则退。在不断探索新技术边界的过程中,我意识到,一直蜷缩在舒适区内,虽然安稳,但也意味着逐渐失去对新技术敏锐的感知和应对变化的能力。为了突破自我,寻求技术上的更大成长,我决定勇敢地迈出这一步——告别 Java 的舒适区,选择 Go 语言开启新的挑战。
而基于 Go 语言复刻 Redis 这个项目,成为了我这场挑战之旅的核心战场。这不仅是不同编程语言之间的转换,更是思维模式、编程习惯的全方位冲击与重塑。在这一年里,我经历了无数次的迷茫与困惑,也收获了数不清的惊喜与突破。现在,站在这一年的末尾,回顾这段充满挑战的历程,感慨万千,有必要好好总结一下这段独特的技术探索之旅中的设计思路和技术心得 。
为什么想尝试用go复刻redis
由于工作上的需求,作为一名 Java
开发者,我深知 Redis 在实际项目中的重要性。为了更深入地理解和熟练掌握 Redis
的运行机制,我决定仔细研读 Redis 的核心源码实现。在阅读过程中,Redis 对单线程性能极致挖掘的设计理念深深地吸引了我。为了能更透彻地领悟 Redis
设计的精妙之处,我萌生出复刻一个简易版 Redis 的想法。
在过去几年里,因个人学习与实践的需要,我接触到了 Go 语言。对于这门语言的语法和设计理念,不同开发者有着各自的看法。以我个人多年的 Java
开发经验,再结合对 Go 语言的使用感受来说,Go
语言在语法表达上与传统的 Java 语言有着显著区别,它有着更直观形象的表达方式。
就拿 Go
语言中的 channel
管道机制来说,其在数据流向的表达上十分清晰明了。以我正在开发的 mini - redis
为例,在这个项目中,我利用 channel
来监听系统中各种针对 Redis
进程的关闭操作。通过 chan 关键字,整个数据流向和操作逻辑非常直观,让开发者能够迅速理解代码的意图。这种独特的语法表达方式,与我们 Java
语言严谨的面向对象语法体系相比,有着别样的魅力和优势:
//监听针对当前进程的关闭信号
sigCh := make(chan os.Signal)
signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
go func(server *redisServer) {
//阻塞监听,收到信号后直接传输到sig上
sig := <-sigCh
//针对sig信号类型进行响应处理
switch sig {
case syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT://如果是关闭信号,则将redis服务进程关闭
closeRedisServer()
//并将关闭标识置为1,通知其他协程也可以开始处理关闭操作
server.done.Store(1)
}
}(&server)
总的来讲,Redis 是一款使用 C 语言编写的内存型非关系型数据库。它涉及大量底层 API 的运用以及复杂的内存管理操作,这使得 Redis 的实现极为精巧且繁杂。
在复刻 Redis 的过程中,需要精准考虑各种函数的语义表达,同时还要兼顾内存管理的高效性。由于 C 语言在底层操作和内存管理方面具有优势,而 Java 虽然功能强大,但在处理这类底层细节时,相对不够灵活,且内存管理成本较高。为了能更好地模拟 Redis 的底层实现逻辑,同时找到一种在函数语义表达和内存管理成本方面更合适的解决方案,我决定走出 Java 的舒适区。
Go 语言虽然对我来说并非像 Java 那样熟练,属于相对陌生的“副手语言”,但它具备简洁高效的语法以及出色的并发性能,在内存管理方面也有着独特的优势,非常适合用来复刻 Redis 这种对底层操作和性能要求极高的项目。因此,我最终选择了 Go 语言开启 Redis 的复刻工作 。
复刻redis的心路历程
依照我的习惯,每当面对一个目标时,我总会遵循一套固定的流程来完成:
- 制定计划与目标
- 拆解任务,明确规划
- 收集相关资料,逐步攻克难题
- 进行复盘总结与优化迭代
下面先谈谈制定计划和目标这一环节。Redis 的源码是用 C 语言编写的,而我打算使用 Go 语言进行复刻。对于像我这样以 Java 开发为主的工作者而言,C 语言和 Go 语言都属于相对陌生的领域。因此,在计划的初始阶段,我考虑过挑选一些优质的学习资料,对这两门语言进行系统性的基础学习,以便消除知识盲区。
在有了初步的想法之后,我进一步从综合成本的角度进行考量。考虑到时间成本以及计划推进的效率问题(毕竟我个人本身已经具备一定的 C 语言和 Go 语言基础),我最终决定采用一种更具导向性的方法——项目驱动法。具体来说,就是从宏观层面入手,阅读 Redis 源码,以此来逐步了解其实现的各个步骤。随后,针对在阅读过程中遇到的不同语义、语法以及函数等方面的问题,逐一进行学习和理解,进而全面掌握 Redis 每个模块的实现原理。
所以在上述的综合考量后,笔者的关于复刻计划任务的拆解思路为:
- 指定复刻目标,以笔者为例便是实现redis中所有常见数据结构的核心指令,这一点可以参考笔者mini-redis中readme的说明:
- 着手查找各类适配的学习素材,具体包括详细且深入的 Redis 源码讲解资料、能够系统进行 C 语言语法扫盲的学习资源,以及有助于提升 Go 语言进阶使用技巧的相关材料。这一步至关重要,丰富且精准的资料将为后续的学习和复刻工作奠定坚实基础。
- 借助获取到的 Redis 源码讲解素材,对 Redis 指令的请求流程、处理方式以及解析思路进行全面且细致的走读分析。在这个过程中,详细记录关键信息,并将整个过程拆解,形成一份条理清晰、逻辑严谨的阅读理解文档。这份文档不仅能够加深对 Redis 指令处理机制的理解,更能为后续的开发工作提供明确指引。基于这份梳理文档,结合自身对项目的理解和规划,制定出贴合实际需求的开发计划。同时,根据开发计划和 Redis 的功能特点,设计并规划与之相关的测试单元,确保开发过程中的每一个环节都能得到有效验证。
- 延续上述走读方式,基于 Redis 源码讲解深入探究各种数据结构的设计理念与实现思路。这要求我们从源码层面剖析每一种数据结构的设计初衷、所具备的优势以及如何在实际应用中高效实现。同样,按照前一步骤的方法,将这一过程详细记录并拆解,形成相应的文档。依据这份文档制定开发计划,逐步完成对 Redis 数据结构的复刻工作,确保每一个数据结构的复刻都能准确还原其功能和特性。
- 在完成各个阶段的开发和复刻工作之后,进行全面细致的梳理与自我走查。这一过程需要对整个项目进行系统性回顾,从代码逻辑、功能实现到性能优化等各个方面进行深入检查,找出其中存在的不足之处。针对这些问题,制定详细的修复方案,并在接下来的开发周期中予以解决。同时,做好复盘总结工作,分析问题产生的原因,总结经验教训,为后续项目的开发提供宝贵参考,以不断提升开发水平和项目质量。
针对redis的源码阅读的参考资料,笔者不得不推荐一下黄健宏老师的编写的这本《redis设计与实现》
通过对这本书籍的通篇阅读,笔者非常轻松的从思想层面了解到源码的实现思路,结合书本中的前几章笔者很好的理解掌握的redis底层数据结构的逻辑结构和设计理念,结合书中对于关键点的提示和C语言语法糖扫盲,笔者很好的梳理出Redis源码整体的实现和落地思路细节:
然后基于笔者输出的这一份拆解文档得出自己的开发计划和复刻思路,从而得出自己的复刻思路,以go语言的姿态复刻出带有C语言味道的mini-redis:
在完成开发之后,笔者也会梳理出个人的开发思路与不足点与朋友们进行交流,从而得出下一步的迭代计划,也正是这样周而复始的不断前进,笔者终于在2024年完成mini-redis核心数据结构及其操作指令的实现:
程序员对于舒适区的一点看法
我们再来说说舒适区的这个概念,对笔者而言,在一个领域或者具体一点来说是一门技术、一门语言长时间的接触和使用之后,都会有着一个相对稳定的舒适区,私以为这个舒适区对于工作来说,他可以较好的保证系统迭代的质量,但对于个人发展而言,舒适区的存在往往会因为人的惰性而逐步让人消沉,随着时间的推移可能会让人失去探索的热情。
这也就是为什么笔者总是喜欢在技术上各种作死的原因,通过在陌生的领域进行摸索、学习、输出总结,感知从未知到已知的过程,保持日常对于跳出舒适区的习惯和节奏,以保持我们对于职业生涯的探索和人情,从而不断的进步。
关于mini-redis的一些展望
回归到技术层面,聊一聊我作为一名对 Redis 源码有着稍微的理解与掌握的程序员,对于mini - redis
的展望。
在开发 mini - redis
的过程中,我目前仅仅完成了对几个核心指令的复刻工作。要知道,Redis
作为一款功能强大且应用广泛的内存数据结构存储系统,其蕴含的技术深度和广度远超于此。像持久化机制,它关乎数据在断电等异常情况下的可靠保存,是保障数据完整性的关键部分;缓存置换策略,这决定了在内存有限的情况下,如何高效地替换旧数据以接纳新数据,对系统的性能和资源利用起着至关重要的作用;还有分布式和高可用特性,它们让 Redis
能够适应大规模、高并发的复杂生产环境,确保服务的稳定运行。
很遗憾,到目前为止,对于这些重要的功能模块,我还未来得及在 mini - redis
中完成复刻。在新的一年里,我由衷地希望能有更多志同道合的读者,特别是那些同样热衷于探索底层技术的朋友们,能够和我保持密切的交流。我们可以一起深入剖析 Redis 这些功能点在源码层面的实现思路,从数据结构的设计、算法的优化到系统架构的考量,全方位地进行探讨。我相信,通过大家的智慧碰撞,一定能够推动 mini - redis 不断发展前进,让它逐渐成为一个更加完善、功能更加丰富的 Redis 复刻项目。
结语
在这一年即将画上句号之际,我内心满是感激之情,想要特别感谢sharkChili技术交流圈里的每一位读者(尤其是建立之初积极助力吸引读者的Leo、强总、人生大佬、知秋大佬、渣凯、李现同学以及好学的人生弟)。
这一年来,大家围绕Redis
技术点展开的日常提问与积极交流,就像源源不断的动力,极大地激发了我深入钻研Redis的热情。每一次与大家探讨那些复杂的技术难题,每一回解答大家提出的疑惑,都让我对Redis有了更为透彻的认知,也促使我在这条技术探索之路上不断迈进。
正是因为有你们的存在,这个交流圈充满了活力与智慧的碰撞。你们的每一个问题,都像是打开新知识大门的钥匙;你们分享的每一种见解,都丰富了我对Redis技术体系的理解。所以,真心地向大家致以我最诚挚的感谢。
新的一年已经悄然来临,衷心希望我们能够携手并进,在技术的海洋里继续畅游。无论是Redis技术的新领域,还是其他相关的技术方向,都期待我们能一同挖掘更多的宝藏,实现更大的突破。希望大家在追求技术成长的道路上,都能遇见更好的自己,收获满满的成就感。
另外,我还要把这份感谢送给渣凯小同学。从你身上,我真切地看到了软件行业蓬勃的新生力量。你积极进取的态度和对新技术的敏锐洞察力,都让我深感欣慰。你就像一颗正在崛起的新星,闪耀着无限的潜力。
在新的行业征程中,愿你能凭借自身的才华和努力,稳扎稳打地前行。希望你在面对各种挑战时,都能保持那份热情与执着,不断积累经验,攻克一个又一个难关。衷心祝愿你在这个充满机遇与挑战的领域里有所建树,创造出属于自己的辉煌成就 ,在新赛道增添一抹绚丽的色彩。