AI 是否在浪费一个人的时间?

在科技飞速发展的今天,人工智能(AI)已经成为一个热门话题。其中,ChatGPT 以其强大的自然语言处理能力,吸引了全球范围内的关注。它从大型数据集中学习的模式和示例创建或生成新的内容,例如文本、图像甚至音乐和视频。

然而,在追捧 ChatGPT 的同时,我们也需要保持冷静,理性看待这一技术,避免成为盲目跟风的“韭菜”。

那么,ChatGPT 能否以及如何人们的生产力呢?作为 IT 程序员的张无剑使用 ChatGPT 来解决他遇到的一些问题的经历或许可以给我们一些启发……

ChatGPT 能够显著提高人类生产力?

嗷嗷喜欢熬夜,夜夜夜夜,夜夜辗转难眠的 IT 程序员张无剑躺在床上,准备再刷 5 分钟手机就睡觉,一打开手机就看到了小红书要裁员的热搜消息。

d20306ecfd8b85b9eca637d207234b6a.png

张无剑居安思危,想系统化的学习 Redis 技术,提高自己的竞争力。网络上铺天盖地的宣传 ChatGPT 强大,就计划用 ChatGPT 来梭哈一把。

在询问之前,张无剑花了很多时间研究如何更好的给出提示语,因为没有好的提示语,ChatGPT 给出的答案可能有点智障。

25845f7611e72e80d9e8418882221b57.png

花了好些时间学会了提示技巧后,询问 ChatGPT 得到一份大纲学习计划。

Redis 7.0 学习计划

c4188ba9a3bff8b0d730d20e8524b216.png

有了计划。今天就从 Redis 基础入门 Redis List 数据类型学习吧。

Redis List 数据类型底层实现原理

张无剑再次绞尽脑汁想了一个提示语喂给 ChatGPT。

假如你是一个资深 Redis 7.0 技术培训老师,我是你的学生。我根据上文你列出的学习目标 “Redis 基础入门”,学习内容为“Redis 数据类型 List 底层实现原理和实战技巧” ,我的目标是掌握这些数据类型的底层实现原理和实战技巧,原理讲解要深入一些,我的目标是成为 Redis 高手。

ChatGPT 的回复如下。

6c33fad4cee3a6f742219ae58d57e8c9.png

张无剑内心嘀咕道:这也太简单了,看起来好像说明了底层原理,但就总觉得好像还不够深入,只能大概了解 Redis 的 List 数据类型,根本成不了 Redis 高手,花了这么多时间,就这???

“人工智能教父”杨立昆说过:ChatGPT 没那么厉害!果然是真的。

fb7bbdc990a85b4c3ef34c81c6dab41d.png

张无剑遇到的问题在于以下几点。

  1. 无图无真相,无法理解 List 底层有两种数据结构(Linkedlist、Ziplist)到底是啥样的。

  2. 无法理解为什么 List 要用两种数据结构(Linkedlist、Ziplist)保存数据。

  3. 语言生硬,也就是从我们说的 AI 味太冲,学习本就是件痛苦的事情,在这样的枯燥文字中还如何学得下去。

  4. 最大的问题在于不知 ChatGPT 的回复到底是不是对的。

  5. 还要花费大量时间来调教 ChatGPT 纠正错误,可本身自己是来学习的,如何做到纠正呢……

欲练此功不必自宫只需放松

Redis 看到张无剑使用 ChatGPT 来学习 Redis,快急死了。因为 ChatGPT 回复的内容存在错误!再继续学习下去的话怕是容易走火入魔!

Redis 开始解答张无剑学习 Redis 的困惑,并推荐张无剑一本至高心法学习,它就是《Redis 高手心法》。

该心法从 Redis 的第一人称视角出发,拟人故事化方式和诙谐幽默的言语与各路“神仙”对话,配合 158 张图,由浅入深循序渐进的讲解 Redis 的数据结构实现原理、开发技巧、运维技术和高阶使用,让人轻松愉快地学习。

将复杂的概念与实际案例相结合,让理论原理与实战相结合,以简洁诙谐幽默的方式配以大量撩人心弦又准确的图片,为你揭示 Redis 的精髓。哪怕是“天阶高级”斗技,也能愉快的修炼,而不会走火入魔。

4dcc81100ae5524a3896a9b79c46d917.png

现在新书上市,优惠力度特别大,原价 100,现在 5 折优惠,只需要 50 灵石,推荐大家趁着这个机会,赶紧冲一波,拍下《Redis 高手心法》 秘籍,早日修炼天阶斗技。

篇幅有限,我只列举《Redis 高手心法》的部分内容给你看下……

开局第一步,先通过源代码编译来安装 Redis,让你在自己的机器上搭建一套可以 Debug 的源码环境。通过源码编译构建出可调式环境之后,想必你想更深入了解我的整体架构。

c50baf1cb569c1fbd7deaec3cd657499.png

张无剑:Redis 支持不同的数据类型,存储原理是什么?

以 Redis 7.0 版本为例,server.h 的 redisDb 结构体抽象了 Redis 核心存储结构。其中 redisDb *db 指针非常重要,它指向了一个长度为 dbnum(默认 16)的 redisDb 数组,它是整个存储的核心,我用它来存储键-值对。

15a03c8c3c993ae978268cad4947da51.png

Redis 继续说道:“我支持很多种数据类型,对于不同的数据类型,底层用了多种数据结构来实现存储。”

我给开发者提供了 String(字符串)、Hashes(散列表)、Lists(列表)、Sets(无序集合)、Sorted Sets(可根据范围查询的排序集合)、Bitmap(位图)、HyperLogLog、Geospatial(地理空间)和 Stream(流)等数据类型。

为了在速度和内存占用之间找到最优解,我设计了多种数据结构。总之为了实现多快好省(支持数据类型多、速度快、好用、节省内存)。

04f15dd4c7527d874472d254a650d90a.png

Redis:ChatGPT 回复你关于 List 地岑实现原理有错误,实际上是这样的……

在 C 语言中,并没有现成的链表结构,所以 Antirez 为我专门设计了一套实现方式。

关于 Lists 类型的底层数据结构,可谓英雄辈出,Antirez 大佬一直在优化,创造了多种用来保存的数据结构。包括早期作为 Lists 的底层实现的 linkedlist(双端链表)和 ziplist(压缩列表),Redis 3.2 引入的由 linkedlist 和 ziplist 组成的 quicklist,以及 7.0 版本中取代了 ziplist 的 listpack。

张无剑:“为什么弄了这么多数据结构呀?”

Antirez 所做的这一切都是为了在内存空间开销与访问性能之间做取舍和平衡,跟着我去

“吃透”每个类型的设计思想和不足,你就明白了。

linkedlist

在 Redis3.2 之前,Lists 的底层数据结构由 linkedlist 或者 ziplist 实现,优先使用 ziplist 存储。当 Lists 对象满足以下两个条件时,将使用 ziplist 存储链表,否则使用 linkedlist。

◎ 链表中的每个元素占用的字节数小于 64。

◎ 链表的元素数量小于 512 个。

975d78f88117e73ecec5f2a5db46f376.png

张无剑:看起来没什么问题呀,为什么还要 ziplist 呢?

你知道的,我在追求快和节省内存的方向上无所不及,有两个原因导致了 ziplist 的诞生。

◎ 普通的 linkedlist 有 prev、next 两个指针,在数据很小的情况下,指针占用的空间会 超过数据占用的空间,这就离谱了,是可忍,孰不可忍。

◎ linkedlist 是链表结构,在内存中不是连续的,遍历的效率低下。

ziplist

为了解决上面两个问题,Antirez 创造了 ziplist,这是一种内存紧凑的数据结构,占用一块 连续的内存空间,能够提升内存使用率。ziplist 有多个 entry 节点,可以存放整数或者字符串,结构如图所示。

a9a3e8bcc322f6f15fd4bcf356bd721c.png

ziplist 头尾元数据的大小是固定的,并且 zllen 记录了 ziplist 头部最后一个元素的位 置,所以,能以 O(1) 的时间复杂度找到 ziplist 中第一个或最后一个元素。而在查找中间元素 时,只能从 Lists 头或者 Lists 尾遍历,时间复杂度是 O(N)。

张无剑:“听起来很完美,为什么还要搞 quicklist ?”

“既要又要还要”的需求是很难实现的,ziplist 节省了内存,但是也有不足。

◎ 不能保存过多的元素,否则查询性能会大大降低,导致 O(N) 时间复杂度。

◎ ziplist 的存储空间是连续的,当插入新的 entry 时,内存空间不足就需要重新分配一块连续的内存空间,引发连锁更新的问题。

每个 entry 都用 prevlen 记录上一个 entry 的长度,在当前 entry B 前面插入一个新的 entry A 时,会导致 B 的 prevlen 改变,也会导致 entry B 的大小发生变化。entry B 后一个 entry C 的 prevlen 也需要改变。

a00cd5374ba108c6ec4ba8179c5e23bb.png

quicklist

连锁更新会导致多次重新分配 ziplist 的内存空间,直接影响 ziplist 的查询性能。于是, Redis 3.2 引入了 quicklist。quicklist 是综合考虑了时间效率与空间效率引入的新型数据结构。它结合了 linkedlist 与 ziplist 的优势,本质还是一个链表,只不过链表的每个节点都是一个 ziplist。

ba53f81c290cbec0d0d5027fda5c04d4.png

listpack

张无剑:搞了半天还是没能解决连锁更新的问题嘛。

别急,饭要一口一口吃,路要一步一步走,步子迈大了容易摔跟头。ziplist 是紧凑型数据结构,可以有效利用内存。但是每个 entry 都用 prevlen 保留了上一 个 entry 的长度,所以在插入或者更新时可能出现连锁更新影响效率。

是 Antirez 又设计出了“链表 + ziplist”组成的 quicklist 来避免单个 ziplist 过大,缩 小连锁更新的影响范围。可毕竟还是使用了 ziplist,本质上无法避免连锁更新的问题。于是, 5.0 版本设计出另一个内存紧凑型数据结构 listpack,并在 7.0 版本中替换掉 ziplist。

33af58e72eb79e5fef2fe78bad70ea07.png

listpack 与 ziplist 最大的区别是 elements 部分, 为了解决 ziplist 连锁更新的问题,element 不再像 ziplist 的 entry 保存前一项的长度。

Lists 实现消息队列实现原理。

79f2fa60d56644b8efed9f36d5ce4fdc.png

Stream 就像一个仅追加内容的消息链表,把消息一个个串起来,每个消息都有唯一的 ID 和消息内容,消息内容由多个 field-value pairs 组成。Stream 底层使用 Radix Tree 和 listpack 数据结构存储数据。

4763f26d12e1df7d115f3dd48c4519d7.png

篇幅有限,不再一一列举……

现在新书上市,优惠力度特别大,原价 100,现在 5 折优惠,只需要 50 灵石,推荐大家趁着这个机会,赶紧冲一波,拍下《Redis 高手心法》 秘籍,早日修炼天阶斗技。

e0fd9234ec264d22bcb35ff17d9cc4e5.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值