粉丝67获赞219

大家好,那今天呢,咱们来聊一聊面试中经常被问到的问题啊,就是如何利用 redis 来实现分布式锁啊,那么我们应该如何如何去很好的回答这道题呢啊,今天呢,我给大家一步一步的讲明白啊,相信你,嗯,考完之后呢,一定会收获不小的啊。 那我们都知道 redis 这个执行指令是原子执行的,也就是同一时刻只能执行单一指令啊,所以我们可以充分利用这个特性啊,来实现我们的封饰锁啊。 那接下来呢,咱们来看一看方案一啊,那就是用这个 set n x 命令啊,那这个指令的意思是说,当这个 k 那不存在的时候呢,才能设置这个 t y 六成功啊,那再加上这个 redis 单线程执行指令的特性呢?所以说只有 一个请求能够设置成功,那其他请求呢?都是设置失败了,那设置成功呢,就抢到了锁, ok, 那咱们来先看一看这个方案一的流程图啊, 那当多个县城都到达这个我的这个业务处理方法的时候呢,那其实多个并发县城都去 rights 之内去申请所了,那也就是执行这个 set next 命令,那其实 由于 redis 是单线程这个执行命令的,所以只会有一个线程会优先的去执行,那这里呢,咱们假设这个 线程 a, 那执行成功了,那说明当前线程 a 获得了锁,那其他线程获取锁就失败了,那其实就是满足了这个锁的互制性啊,那其他线程执行赛的 nx 命令,那都会失败,那其实是可 可以进行这个重试啊,或者是等待的,嗯,那也可以这个呃快速的失败,直接返回结果啊,那县城 a 执行自己的业务,嗯,之后呢,其实就可以删除所,那也就是释放所了,那后续其他县城呢?能够继续这个抢占所,那也就继续执行这个 set x 命令。那因为线程 a 已经删除了锁啊,所以又有其他线线程呢,可以抢占得到锁了。 ok, 那流程咱们这个分析完了啊,咱们再看一看这个代码是 怎么实现的啊?这里呢,我有一段尾代码,那咱们来看一下啊,那这里呢,我先通过这个,呃, set nx 命令呢,设置这个 lock 的值为一二三,那如果设置成功呢,则表示加速成功啊,接着呢,他会执行这个业务逻辑。那最后呢,我在这个 friendly 的这个代码框内呢,删除了这个锁啊,也就是释放锁,那如果这个 set n x, 那返回 false 呢?那说明就是加锁失败了。嗯,我们可能会这个需要重试呀,或者是快速的失败返回啊。 ok, 那这个方案说完了呢,大家可以想想这个方案,嗯,有什么问题呢?那其实呢,这个方案呢,是有这个很大的问题呢,那假如在第一步我 set nx, 我加锁成功之后,也就是在底粒的释放锁之前, 服务器挡机了,那后面释放锁操作是没有执行的啊,那么其实其他的县城此时就永远无法获取到 lock 这把锁了啊,此时就形成了死锁,因为这个锁在 reaches 内会一直存在啊,主要是因为我们在 set nx 这个指令的时候,并不能设置这个锁的国际时间啊。那我们应该如何解决这个问题呢?咱们来看一下这个改进后的方案啊,也就是 方二,那这里呢?呃,我在里面这个获取锁成功呢,之后呢,我接着用这个 xp 命令,然后这个设置了这个锁的过期时间啊,那此时这个锁在 redis 内呢,就有了这个过期的时间,那即使这个在业务呃 执行的时候,那服务出现这个档机或者其他原因,这个程序异常退出了,那锁也会在过期时间到达时候呢,自动删除啊。 ok, 那此时的方案呢?看似这个完美的解决了夫妻异常呀,或者说这个程序异常退出造成这个所谓释放的问题啊, 但是呢,还是有其他的问题呢,那咱们继续来看代码啊,那其中啊,这个 我通过这个 set n s 去设置这把锁,就是抢占这把锁,那如果这抢占锁成功呢?接着我又通过这 x here 这个命令呢,设置这个锁的估计时间啊,那其实这两个指令呢,是在扣断执行的,也就是分两次这个 网络的 io, 那请求到 redis 服务器内去执行这个命令,那如果在这两个步骤之间,你的服务器依仗退出,或者说你的服务依仗退出,服务器当机了, 那么其实在这个过期时间还是没有设置成功呢,也就说这个 lock 这把锁的过期时间还是没有设成功的,还是有一样的问题,锁这个永远不过期,那可能还是会出现死锁。 ok, 那咱们继续来这个改进方案啊,那其实我们可以将这个 set n x 和这个 xp 嗯,这两条指令啊,进行原字的执行,也就是将 set n x 和 expear 通过一次网络 io 发送给 redis, 那一次性的在 redis 服务端内,那执行完成,那中间是不能够穿插其他指形的, 那我们应该如何去做呢?这里呢,由于 redis 是支持这个在 redis 内原子的执行撸画脚本的,所以呢,咱们可以将这两个步骤 写一段这个撸啊脚本,然后将撸啊脚本发送给 redis 服务端,让 redis 服务端内原子的执行这段撸啊脚本就可以了。 ok, 那下面呢,咱们来看一下这个撸啊脚本的编写啊,那其实就是 redis call, 那第一个参数呢,就是你要执行的这个 reddis 的指令,也就是 reddis 的命令,那后面呢,就是你的 key 和 value 相关的参数,那具体的使用呢?大家可以参考这个 reddis 的 官网进行查阅啊,其实是很简单的,那咱们来先来说这个代码吧,那这里呢,我先判断这个赛德 nx 是否设置成功啊,那如果是返回的是一,那就设置成功。那接着呢,我会调用这个 这个 expear 这条指令,那设置这个 k 的过期时间,那 如果啊设置过一些成功了,那么我就返回这个一,如果设置过一时间失败了,那么我就会返回这个零,那如果第一步这个 redis 点 call 赛德 nx 执行失败了,那我也会返回这个零。 ok, 嗯,这样呢,两条指令,嗯就可以源自的在副端内进行执行了。那有的小伙伴可能会想呢,那如果 expear 指令执行失败了,那散的 n s 还是执行了? 其实这样的就是如果你的语法是没有错误的,那 redis 是可以保证你的这两条直径都会这个源自的成功的执行完毕的。那其实 redis 为了保证自己简单高效快速啊,并没有实现这个版本的回滚的操作啊。 ok, 那其实上述的这段撸啊脚本呢,还是比较麻烦的啊,那 red 后期呢,给咱们提供了一个 set 指令的扩展参数啊。 呃,用于原子的执行 set n x 和 x p r 这两条制令啊,那咱们来看一下这两条制令啊,那其中这个 p x 和 n x 那是代表的是这个国际时间啊,他只是一个单位不同的而已,那一个是毫秒,一个是秒,那后面的最后的 n x 呢,表示的就是 k 不存在的时候才能够 set 成功,那也就能保证只有一个扣端请求才能获得所,那其他扣端请求只能 等待其他释放所才能够去获取所啊。 ok, 那下面呢,是 set 指定这个扩展参数的流程图案,那流程图内呢?其实我是将这个获取所的方式修改为了 set 这个 nx ex 方式啊,这样就能保证 k 和这个设置过之一时间呢,是是源自性的操作了。那这里我设置的国际时间是十秒啊。 ok, 那这个方案讲完了呢?嗯,其实这个方案还是有很大的问题呢,咱们继续看问题吧。 那问题一呢,就是锁释放了,嗯,业务还没有执行完啊,就是假设,咱们来看一个呃,场景啊,那假设线程 a 获取所成功,嗯,一直在这个执行他这个临界区的代码,也就是他的业务代码一直在执行那,但是十秒钟过去了,他还没有执行完,但是这时候锁 已经过期了,因为你设置的超时间是十秒钟,此时呢,现成 b 又请求过来了,显然现成现成 b 呢,是可以获得这个锁的成功的,那也开始执行这个邻居的代码,那么出现的问题就是,邻居这代码现在已经不是严格的 串形执行的了,那这就是问题所爱所在啊。那第二个问题呢,就是所被别的县城误删了啊,那假设县城 a 执行完去 释放锁,但是他不知道当前的锁可能已经是其他县城持有的了。那咱们这里再说一个场景啊,因为之前的县城 a 去释放锁之前啊,执行的业务代码的时间超过了十秒钟,那锁已经过期了,对吧?那此时这个 锁就释放了,那接着呢,现成币重新占有了锁,执行自己的业务逻辑代码, 那么此时县城 a 这个业务执行完了,开始释放自己的锁,那么他其实就是把县城 b 的锁给释放掉了,但是县城 b 临界区的业务代码可能还没有执行完呢, 这就是问题,就是所被别的县城误删了。 ok, 那么咱们来继续改进啊。那咱们先来看这个问题二啊,所被别的县城 误删的这种情况啊,嗯,咱们来看一下如何解决啊,就是咱们在设置这个 set nxex 呢,除了设置这个 锁的过期时间,还要设置一个与当前县城关联的唯一编号啊,你可以用这个 u i d 来实现啊。那主动删除锁的时候呢,其实是要判断这个编号是否与你当时设置的 这个编号也就 uid 是一致的,那如果一致,那则认为是自己设置锁,当然就可以进行相应的删除了。 ok, 那下面呢,咱们来看一下呃,这个流程图的一段伪代码啊,首先呢,我生成了一个 u i d, 那接着呢,我通过这个呃 set 的扩展命令啊,设置 log 对应的职位这个 u i d, 然后 n x, e x, 然后设置的国际时间为十五秒来保证这个原子性,通过这个 side n x, e x 来保证原子性,那如果加速成功,那么执行 业务逻辑,那最后呢,我通过这个 get 指令来获取 lock 对应的值,那如果我获取 lock 这个值和这个 uid 是相等的,那么接着呢,我就进行这个 delete 操作,也就进行删除来释放自己的锁。嗯, 这样是不看似就解决了问题呢,那其实这个代码还是有问题的,那判断是不是当前的 线程加的锁和释放锁这两个步骤呢?其实他不是一个原子操作,而是分两次网络 io 的请求到达 redis 负端进行执行的。咱们来考虑下面的情况啊,就是 如果现成 a 启动并设置锁成功了,那接着执行这个业务代码,那执行业务代码完成之后呢,查询对应的 uuid, 也就这个锁对应的 uuid。 查询之后呢,此时 cbo 让现成 a 挂起了,那么 接着这个十五秒就过去了,那现成 a 的锁过期了,那接着现成 b 启动了,那现成 b 就会设置锁成功,开始执行 自己的这个业务代码,那同时 cpu 让县城 a 恢复了,那么就会继续执行这个删除所的操作。由于之前我已经判断 他是我的锁了,对吧?那此时删除的锁是谁的锁?其实是已经是现成 b 的锁了,那锁删错了,所以我们要保证现成 a 执行获取这个锁的对比 以及到删除所必须是原字形的操作,那中间是不能穿插任何指令的,所以呢,我们要将这个过程编写成撸啊脚本,发送到 readys 段的服务段去执行,那就会原字性的执行,那中间就不会打断了。 那下边呢,就是我改进后的这个流程图啊,在看到这里的红框框呢,这里呢会执行一段这个乱脚本来保证这个操作的原子性啊,那至于这个乱脚本的代码,其实很简单啊,这里我就不再奥数了。 ok, 那咱们来,嗯,最后呢,再来看一看这个锁过期,对吧?过期已经释放了,但是业务还没有执行完,那这个问题呢,应该如何去解决啊?那有些小伙伴呢,可能认为,那咱们稍微把这个过期时间设置长一些不就可以了吗?那其 这个是不准确的啊。嗯,其实我们可以设想一下,是否可以在这个获取所的县城啊,他获取成功之后,开启一个定时的守护县城,那每隔一段时间去检查这个所在 redits 内 是否还存在,那存在呢?咱们就这个对锁的国际时间进行延长,我再调一下 inspare, 对吧?对锁进行这个 过期时间的延长呢?防止这个所这个过期的提前释放呢?那其实这种方案呢,也是这个开源框架 redison 的解决方案呢,咱们来再来看一下这个改进后的流程图案,也就是方案六, 只要县城一加锁成功,就会启动一个叫做 watch dog 看门狗,它是一个后台的守护县城啊,会每隔十秒钟检查一下锁是否存在啊,那如果县城还持有锁,那么就会不断 的延长锁这个 k 的生存时间啊。 ok, 那这样呢,这个锁的过期释放业务还没有执行完的问题就解决了,那检查这个时间的间隔呢?肯定是不能太长啊,如果比锁的失效时间还长,那锁都没了,那检查就 没有意义了啊。 ok, 那这个就是用 redis 来实现,嗯,分布式所的一个整个的一个方案啊, 从方案一到方案六啊,怎么进行一个改进啊?那其实上述 redis 分布式锁还是有一些问题的啊,问题出现在哪呢?其实我们的 redis 在线上呢,大多数都是主从或者集群这个架构部署的啊,那再进行这个分布式锁, 呃,实现的时候呢,你的锁的写入呢,会优先写入到这个 redis, master 实力呢,那此时会这个 e 步复制给这个对应的 slave 实力那但这过程中呢,一旦你的 master 发生了宕机啊,也就是说这个锁还没有来得及同步到其他的 slave, 也就是背上面去,那此时呢,这个 reddis 进行了主背切换,那 slave 呢?变为了 新的 master, 那接着就会导致呢,新的客户端来尝试枷锁的时候呢,并在新的 master 上完成了枷锁,而老的客户端也以为自己 成功的加了锁,那此时就导致多个客户端对一个风式锁完成了枷锁, 那这时系统在业务的语音上呢,一定会出现,嗯,一定的问题啊,那导致这个各种脏数据的产生啊,所以这就是这个 regis classer 或者是 master slave 架构的主从异部。呃,复制,那导致 regis 分布式锁,呃,最大的缺陷啊,就是在 master 当机的时候,那可能会导致多个客户端同时完成加锁,加锁成功啊。呃,所以说最后我来说一下我的个人观点啊。那本来呢,咱们是想用这个分布式锁来保证这个共享 资源或者你的业务,对吧?执行的串性化的来保证这个数据并发带来的数据安全问题 来保证,最后来保证这个数据的一致性。所以说,呃,咱们的分布制锁呢,应该是一个 c p 模型的,但 redis 本身呢,是一个 a p 模型,它并不是一个 c p 的。那所以利用 redis 来实现 风事所呢?个人感觉就是,嗯,有一种误区啊。那同时也欢迎大家在评论区来讨论啊。

很多同学简历上敢写精通 reddis, 那 我问你, reddis cluster 的 哈希槽为什么是一万六千三百八十四个?既然是 crc 十六算法,为什么不是六万五千五百三十六个呢?这时候你要是回答,呃,因为大家都这么用,或者坐着心情好,那基本上出门左转不送了。 这个数字背后,其实藏着 reddis 作者对待宽规模和性能的极致权衡。今天我们图文并茂给大家讲清楚。首先我们来解决第一个疑问, 为什么不用六五五三六?大家看这个标题,带宽隐形杀手。很多同学不知道, radis cluster 是 去中心化的,节点和节点之间需要不断地说悄悄话,这叫 gossip 协议, 它们每秒钟都要互相交换信息,哎,我还活着,哎!我负责哪些槽位?大家注意看右边这个动画,如果是六万五千五百三十六个槽,这个用来携带信息的心跳包, b map 有 多大? 算一下,八 kb, 你 看这个红色的方块,是不是跑的很慢,而且看着就很拥挤? ready 是 节点每秒钟都在疯狂发送这种包。 如果这是八 kb, 在 一个大 g 群里,这根本不是心跳,这简直就是内网的 ddos 攻击,网络瞬间就被打满了。反过来,如果是一万六千三百八十四个槽呢? 看上面这个绿色的小方块,只有两 kb, 哎,大家想一下,两 kb 和八 kb 差了四倍,对于内存和内存来说,这就是天壤之别。所以呢, radis 作者为了不让网络爆炸,强行把槽位数给砍下来了,这就是空间换时间的智慧。 好,那有同学又要杠了,老师,那砍到幺六三八四槽位够分吗?以后我要是搞个几万台机器怎么办?太天真了!大家看这个数字,一千 radis 的 官方作者 antirez 早就说过了, radis cluster 的 建议节点数最好不要超过一千个。 咱们算笔账,如果是一千个节点,分一万六千三百八十四个槽,平均每个节点分到多少?十六个槽,这足够做到负债均衡了吧?说实话,在座的各位,以后工作了,谁家公司能有一千台 radis 的 集群? 哪怕是阿里字节,大概率也是拆分成多个小集群,而不是搞一个巨无霸。所以呢,为了一个你永远达不到的万级规模,去牺牲每一秒的网络性能,这叫什么? 看屏幕上的单词, over engineering 过度设计,懂了吗?幺六三八四足够你用到退休了。 好原理讲完了,我们来看看生产环境会出什么问题。本视频的代码笔记,我整理进了两百万字的 java 与 ai 大 模型学习笔记里了,里面包含了三十多个技术站与几十个项目场景实战笔记,还有不同工作年限同学的简历模板,以及一份 java 加 ai 的 三十天面试突击学习路线,需要的话直接拿去。大家看这个图,这是面试常考题, redisk cluster 是 怎么处理请求的?假设你是一个笨客户端,你随便连了一个节点 a 想拿 key, 结果 redisk 发现,哎,这个 key 的 槽位不在我这儿,在隔壁老王节点 b 那 儿,它会给你数据吗?不会,它会给你退回来一个错误,叫 move 的。 这时候你的客户端就像被踢皮球一样,还得再发一次请求给节点 b, 同学们注意了,一来一回,这叫 double latency, 双倍延迟。 你的系统本来就慢,这么一搞更慢了。所以呢,开发的时候一定要用 smart clients。 比如 java 的 jess cluster, 它会在本地缓存一张地图 slot cache, 每次出门前先查地图,直接去找对的人, 别像个无头苍蝇一样乱撞。最后我们讲一个高频生产事故,很多同学喜欢用 make it 批量查数据,比如一次查十个用户的订单,在单机 ready 上没问题,但在 cluster 里直接报错。 看这个红色的 cursor error, 为什么?因为 user info 可能在节点 a, user orders 可能在节点 b, reddis 不 支持跨节点去给你聚合数据,这时候怎么办?难道要在 java 代码里写个 for 循环一个个查吗?那性能太拉胯了。来看右边的解决方案, 我们用一个大括号把关键的 id 包起来,这就叫 reddit。 reddit 看到大括号就只算大括号里面的哈希值,这样就能强行把 info 和 orders 锁进同一个 slot, 也就是在同一个节点上,这样 m get 就 能用了。 这就是架构师必须掌握的数据局部性优化。好。最后总结三句话,以后面试官再问你为什么是幺六三八四,你就把这三点甩给他。第一,为了省贷款,二 kb 的 心跳包比八 kb 香太多了,防止内网风暴。 第二,规模够用了,一千个节点顶天了,别搞过度设计。第三,开发要注意,一定要用 smart client, 一定要会用 hashtag 解决批量操作。

好,这一节我们来看一下 redis 常用操作秘密。 redis 主要是带领大家,呃,就是和大家一起回顾一下啊,回顾一下这个 我们经常使用的一些 redis 的一些命令啊,啊,无非就是像他的一个管理的命令啊,常见的一个什么管理的命令, 然后跟 key 啊,操作 key 相关的啊,可以操作。嗯,还有 super 啊, super 类型的呀,一盒类型的,还有这个六张,嗯,韩系,韩系类型的啊, 等等啊。呃,首先来看一下啊,这里就写到一个 小盆里面来,呃,启动 ready, 启动 ready 时我们可以,就是比如说你如果配置了那个 pass 就 就可以直接执行,我们一个是 plus, 你的并目就 release 杠 server 啊,就是这样来执行 release 杠 sewer, 那这个你嗯还可以指定参数啊,就是那你 redis come redis com 啊,在哪啊?我这随便写一下啊, 是你的那个 redis 点控这个配置文件啊,你放在哪了?呃,就是说还有你这个 加上 redis, 最简单的就是一一个就行了,还有 redis 看 so, 然后可以指定端口号啊,张张 port 啊,默认的是六三七九,那我可以直接六三八零是不是也可以啊?对, 好,这个是启动 redis, 启动 redis 之后我们就要进行连接啊,你配置的这个黄金边上 呃,系配置到了 pass 里面去了。看你这里就不需要点杠啊,你任意目录都可以执行,看,我这个是在呃 reds 杠 c r i 所在的目录就这样执行啊,最简单的就直接就这样可以连接,但是如果我想连接远程的啊, 这个二十七点零零表示连接本机的,但是你这个 ip 地址你可以指定其他的位置啊,六三八零幺三七九啊,根据 实际情况来连接。呃, release on c r i 那我也可以搭档啊,搭档就关,关闭, 停止是 release, 停止 release, 你还可以用 care 的,秘密就是你 release 用这个 p i d, 这个 p i d 是个字啊,不要这样去写,就是一个它的一个提成号儿啊,都可以删掉啊,都可以停止这个 release 啊。 oh, 那么你连接之后,嗯,你这连接进去之后,其实你是看联通性就直接性啊,那一般啊,如果是正常的,就是他会响应一个碰啊碰啊,那这个是 redis 常用操作命令,它 这里面的这个啊,启动命令以及连接相关的一些命令管理命令啊,这一节就先讲这里,接下来我们就讲这个可以操作的。


大家好,今天我们来聊聊 radis 的 持久化机制,二 d b 和 a o f。 二 d b 就是 radis that best a o f 就是 a b only five, 这是两种持久化机制。 那我们先说二 d b radis 的 一个快照,它是存储的紧凑的一个二级质文件, 非常节省空间,而且他呢非常适合一个快速的恢复数据恢复,他也适合一个数据备份,比如说我们瑞瑞斯的数据备份和主存同步都是基于二立币这种模式做的,但是他也有一些缺点,二立面他也有些缺点,他最大的缺点就是容易丢失数据, 他会丢失最近一次二立币备份的这个时间段内的数据, 这就是它的缺点啊。其实还有一个缺点是什么呢?因为我们二列 b 是 通过 fork 一个紫禁城来做的, 这个是这个它造成优点就是非常快速,有点不影响,不会主色,我们的紫禁城也就是不影响我们 radis 的 数据读写。 但是呢,对于一些大的数据机的二列 b, 它可能会这个紫紫禁城会有一些主色。 我们刚才说到啊,二 d b 适合做一个数据快速的恢复以及主存复制。那主存复制呢?它又分为两种,一个是增量复制和全量复制。 那我们第一次,比如说,呃,第一次从服务器要和主服务器做数据同步的时候,是一个做一个全量复制,就是说由从服务器发起一个 full size 全量同步的一个命令给主服务器,主服务器接受了命令的话,它就会执行 b c c 五,就是相当于是把 我们当前的数据做一个快照,保存一个二厘米文件,保存完二厘米文件,然后把这个二完整的一个二厘米文件发送给从服务器,从服务器拿到这个二厘米文件以后,他会删掉自己本地的一个数据库,然后重新读取这个二厘米文件, 不备份到自己的数据库中,这就完成了一个呃第一次的全量备份。呃,这时候呢?呃,因为我们 b g s 执行完以后,到从服务器同步完全完成同步这个文件,这个之间还会有一些写操作, 所以这时候呢啊,主服务器会把这个阶段的写服务器写数据写,写到一个一个八分里,专门做这个同步的八分里边啊。再从服务器 完全同步完这个二厘米文件以后,会把这个这部分的一个八分再发送给服务器,从而保证从服务器和主服务器达到数据的一致性。 啊,当我从服务器执行完全量备份以后,后续的备份就是一个增量的复制,增量复制呢是它依赖的并不是二 d b, 也不是 a o f, 而是单独的一个八份文件,就是主服务器会 把这个写写命令写到一个专门儿主动复制的一个 buffer 里边,然后从服务器呢,会通过 buffer 里这些大数据,通过一个 offset 来保证我们要同步哪些数据到从服务器, 这就是,呃, linux 的 主动复制,也就是利核心就是利用了 r db 机制。那我们说完 r db, 再聊一下 a o f avendony file, 它是什么?它的作用是什么呢?它相比于二 d b, 它的优点就是它会把每一条写命令都会记录在 a o f 文件里边, 就是最终这个效果就是达到数据的一个零丢失。当然它也有一些策略啊,比如说我可以呃每条写命令,我都做一个数据的 a o f 文件的写入,或者是 每秒写入 aof, 当然还可以是就是 no, 就是 不关闭这个,由操作系统来控制这个写入,这个信呢最好,但是也容易丢数据。虽然 aof 呢,它的呃信优点是不会丢数据,但是它有一缺点就是它的文件会非常的大, 因为它每一条写名里都会写入 aof 文件里边,这会就是它,所以说它不适合快速的恢复,快速恢复还是利用 rdb。 然后 a f 文件呢?它如果说我们一直往同一个文件里面写,会造成这个文件特别大,所以呢,我们需要通过 a o f 的 a o f 的 一个重写机制来避免这个 a o f 的 一个写膨胀。 它其一个重写机制呢,其实也是复合一个紫禁城来做,就是不引,不会堵塞这个紫禁城。 那它具体是这个重写是干什么呢?它并不是对这个 a o f 文件做一个编辑或者压缩,而是对这些 a o f 文件里边的一些命令做一个合并。比如说我们对一个那个自增的一个命令,我们一 increase 了 一千次,那我们这个重写的时候呢,会把这个命这些一千个命令合并成一个,我直接就是把它 a d d 一 千就完了, 这所以说这样能够保证这个 a o f 文件呃变小,就避免这个写文章。好,那我们今天就聊到这里,知己者知己所疑人,拜拜。