Git设计原理对业务系统设计与开发的启示

栏目: 编程工具 · 发布时间: 5年前

内容简介:作者简介近铁Jeff Dean, 饿了么物流研发部搬砖工, 崇拜各种大牛, 由于Jeff Dean的作品深而广, 本文特意专注于小而美的Linus Torvalds 第二作品:Git, 希望从中汲取营养, 向大师致敬。提示: 本文介绍Git核心优点和实现思路,重点引申出对业务系统设计与开发的启示; 由于篇幅有限,本文不详细介绍Git命令的具体执行细节,如果需要了解执行Git命令时,底层具体发生了什么, 请移步

作者简介

近铁Jeff Dean, 饿了么物流研发部搬砖工, 崇拜各种大牛, 由于Jeff Dean的作品深而广, 本文特意专注于小而美的Linus Torvalds 第二作品:Git, 希望从中汲取营养, 向大师致敬。

提示: 本文介绍Git核心优点和实现思路,重点引申出对业务系统设计与开发的启示; 由于篇幅有限,本文不详细介绍Git命令的具体执行细节,如果需要了解执行Git命令时,底层具体发生了什么, 请移步 Git官方文档第十章 Git Internals

为什么关注Git?

Git作为一个前无古人,很可能后无来者的内容地址跟踪器 , 席卷各大公司,深受所有 程序员 喜爱(觉得Git难用的除外), 肯定有他的过人之处。

先搬出互联网技术关键词标配:

分布式、去中心化、可靠性、容错性、可用性、数据一致性、性能是一个功能, 而不是一个优化等。

Git都满足有木有! Linus用两周就实现自举的Git十几年后依然健壮如初。 假如我写一个接口或设计一个微服务或写一个小工具, 自带扩展技能,从来不挂,QPS暴增也无需推翻重构,外部依赖抖动时自动降级,数据量增大而没有拖垮性能, 能与Git有很多共同点,岂不很有成就感?

Git最初设计时要达到的目的

分布式:1)多人同一个分支不同地点不同时间并行开发;2)单人本地多分支并行开发。

性能: 速度要快。慢是Linus Torvalds本人无法接受的,因为 linux 内核每天有成百上千次提交。

安全与信任: 即可靠性, 我push上去的代码pull下来一定还是我的代码, 没有丢失或被恶意篡改过。

Git 数据建模

插播一条语录: Bad programmers worry about the code. Good programmers worry about data structures and their relationships.- by Linus Torvarlds. (一般的程序员只关心代码,而优秀的软件工程师更关心数据结构以及他们之间的关系。)

启示

Linus本人写 C语言 比较多,个人认为这里的data structures and their relationships 如果脱离C语言 的特定背景,可以泛指技术对场景或业务逻辑的抽象, 比如: 面向对象建模,领域驱动, 甚至更宏观的架构设计或微服务怎样划分。

根据个人经验,如果系统设计的好, 代码稍微写low一点,整个系统的表现也不会太差, 而且代码的坑比较容易填; 反之,再漂亮的代码也很难填上系统设计的坑, 只能面临重构。

Git 内部文件处理:

  1. 代码库里所有文件都是数据,以数据为中心,所有操作、存储和处理逻辑围绕数据展开。
  2. 跟踪整个项目整体状态,每次建立全局快照,而不是跟踪每个文件的变更。
  3. 针对git目录下的每个文件计算一个hash值, 文件内容作为value, hash值为文件key。
  4. 如果单个文件内容发生变化, 下次重新计算hash值。如果文件没有发生变更,当前快照指向历史hash。
  5. 整个代码库的变化历史和文件组成用树形结构表示。
  6. Git每次commit记录整个代码库的一次快照, 当前快照包含发生变化的文件和历史快照(子树)。
    Git设计原理对业务系统设计与开发的启示
    Git数据建模

Git 执行效率与时间复杂度

对于Git内部结构可以简单的理解为: Git内部是一棵树, 每个节点都是一个指针(key), 这个指针(key)可能代表一个文件,或一次commit或一个分支起点或一次merge或一个tag, key对应的value就是内容, 如果key是代表一个文件, value就是文件内容; 如果key是代表一次commit, value是一颗子树, 包含此次commit对整个项目的snapshot。

平时很多git操作都可以近似理解为: 在树上执行遍历查找O(lg(n)),切换指针O(1),然后根据指针取文件内容O(1))。 这些操作速度都是很快的,只有在网络交互,文件压缩与解压和计算diff时,人肉可以感知到有时间等待。

启示

  1. 数据结构和算法原来是这么用的,基本功还是要扎实呀。
  2. LeetCode还是要常刷的。
  3. 建模很重要。越好的设计模型离被推翻重构的距离越远。 关于架构设计和规划的 做技术选型和概要设计,P7级别的就要做到, 1年以后当别人接手时就不需要考虑重构,如果是P8的就有信心做到2年以后,而P9的则是3年或更长时间。 Git已经经历了超过10年的考验了。

Git 空间压缩与访问效率平衡

对于Git,近期发生变化的数据属于热数据,Git假设这些数据会被频繁访问或使用到。其他数据为历史数据。 对于热数据, 即使发生微小变化,Git也会全量冗余存储,提高访问效率。 当热数据文件数量达到一定值时,会触发打包压缩逻辑, delta差异存储,节省空间。

启示

对于不同的存储介质,例如db, redis, mq, 选用不同的存储逻辑或策略,以达到访问效率与存储空间的平衡。

Git 安全性与容错性

Git对文件内容和项目整体snapshot都使用hash值表示,hash值与内容一一对应, 如果文件内容被篡改或硬盘损坏 导致数据丢失,hash值校验都会失败。 此时Git设计时已经假设:

  1. 硬盘是随时崩溃的,即存储是不可靠的
  2. 有人恶意引入Bug或偷偷修改代码

启示

在分布式环境下,设计系统或接口,能否保持容错性,自带降级,建议多向自己提出假设:

  1. 网络是不可靠的。 接口调用timeout和失败是必然存在的, 逻辑应该怎样处理?是否自带降级技能。
  2. DB是会抖动的,缓存也会失效,主从延迟一定存在的,此时代码逻辑能否兼容?如果fail fast, 是否有报警机制?
  3. 对外的接口,调用方的传参要考虑最坏的场景,是否有合理的入参校验/防重/幂等处理?

Merge 算法思想: 三路合并

先找出两个分支的公共祖先, 然后两个分支分别与公共祖先diff,指出有冲突的地方。 Git merge并没有试图智能的去解决冲突,只是指出冲突,然后将merge交给最合适最高效的人去解决: 即引起冲突的开发者。

启示

  1. 选用最合理的数据结构、索引结构或算法思路,不断优化系统处理速度。
  2. 划清边界,只做自己最擅长和应该做的事情, 尽量保证高内聚,低耦合 。 微服务环境下,在设计系统时,应该多考虑: 各个服务调用时,不同的异常谁负责处理; 接口超时谁负责补偿; 数据一致性交给谁来保证等。

Linus Torvalds眼中好的代码和好的软件工程师

好的软件工程师要有good taste, 坚持不懈的追求用正确的方式解决问题。

好的代码, 举个例子:移除链表中某个节点

一般的代码, 用if else 判断边界值:

void remove_list_entry(entry)
{
    prev = NULL;
    walk = head;

    // Walk the list
    while (walk != entry){
        prev = walk;
        walk = walk->next;
    }

    //Remove the entry by updating the
    //head or the previous entry

    if(!prev)
        head = entry->next;
    else
        prev->next = entry->next;
}
复制代码

好的代码, 换一种写法,使正常处理逻辑可以兼容边界值:

void remove_list_entry(entry)
{
    //The "indirect" pointer points to the
    // *address* of the thing we'll update

    indirect = &head;

    //Walk the list,looking for the thing that
    //points to the entry we want to remove

    while ((*indirect) != entry)
        indirect = &(*indirect)->next;

    // .. and just remove it
    *indirect = entry->next
}

复制代码

启示

平时编码中对边界值的处理是否优雅?

现在一个变量的传递会经过多种编程语言和中间件,中间过程一般有序列化和反序列化, 给空对象赋默认值等逻辑, 怎样保证实际结果与预想的完全一致? 边界值处理不好,一是代码不好维护,二是容易引入Bug。 日常碰到的边界值有: null, int默认值0等。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

重构

重构

[美]马丁•福勒(Martin Fowler) / 熊节 / 人民邮电出版社 / 2015-8 / 69.00

本书清晰揭示了重构的过程,解释了重构的原理和最佳实践方式,并给出了何时以及何地应该开始挖掘代码以求改善。书中给出了70 多个可行的重构,每个重构都介绍了一种经过验证的代码变换手法的动机和技术。本书提出的重构准则将帮助你一次一小步地修改你的代码,从而减少了开发过程中的风险。一起来看看 《重构》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具