从redis主从复制学习系统设计

471 阅读4分钟

今天看《redis设计与实现》,学习了redis主从复制相关的知识,学习不总结就没有真正的提高,但也不想简单的把书中东西进行一次誊写,正巧最近做了很多次系统设计,下面就讲讲,我理解的从redis主从复制可以学习到的系统设计知识。我就从一个最简单的缓存模型开始,一步步的讲述下reids设计了哪些东西,为什么要设计这些,来更深刻的领会这些知识的使用场景。(我将讲述各个设计的考虑场景,引出更多的问题,为了促进思考和避免文章冗长,将不在文中赘述

首先,我们有一台主机和多台从机,主机上的数据需要同步到从机上。这个时候我们有两个方式将数据从主机同步到从机上,第一个将主机上的数据整体的发给从库,从库执行这些数据。第二个是将主机上的数据一条条的发给主机(大家可以了解下redis主从复制完全使用aof方式的问题,这个方案不做展开)。

如果每次都是整体发给从库,那么只有主库读很多写很少的场景才勉强可以使用,否则每次都要重新生成整体数据,性能一定超差了。redis现在做了第一步优化(并非实际上的构思顺序,只是为行文顺序),当客户端整体同步完成后,后续主机的命令可以通过命令传播的方式,传递给从机,这样就保证了主机和从机数据的一致。

其实进行到这一步,在某些业务场景下就已经满足了。但是redis毕竟是个大范围使用的中间件,要面临更大的流量,更加复杂的线上环境。比如主机如果挂了怎么办,命令传播阶段断开连接了怎么办。前者redis引入了runid,后者引入了积压缓冲区偏移量。积压缓冲区类似于业务系统中的本地缓存,我不清楚是否给你发送了,先记录在缓存当中。如果是我设计的话,肯定是每个从库都需要一个对应的缓存了,这样一来主库需要多份记录,二来主库需要对从库的增加有感知,增加了系统复杂度。大家可以看下redis怎么设计,带着情景思考肯定可以有不同的收获。

再说个命令传播阶段的设计细节。积压缓冲区1,.先进先出,2.固定长度。大家想一下为什么需要这样?redis通过环形数组实现了上面的两个要求,环形数组的实现大家可以了解下,redis真的是有很多设计将省内存进行到底。

说完了命令传播阶段,再简单说下整体数据生成时候的一个问题。如果生成数据的时候又有新数据发来怎么办呢,直接发给从库将会导致命令执行的顺序不一致,难道加锁不允许写入吗?redis使用了缓冲区的方式,这里的缓冲区每个从库对应一个,为什么积压缓冲区可以多个从库共享一个呢?

最后还有个整体设计的点,redis主从库建立连接后,主库相当于从库的客户端,从库也是主库的客户端,这样主库和从库其实是从业务角度理解的,从redis角度讲只有服务器和客户端。合理的抽象和封装,可以使得架构的复杂性降低,在命令传递阶段对于每台服务器而言都相当于接受命令,执行命令,不需要考虑主从的问题。

为了引发思考和不给互联网添加更多同质化的文章,所以本文留了很多开放问题。大家可以根据下面的参考文章去解惑,掌握了其中的机理,在设计存储高可用系统时就可以进行借鉴。如果有疑惑也欢迎留言讨论。

参考书目:《redis设计与实现》

参考文章:https://mp.weixin.qq.com/s/Vxg8DIaxPjSlSFBNtTvyIg