编程类开放书籍荟萃

关于开源图书有人在网络上做了大量整理,本文为大家刊载《免费的编程中文书籍索引》

书山有路勤为径,学海无涯苦作舟!

语言无关类

操作系统

智能系统

web服务器

版本控制

NoSQL

MySQL

项目相关

Web

大数据

编程艺术

其他

语言相关类

AWK

C/C++

CSS/HTML

Dart

Fortran

Java

JavaScript

PHP

iOS

Android

Python

Ruby

Shell

Go

Groovy

LaTeX

LISP

Lua

Haskell

R

Scala

Swift

Perl

Prolog

Vimscript

读书笔记及其它

读书笔记

测试相关

【编辑推荐】从零到百亿互联网金融架构发展史 (58/6260) »

回想起从公司成立敲出的第一行代码算起到现在也快三年了,平台的技术架构,技术体系也算是经历了四次比较重大的升级转化(目前第四代架构体系正在进行中),临近年底也想抽出时间来回顾一下,一个小公司从最开始的零交易到现在交易量超过百亿背后的技术变迁。

总体介绍

在互联网金融行业一百多亿其实也算不上大平台,也就是二级阵营吧,其实每次的架构升级都是随着业务重大推进而伴随的,在前一代系统架构上遇到的问题,业务开发过程中积累一些优秀的开发案例,在下一代系统开发中就会大力推进架构升级。一方面可以平滑过度,一方面公司资源可以大力支持,同时技术的小伙伴们可以使用到前沿的技术,更有开发的成就感,就这样我们大概也就是9个月就行系统架构一次升级,就到了我们现在的这套架构中。

很多网友经常会问,你们平台的TPS是多少呀,最大并发是多少呀,性能怎么样,说实话我们是一个小公司,最夸张也就上万人同时抢标,但是做为一个中型的互联网金融平台要做的事情也真的不少,远远不只是这些参数可以说的清楚;我们也不是什么高大上的平台,使用的技术也是目前比较主流开源产品,但在公司不断发展的过程中也遇到了很多的问题,也尽量去使用比较主流的、开源的、适合我们的一些解决方案来构建整个系统,在这里分享平台发展背后技术换代的变化,同时希望和大家多做一些交流,多提一些建议。

我们进行了四次大的架构变化,每代架构都用一句话来总结:

  • 第一代架构特点:业务比较集中、功能满足投资理财需求、快速上线
  • 第二代架构特点;分布式系统改造,平台化初具规模,各项垂直业务系统搭建上线、产品端极大丰富用户投资、大数据平台研究并使用
  • 第三代架构特点;SOA治理,使用zookeeper作为注册中心,dubbo做监控和调度中心;cas实现单点登录,使用shiro做权限控制
  • 第四代架构特点;全面启用微服务开发模式,springboot+springcloud技术桟做为第四代架构技术支撑

下面做详细介绍

第一代系统架构

2014年应该算是互联网金融元年,在之前其实已经有很多互联网公司用着各种模式在生存,一直不温不火,但是到2014年突然火爆了起来,首先是网贷之家,网贷天眼这种第三方网站流量突然增加,接着是媒体报道不断跟进,再后来就报出各种互联网金融公司获得XXX美元投资的报道越来越多,政策也慢慢明朗,于是很多大型公司(集团)也就趁着这股热潮跟进,其中就包括我们。

第一代系统最主要就是抢时间,公司希望用最短的时间内保证系统上线,那时候移动浪潮已经启动,于是决定优先上线移动端,网站可以暂不考虑。公司当时有PHP和Java两种开发语言技术储备,因为PHP在快速开发上面有着非常大的优势,因此决定采用前端PHP+后端Java这种模式。系统分成了三层:用户层:安卓和IOS移动端;接口层:php提供用户和交易接口;后端:后端有两部分,后台和定时系统。后台用PHP开发和接口层公用了一个系统,另一个是定时系统,负责计息、派息、到期等定时任务等使用了java开发。

基础服务和中间件,mysql做了最基本的主从来支持,第一代系统只是使用了mysql的主库,从库只是同步备份;memcached用来处理用户抢标的并发问题,也只用了这一块;ActiveMQ用来使用二级市场的转让撮合以及其它一些异步消息通知。项目部署:php使用apache部署,定时服务使用tomcat6来做应用服务器,使用lvs来做前端apache的负载,基本上第一代也就这些技术了,下面是第一代系统的架构图。

第一代系统上线之后,网站和H5(手机浏览器或者微信端)系统建设就变的特别突出,作为一个互联网金融公司没有官网不能忍,于是又开始马不停蹄的开始开发网站和H5系统,在这个期间PHP之前做的后台这块摘了出来,用java从新规划了一版,至此PHP就负责了网站、APP接口、H5这三个系统,三个系统共用的一个核心交易,java这边负责后台管理和定时服务,我们一般给这个架构叫做1.1代架构。

第1.1代系统架构图,绿色部分为变动部分

第一代系统的缺点是业务过于集中,仓促上线,后期问题较多

第二代系统架构

第二代系统的背景是随着公司业务量的快速发展,很多初期所欠的技术债务统统爆发,线上出现了很多问题,最严重的一次是给个别用户重复派息,各种被骂,现在记忆犹新。另一方各业务部门需求不断,公司产品需求不断,所以这个阶段就是忙着修复各种生产问题,一边还需要开发垂直业务系统。那段时间差点被逼疯了,第一代系统是封闭开发,回来还没缓过劲,这边又赶马上架,真是疼并快乐着。

第一个垂直子系统上线的是:合同系统,当时用户投标后没有一个合同,很多用户很不放心,就把优先级提到了前面。后来就单合同系统就改了三个版本,第一个版本只是生成pdf,第二阶段上线电子签章,第三个阶段加水印,自定义动态生成pdf;紧接着开发积分系统:用户邀请,投资等生产积分,用来兑换抵现卷等;抽离出消息系统:站内消息、短信、邮件等;上线监控系统、业务监控和服务监控,业务失败预警;各业务部门继续不断提需求,上线财务系统:财务人员统计核算金额;风控系统:监控异常用户,异常交易;给销售开发了销售系统;因为和很多第三方系统对接,又开发了对外接入系统。

一代系统做的很赶,产品界面又很烂,随即启动规划了网站2.0、APP2.0、H52.0,针对前端系统的需求,在后端开发了CMS系统来发布项目、公司的公告新闻等;第二代产品端普遍规划了很多大数据分析的一些需求,会在官网展示全量数据分析后投资偏好、投资的金额都跑到哪里去,前端用地图来展示,对于个人也会有还款日历,代收数据分析等,因为需要跑全量数据,在规划的时候都是设计离线来处理,将数据从mysql从库同步到mongodb的集群中,利用mongdo的mapreduce技术来处理大量的数据,于是我们的数据库层就变成下面的这个架构

mysql实时同步到mongodb,我们使用的是tungsten-relicator这个工具,会在mysql服务器端启动一个监控agent,实时监控mysql的binlog日志,同时在mongodb的服务器端也起了一个服务端,agent监控到数据变化后传送给服务端,服务端解析后插入到mongodb集群中以达到实时同步的效果,如上图,当初写了一篇文章来介绍:大数据实践-数据同步篇tungsten-relicator(mysql->mongo),其实这个工具在使用中,也不是特别的稳定,但是当初的选择方案并不多,幸好后期慢慢的熟悉后算是稳定了下来。

数据清洗系统我们大胆的使用了golang来开发,当时使用的golang版本是1.3吧,现在都1.8了,以前也是没有接触过也是锻炼了队伍,好在golang语言本身非常简洁和高效,虽然踩了N多坑,但是最终我们还是按时投产了;后来又使用了golang开发了一个后台,是在beego框架的基础上来做的。大数据分析系统后来又升级了一代,在前端的各业务系统,UI用户层做了很多埋点来收集用户数据,通过activeMQ传输接收最后存储到mongodb,在进行数据清洗,将清洗后的结果存入到结果库中,供前端业务系统使用;后来利用beego+echart重新做了一版数据分析系统。

大数据系统的架构图

因为后端数据库的压力不断增大,后端管理系统、业务系统均作了主从分离;后台管理系统增加缓存,启动了redis做缓存;使用nginx搭建了独立的图片服务器;第二代系统开发过程中,也是公司发展最快的阶段,上线了N多的活动。

第二代系统架构图:

稍等总结一下:
第二代架构上线了各业务系统,做了主从分离,搭建了大数据平台为以后更多的数据处理提供了技术基础
缺点:各业务系统切分之后,各项目之间调用复杂;后台系统繁多、各系统之间有单独的账户系统,运营需要来回切换完成平台运营监控

第三代系统架构

第二代系统开发完成之后,留给我们了三个问题很痛苦,第一个是随着业务系统不断增多,系统之间的调用关系成指数级别上涨,在第三代系统初期,我们又开发了很多基础组件,更是加剧了这个问题;第二个问题和第一个问题相辅相成,系统之间调用关系太多,如果移动其中一个子系统,可能需要修改关联系统的配置文件,重新启动服务,经常因为更新一个系统,其它系统也需要被动更新,投产和出问题切换很复杂;第三个问题是我们开发了很多的后台系统,但是账户没有统一,每个子系统有各自的账户中心,运营和业务人员需要来回登录才能完成日常工作,随着业务量增大这个问题也日益突出。

于是又开启调研、系统选型等,解决第一个问题就是引入SOA服务治理,通过服务的注册和发现解决系统之间的解耦,当时考察了很多,最后选型dubbo,原因无它,有大量群众使用基础该趟的水的趟过了。解决第二个问题就是引入配置中心,当时调研了360的Qihoo360/QConf、Spring的spring-cloud-config、淘宝 的diamond、还有百度的disconf,最后纠结半天选定了disconf,完美和spring cloud擦肩而过,但是正是从这里开始让我们注意到了spring-cloud、Spring-boot为第四代的架构选型做了基础,其实最后disconf也只是在少部分项目使用,也没完全推广开;解决第三个问题就是账户中心,使用了cas实现单点登录,shiro做权限控制,dubbo来提供登录后权限列表等服务端接口。

改造后的架构图

在这个基础上面,我们又抽离出来很多基础组件,comomn组件处理共用的基础类,包含字符类、日期类、加密类….,搭建了fastDFS集群来处理文件系统,做了redis集群的测试;单独开发了定时调度系统,将所有的定时任务统一集成到调度系统,那个系统需要定时任务都可以在页面自动添加调度策略;前端PHP做了系统改造,主从分离、静态优化等

在后来,公司又启动众筹平台的建设,这次系统完全采用java语言开发,app端采用混合开发模式,其中APP的所有一级页面全部采用原生开发,所有的二级页面都是H5+vue这种模式,后端全部采用dubbo做服务化,最终的架构如下:

图里面系统只罗列一部分,使用其它服务来代替

第三代系统启动了SOA服务治理,引入统一账户中心、基础组件;缺点是开发环境较复杂

第四代系统架构

人总是不满足,技术呢也总是希望可以使用最好架构体系,在三代系统架构的开发中,了解到了spring cloud和spring boot,在不断的学习之后,越发的感觉到springboot的便利性,快速开发的优点甚是喜爱,spring cloud体系也完全满足一个大型系统需要考虑的方方面面,微服务的概念不断的被提出来,以上为技术背景;另一方面国家开始严格要求P2P公司必须与银行存管,分析了银行的相关接口后发现如果严格按照规则走,我们的系统需要大改造,同时公司为了满足监管要求,又开发出白条相关产品也是一个大项目,趁着以上的两个背景,我们决定在进行银行存管和白条项目的同时全面拥抱微服务。

至于为什么我们要抛弃dubbo转而全面拥抱spring cloud原因有三,1、dubbo多年都没有更新了,spring cloud不断的在更新升级;2、dubbo主要做服务治理和监控,spring cloud几乎考虑了微服务所需要方方面面,比如统一配置中心、路由中心;3、spring cloud更是无侵并且完美和spring其它项目整合,开发效率更高。

既然选定了使用spring boot+spring cloud来改造,微服务技术选型这边就定了下来,那么如何开启改造呢,毕竟在进行新一代系统改造的同时也不能影响原有业务,其中最主要的问题就是最初的系统虽然都是按照分布式的开发模式来进行,由于老系统的原因有的系统还是共用了一个数据库,微服务要求每个独立的子系统有自己独立的库操作,别的系统如果需要修改或者查询子系统的数据,需要根据服务间接口调用来获取。因此计划先从新开发的项目和需要改造的项目中启用springcloud项目,别的系统暂时先通过路由器模式来通讯,最终的系统架构图如下:

在架构的这条路上面没有终点,变化就是永远的不变,架构的升级更是为了更好的支撑业务,二者相辅相成。

开源软件

在这几年中我们也想对开源世界做一点点贡献,总共开源了两个软件:

generator-web

在项目中大量使用了mybaits,我们对mybaits的generator做了改造,并且做了一个系统界面,方便根据相关参数自动生产相关代码(只需要设计好表结构,系统会自动生成mappper、Entity、dao层的代码),最后也开源了出来

generator-web

界面如下:

云收藏

为了锻炼技术学习springboot我们开发了一个云收藏的开源软件,使用的技术主要是springboot/Spring data jpa/redis/thymeleaf/gradle,功能主要是可以帮助用户在云端收藏、分享和整理自己的收藏夹。

favorites-web


作者:纯洁的微笑
出处:http://www.ityouknow.com/
版权所有,欢迎保留原文链接进行转载:)

给定一个数字数组,从这个数组里找出所有的数字组合,且各组合里的数字相加之和等于同一个数字

最近在做在线问卷考试的时候想到这么一个功能,在试卷内给定140分值的试题,从这些试题中随机生成一张100分值的试卷,这个想法的意思说成算法描述就是:

给定一个随意的数组,如[1,4,3,2,5,7,6,8,9],再给定一个数值,如10,要求:从数组中找出所有的组合,使组合内各数字的值相加等于10;如列出某些组合:[1,2,3,4],[2,3,5],[2,8]等等。

花了一上午的时间,把这个算法实现了(领导给我派了另外的活,我却在研究昨天晚上想到的算法问题,不太好吧?各位朋友,别告诉领导哦)。

题目分析:从题目中得出,由于组合内数字的个数不定,只要各数字相加之和等于固定的值就行,所以首先想到用递归的方式来处理,过程发下

假定数组为[1,2,3,4,5,6,8,7,9]

从第一个数开始,一共有三种状态:

(1)等于给定数,则结合缓存里的数产生一种组合并保存下来,再清空缓存并将除了此数之外的此组合的另外的数字存入缓存里

(2)小于给定数,则保存此数至缓存之后,给定数减去此数,然后进入下一次递归,之后将此数从缓存中删除,处理完之后,再跳过过此数,给定数不变,进入到下一次递归

(3)大于给定数,跳过此数,进入到下一次递归

 

经过这样处理之后,用递归的方法就实现了此算法,C#代码如下:

/// <summary> 
/// 给定一个数字数组,从这个数组中找出所有的组合,使组合中各数字相加等于一个给定数值 
/// </summary> 
/// <param name="nums">给定数组</param> 
/// <param name="num">给定数值</param> 
/// <param name="index">当前操作的数字在数组中的index</param> 
/// <param name="count">存储所有组合的可能数</param> 
/// <param name="results">存储所有组合的情况</param> 
static void NumCount(double[] nums, double num, int index, ref int count, ref List<List<double>> results) 
{ 
    //当前操作的数字=给定数值 
    if (nums[index] == num) 
    { 
        //保存此组合 
        results[results.Count - 1].Add(nums[index]); 
        count += 1; 
        //清空缓存并将除了此数之外的此组合的另外的数字存入缓存里 
        results.Add(new List<double>()); 
        for (int i = 0; i < results[results.Count - 2].Count - 1; i++) 
        { 
            results[results.Count - 1].Add(results[results.Count - 2][i]); 
        } 
        if (index == nums.Length - 1) 
        { 
            return; 
        } 
        //进入到下一递归 
        NumCount(nums, num, index + 1, ref count, ref results); 
    } 
    //大于给定数,跳过此数,进入到下一次递归 
    else if (nums[index] > num) 
    { 
        if (index == nums.Length - 1) 
        { 
            return; 
        } 
        //此组合无效,跳到下一递归 
        NumCount(nums, num, index + 1, ref count, ref results); 
    } 
    //小于给定数,则保存此数至缓存之后,给定数减去此数,然后进入下一次递归,之后将此数从缓存中删除 
    else
    { 
        if (index == nums.Length - 1) 
        { 
            return; 
        } 
        results[results.Count - 1].Add(nums[index]); 
        //给定数减去此数 
        var tempNum = num - nums[index]; 
        //进入到下一递归 
        NumCount(nums, tempNum, index + 1, ref count, ref results); 
        //将此数从缓存中删除 
        results[results.Count - 1].RemoveAt(results[results.Count - 1].Count - 1); 
        if (index < nums.Length - 1) 
        { 
            //再跳过过此数,给定数不变,进入到下一次递归 
            NumCount(nums, num, index + 1, ref count, ref results); 
        } 
    } 
}

运行结果:

 

这篇文章是我一个字一个字敲出来的,觉得好就给个赞吧,3Q

[装机配置讨论] 七周年来了,3000-15000+电脑配置推荐贴(2016年06月02日开贴备战618,持续更新中!)

想为WOW 7.0装机的又不急用的请等618!!重要的事情放最顶上了……不过为了守望装机的,我真没法拦你了,因为明天要开了。 you ga wa ka tai ke na ku yao~~
新浪微博[

http://weibo.com/tibitteam
此网页不属于本网站,不保证其安全性
继续访问       取消

http://weibo.com/tibitteam]
新浪博客[http://blog.sina.com.cn/tibitteam]
声明:此贴转载须注明出处和本人ID,可扩散!

七年了,估计大家已经换了2-3代配置了,我当初根本想不到能坚持如此之久,但是随着大家的认可,以及存在感和成就感的积累,逐渐坚持了下来,并且也算踏入了更专业的领域,甚至可以借用资源做到行业标准的测试了(国家3C 电源80PLUS),虽然很多项目的数据是无法公布的(具体物料号和3C单号都涉及商业原则),但是很多配置的兼容性和已经通过的标准后面可以写出来。让大家有一个更好的参考,性能方面的测试数据依然以真实为底线,并且很多会长期更新。如今,已经成为团队的我们,相信会做的更好!与大家共勉!

配置贴希望能给大家一个装机参考,但是不希望帖子成为桎梏,考虑灵活搭配的原则,多准备备选方案。配置不定期变动(或者有比较大的突变的时候),寻找最具性价比的明星产品,为大家服务!!请大家尽量不要PM我……问的人太多,有时候会屏蔽了PM,直接跟帖问吧。感谢一直帮我回帖的深田公子,枫子兔,天inspiration,至尊披萨,No3嘉拉迪雅,八坂穷勾玉等朋友,希望更多的朋友能从看贴受益到帮助更多的网友。

我不加QQ好友,不发推荐码,新手互助群215417875(现为二群,广泛接纳DIY玩家,无商家,尽力快速回复新手应急问题,一群人满暂时不加人了) 。其他精华帖链接在最后,另外其他散件补充贴非本人所写,有什么问题请问开贴人。

WOW从6.1版本大幅提高了显卡需求,重夺兵器谱第一的位置(极限特效是SSAA200%+MXAA8X+CMAA,其他最高),成为最依赖电脑配置的网游,没有之一!!由于6.1版本加入了NV的点光源技术,以及更好的优化技术,所以现阶段玩WOW,建议N卡。不过单机游戏方面270X和370X相对750TI还是有优势,280X和380相对960也是有优势,特此说明。
所有游戏卡顿,帧数不正常的看下面两贴,需双剑(贴)合璧才完美。
WOW6.1视频高级设置介绍[/read.php?tid=7893363]
WOW最优化攻略终极版,专治各种游戏帧数不服不正常 6.0版本[/read.php?tid=7622866]

个人看法:
特别注意:微软不再为INTEL的4系列、6系列及以后的CPU(即G3XXX,I3 I5 I7 4XXX及skylake的CPU)和主板(H81,B85,Z87,Z97及h110 b150 z170等)提供XP驱动支持,也就是说用不了WIN XP了,请纯办公或者还想用XP的网友特别注意!!!

CPU:AMD目前比较低迷,APU不给力,FX系列能耗比太低。新装机直接上INTEL的U吧,单核心性能强劲,更适合玩WOW。现在建议低端买G3258或I3散片(新平台可用G4400或I3 6100),中端用I5 6500,中高端请选4690K或E3(新平台6600K),高端的新平台6700K,发烧的考虑新的68XXK和X99平台。

关于CPU盒装和散片的差别在于是否是正规质保,原盒是3年质保(要留好包装和散热器),而散片(无散热器,就一个CPU)大多是店铺质保一年(需要注意国内OEM厂商散片是质保三年的),所以新手买散片尽量从本地电脑城购买,淘宝买风险比较大,一旦出问题扯起皮来很麻烦。

兔大师(枫子兔,硬件区里疯狂积累人品的兔子)详解INTEL系列CPU补充:
包括WOW在内的大型网游里,建筑和NPC的建模、游戏AI运算、游戏内各种数据计算、游戏插件计算,这些工作都需要CPU来做.显卡只负责特效部分,但显卡特效是可以根据实际情况调整的,这部分其实不是什么事儿.越是满地人/NPC、各种建筑、密密麻麻的花花草草、各种飘数字的地儿,CPU的压力就越大. CPU的整体性能决定了大型网游里高负荷场景下的最低帧数水平.对于CPU的要求,无非就是:同频率的CPU更依赖架构效率也就是核心效能;同架构效率下更依赖CPU主频;大量AI运算需要大容量低延迟高命中率的共享缓存.
i5 和 E3/i7的选择问题:i5 和 E3/i7 的选择取决于你的实际需求. 以日常应用和游戏为主,上i5就没压力.
如果你日常有 一定工作量 的渲染/建模/转码/作图、工作室级别极限多开游戏,HT超线程技术就能发挥比较大的用处,就有必要上E3/i7.
别说什么i5 E3一样价,中文原封、行货带散热器官方三年保 和 散片、水货店家一年保 是没有可比性的. E3 V3中文原封什么价京东自己查.
只有你有上述那些使用需求的前提下,加上E3相比同功能的i7不带k散片的价格差(少了核显),E3才有性价比.
需要正规发票/增票的且需要走B2C可以选i7不带k. 在此需求基础上想要超频的,就选i7带k.
如果没有上述需求,选E3那就是基本白扔300块的节奏. 说什么为将来打算的,准备开工作室极限多开挂机当然没问题,但其它的那些专业应用、除非你准备0基础起步换行业,否则也是用不到.但是强迫症、不差钱、无脑跟风的,那就只好慢走不送了.

主板:低端买G3258+B85,中低端可以买I3 6100+B150,中端6500+B150,中高端性价比搭配选4690K/E3V3/4790K+一线B85组合( 新E3 1230 V5需要搭配X150才可以,性价比比原来低了一些),高端的考虑6700K+一线精良做工的Z170,发烧可上X99平台。具体选购细节可以看下网友black_hawk写的[/read.php?tid=7739622]

内存:不超频直接电商买金士顿不纠结,正品金士顿的内存条兼容性做的很好。实体店千万别买金士顿普条(fury和savage等马甲条可买),选芝奇,威刚或者金邦的。DDR4方面建议2400的即可,高频还是处于比较高的价格。另外如果搭配华硕X99主板,则不建议选择芝奇内存,考虑性价比选择金士顿,考虑逼格则选择海盗船统治者。

显卡:因为6.0大幅提高了显存占用,建议最好用2G或更大显存的显卡。6.1再次大幅提升了显卡需求,对N卡有了优化,建议纯WOW玩家买N卡。
N卡低端买750,800以内买750TI(2G版本),950如降到950块左右可以买,1200-1500元买960,2200左右买970,3000出头买980,土豪买980TI,泰坦X。切记610,630,640,720,730等等是垃圾。。游戏建议750起。
A卡现在低端各种缺货不给力,直接中端1100左右买370X,中高端1500左右买4G版本380,再往上能耗比太低,还是买N卡吧。喜欢三年保又不在乎价格的可以考虑华硕、微星、技嘉。54XX 55XX,64XX,65XX,66XX是垃圾~~~另外R250性价比低也不建议购买。

机械硬盘:非存储专用别买西数绿盘,会影响游戏体验,尽量买蓝盘,黑盘意义不大,噪音反而会大。长期开机和监控录像类建议用企业级,数据安全第一,别光看省钱。500G和1TB价差很小了,直接上单碟1TB的,希捷西数都看脸,随便选吧。

SSD(固态硬盘): SSD只会改善读蓝条速度,不会影响游戏帧数!!另外没事别折腾固态硬盘的固件,除非这个固件已经得到广大小白鼠和大神的验证!!建议预算低买OCZ arc100(120G 379元,240G 599元),预算足且要求性能和质保给力就买INTEL 730(目前只有淘宝有了)。
SSD选购贴[/read.php?tid=7442061],非本人贴,请问开贴人。

电源:首选台系或台系代工电源 !!尽量网购!!详情请看菲娅大师的讲解[/read.php?tid=6131614&_fp=3]
主要推荐的是台达NX350(如无货则考虑安钛克VP350P,注意安钛克是两年质保了,比一般少一年) RS450 NX550,全汉的RA、经典PLUS和AS系列,海韵G,X,P系列,不考虑性价比可选择海盗船高端的RM及以上系列。

机箱:机箱板材(SECC SPCC区别自己百度)外观、内部设计、做工、导热风道、免工具设计、防尘静音设计、风扇集线器/调速器、喷漆品控、前面板接口、按键材质质量、前面板延长线线径等等,一样可以天差地别,所以硬件区经常会标配200元+的机箱。

显示器:为了大家的眼睛,请不要选择20,21.5这几个尺寸的显示器,点距太小!!大家切记,别只为省钱损害健康!!18.5的是分辨率不给力,也不推荐购买。想买16比9的就买23或者27的,想买16比10就买22或24的,再大尺寸看个人喜好了,但是一般显示器尺寸越大,标准分辨率越高,对机器的配置的需求也越高!!
网友sujkypc的研究帖子[/read.php?tid=6204856&_fp=3]

外设各有所爱,希望大家去实体店体验再决定购买!!实体店价格坑爹的话试好手感走商城网购!!

注意:
关于AMD显卡VPU重置或者驱动未响应的问题,兔子的贴[/read.php?tid=4923570&_fp=1]

更新记录:
2016年5月23日:7周年发帖,逐渐更新618配置。
2016年6月02日:更新部分配置,详细实时活动讨论帖见此贴 [/read.php?tid=9395325]

3000元级(办公,普通家庭应用)
———————————————————————————————————————–
解析:这个价位3000带显示器基本都是入门配置,但是价格低并不代表性能低下。如果平时只看看股票、上上网、看电影、玩普通的网页游戏和网络游戏(大话,梦幻2D)的话,这套配置完全可以胜任!!另外伪办公配置,大家懂得,想玩WOW自己加显卡就是,但是需要注意4系列6系列主板不支持XP。
老平台的优势在于G3258可以超频,随便超一下4-4.2G还是完全胜过G4400的,当然G4400的核显要比G3258的核显强。如何取舍看各位选择了。

注:此配置在G32XX-I3全系列CPU下,可过3C。G3258超频主频不同,没法提交。

CPU:INTEL G3258盒 459元(公司不让买超频的用G3250)
主板:技嘉B85M-D3V-A 449元(带打印口,备选华硕B85M-D PLUS 439元带打印口)
内存:金士顿 DDR3 1600 8G 189元 (备选芝奇Ripjaws DDR3 1600 8G 199元特价,实体店别买金士顿普条)
硬盘:希捷1TB或西数蓝盘1TB 319元(质量都是完全看脸)
光驱:先锋DVR-221CHV 125元(不需要就不选)
机箱:酷冷毁灭者经典U3版 229元
电源:台达NX350 219元(备选安钛克VP350 219元 )
键鼠:自选
显示器:IPS漏光比TN严重,可视角度比TN好,MVA处于两者之间,个人取舍吧
IPS屏 AOC I2476VWM 739元(满100-10块后的价格,16比9 IPS屏备选戴尔P2314H 1089元 也是满100-10块后的价格)
备选
MVA屏 明基(BenQ)EW2440ZH 819元(满100-10块后的价格)
共计:3000元左右

注:此配置在G系列-I3全系列CPU下,可过3C。

SKYLAKE新平台低端入门配置(以后可以自己加个显卡玩点网游)
CPU:INTEL G4400盒 419元
主板:华擎B150M-HDV 499元(备选技嘉H110M-DS2,H110价格都还是比较贵的,性价比不高)
内存:金士顿 DDR4 2133 8G 199元
硬盘:希捷1TB或西数蓝盘1TB 319元(质量都是完全看脸)
光驱:先锋DVR-221CHV 125元(不需要就不选)
机箱:酷冷毁灭者经典U3版 229元
电源:台达NX350 219元(备选安钛克VP350 219元 )
键鼠:自选
显示器:IPS漏光比TN严重,可视角度比TN好,MVA处于两者之间,个人取舍吧
IPS屏 AOC I2476VWM 739元(满100-10块后的价格,16比9 IPS屏备选戴尔P2314H 1089元 也是满100-10块后的价格)
备选
MVA屏 明基(BenQ)EW2440ZH 819元(满100-10块后的价格)

4000元配置,低阴影,关AA,SSAO和反射流畅玩WOW。用G3258的可参考本人类似作业含超频教程[/read.php?tid=7421884]
另外如果用G3258超频不要用WIN10操作系统,切记!
解析:老平台和新平台实际性能差不多,6100的核显还是比4170的强。
注:此配置可过3C。

CPU:4170散片 650元(想玩超频的可以玩玩G3258,不过仅仅做为过渡吧,后面还是得上I5玩游戏)
散热:采融B48 99元(备选九州风神 玄冰400)
主板:技嘉B85M-D3H 499元(现在为rev1.2版本了,没有缩水,2.0已经被憋回去了,大家放心购买,备选华硕B85M-E R2.0 469元 这个买REV2.0版本,别买1.0版本 )
内存:金士顿 DDR3 1600 8G 219元(备选芝奇Ripjaws DDR3 1600 8G 199元特价,实体店别买金士顿普条)
显卡:华硕750TI 2G圣骑士 819元 (备选技嘉GV-N75TD5-2GI GTX750Ti 819元)
硬盘:希捷1TB或西数蓝盘1TB 319元(质量都是完全看脸)
光驱:先锋DVR-221CHV 125元(不需要就不选)
机箱:酷冷毁灭者经典U3版 229元
电源:台达 NX350 219元(备选安钛克VP350 219元 )
键鼠:自选
显示器:IPS漏光比TN严重,可视角度比TN好,MVA处于两者之间,个人取舍吧
IPS屏 AOC I2476VWM 739元(满100-10块后的价格,16比9 IPS屏备选戴尔P2314H 1089元 也是满100-10块后的价格)
备选
MVA屏 明基(BenQ)EW2440ZH 819元(满100-10块后的价格)

SKYLAKE新I3配置
注:此配置可过3C。

CPU:INTEL I3 6100 散片 680元左右
散热:采融B48 99元(备选九州风神 玄冰400)
主板:华硕B150M-PLUS 699元(京东送内存或散热的价)
技嘉B150M-D3H 599元(特价,一般也是699送内存或者散热)
内存:金士顿 DDR4 2133 8G 199元
显卡:华硕750TI 2G圣骑士 819元 (备选技嘉GV-N75TD5-2GI GTX750Ti 819元)
硬盘:希捷1TB或西数蓝盘1TB 319元(质量都是完全看脸)
光驱:先锋DVR-221CHV 125元(不需要就不选)
机箱:酷冷毁灭者经典U3版 229元
电源:台达 NX350 219元(备选安钛克VP350 219元 )
键鼠:自选
显示器:IPS漏光比TN严重,可视角度比TN好,MVA处于两者之间,个人取舍吧
IPS屏 AOC I2476VWM 739元(满100-10块后的价格,16比9 IPS屏备选戴尔P2314H 1089元 也是满100-10块后的价格)
备选
MVA屏 明基(BenQ)EW2440ZH 819元(满100-10块后的价格)

6000元性价比配置(主流网游高效果没啥问题,这个价位段基本没法什么追求配色,侧不侧透无所谓,加不加固态看大家预算了。)
本人类似作业,老i5和E3V3对比[/read.php?tid=7479566]
解析:新老I5 4590和6500对于玩家来说基本没什么感觉,目前两套配置价格基本相当了,建议I5可以用skylake配置,E3用老配置

6000左右 skylake新平台 I5 配置(加不加固态看大家预算,也可以后面再加) 注:此配置可过3C,如用机箱QT01侧透无法过。并不是机箱不好,是3C标准下,带侧透的都无法提交通过。所以即使DELL外星人也不是侧透。

CPU:I5 6500/6600散片 1200-1300元
散热:采融B48 99元(备选九州风神玄冰400 99元)
主板:华硕B150M-PLUS 699元(京东送内存或散热的价)
技嘉B150M-D3H 599元(特价,一般也是699送内存或者散热)
显卡:技嘉960WF 4G 1499元 (华硕猛禽STRIX 960 4G 1499元 逐渐用4G代替)
内存:金士顿 FURY DDR4 2400 8G 229元
固态:金士顿HyperX Fury 240G 499元
硬盘:希捷1TB或西数蓝盘1TB 319元(质量都是完全看脸)
机箱:酷冷毁灭者经典U3版 229元(预算足可选择QT01)
电源:全汉经典PLUS450 329元(RA系列逐渐停产,备选台达RS450 329元)
光驱:先锋DVR-221CHV 125元(不需要就不选)
键鼠:自选
显示器:IPS漏光比TN严重,可视角度比TN好,MVA处于两者之间,个人取舍吧
IPS屏 AOC I2476VWM 739元(满100-10块后的价格,16比9 IPS屏备选戴尔P2314H 1089元 也是满100-10块后的价格)
备选
MVA屏 明基(BenQ)EW2440ZH 819元(满100-10块后的价格)
共计:6000元左右

渲染多开党用这个配置(加不加固态看大家预算)
注:此配置通过兼容性认证,未提交3C认证。

CPU:E3 1231V3 1450元
散热器:
采融B48 99元(非常容易拆装)
九州风神玄冰400 99元(散热好点,但是不易拆装)

主板:技嘉B85M-D3H 499元(现在为rev1.2版本了,没有缩水,2.0已经被憋回去了,大家放心购买,备选华硕B85M-E R2.0 469元 这个买REV2.0版本,别买1.0版本)
显卡:技嘉960WF 4G 1499元 (华硕960 strix战枭版4G 1499元 2G版本960陆续停产,逐渐用4G代替)
内存:金士顿 DDR3 1600 8G 219元(备选芝奇Ripjaws DDR3 1600 8G 199元特价,实体店别买金士顿普条)
硬盘:希捷1TB或西数蓝盘1TB 319元(质量都是完全看脸)
机箱:酷冷毁灭者经典U3版 229元(预算足可选择QT01)
电源:全汉经典PLUS450 329元(RA系列逐渐停产,备选台达RS450 329元)
光驱:先锋DVR-221CHV 125元(不需要就不选)
键鼠:自选
显示器:IPS漏光比TN严重,可视角度比TN好,MVA处于两者之间,个人取舍吧
IPS屏 AOC I2476VWM 739元(满100-10块后的价格,16比9 IPS屏备选戴尔P2314H 1089元 也是满100-10块后的价格)
备选
MVA屏 明基(BenQ)EW2440ZH 819元(满100-10块后的价格)
共计:6000元

分水岭:以下带K CPU配置,均可通过兼容性认证,但是由于机箱侧板问题和配件物料更新太快,均未提交3C认证。

6000-7000+配置(网游1080下特效全开,更适合WOW类副本和大型团战,单机中高特效)

红黑配色
CPU:I5 4690K散片(工作有渲染需求也可用E3V3散片)/ i7 4790K散片 1400元/2000元
主板:华硕B85PRO GAMER 699元
散热:采融B81 208元(追求外观就单独买,不追求的话也可以买套装)
内存:金士顿fury ddr3 1600 8G 229元(B85只能让内存跑在1600频率上)
显卡:华硕960strix 4G 1499元
硬盘:希捷1TB或西数蓝盘1TB 289元(质量都是完全看脸,预算够又追求速度的上SSD)
电源:台达NX550 499元
机箱:迎广703 349元(红黑,预算高可上H440红黑版)
显示器:IPS漏光比TN严重,可视角度比TN好,MVA处于两者之间,个人取舍吧
IPS屏 AOC I2476VWM 739元(满100-10块后的价格,16比9 IPS屏备选戴尔P2314H 1089元 也是满100-10块后的价格)
备选
MVA屏 明基(BenQ)EW2440ZH 819元(满100-10块后的价格)

绿白配色
CPU:I5 4690K散片(工作有渲染需求也可用E3V3散片)/ i7 4790K散片 1400元/2000元
主板:技嘉G1 sniper B6 699元(注意鲁大师识别为b5-cf,别误认为是假货)
散热:采融B81 208元(追求外观就单独买,不追求的话也可以买套装)
内存:金士顿 fury ddr3 1600 8G 229(B85只能让内存跑在1600频率上)
显卡:技嘉960WF 4G 1499元
硬盘:希捷1TB或西数蓝盘1TB 289元(质量都是完全看脸,预算够又追求速度的上SSD)
电源:台达NX550 499元
机箱:恩杰H240 389元(预算高可上S340或H440白色版)
显示器:IPS漏光比TN严重,可视角度比TN好,MVA处于两者之间,个人取舍吧
IPS屏 AOC I2476VWM 739元(满100-10块后的价格,16比9 IPS屏备选戴尔P2314H 1089元 也是满100-10块后的价格)
备选
MVA屏 明基(BenQ)EW2440ZH 819元(满100-10块后的价格)

9000-10000元区间 SKYLAKE 带K配置 特别注意:618时NV新卡可能就可以买到了,不急的朋友可以等1070和1080上架!!
解析:用稍微低一级别的Z170一线大厂主板,考虑U体质不同,散片价格低,所以尽量控制在4.4-4.5安全范围之内,日常应用稳定即可,不要频繁用软件拷机!

skylake 6600K/6700K 不大幅超频配置(超频幅度控制在4.4-4.5G)
CPU:I5 6600K 散片 1500元 / I7 6700K 散片 2100-2200元
主板:
华硕Z170-A 1099元
技嘉Z170X-UD3 1099元

散热器:采融B81 208元(非常容易拆装,搭配侧透机箱好看)
显卡:等970降价或NV新卡1070上市
内存:主板赠送(如果不赠送了可选金士顿fury ddr4 2400 8G 229元)
SSD:OCZ Vector180 240G 629元
机械硬盘:自己酌情添加。
机箱:恩杰H440 549元(特价时可499元)
电源:台达NX550 499元(备选海韵G550 全汉AS550 不求性价比的选海盗船RM550X)
光驱:先锋DVR-221CHV 125元
键鼠:自选
显示器:
DELLU2414H 1399(满100-10块最低价,16比9,建议自备HDMI线材)
DELLU2415 1999(16比10)
总价 9000-10000元

11000-13000+级别 skylake平台,6700K实际性能和4790K差不多,虽然超频电压会高点,但是温度会低一些。 显卡方面我个人认为选择1070会更有性价比,有更高游戏需求的玩家可加钱升级显卡到1080。

CPU:I7 6700K 2599元(京东自营原盒价格,散片2100-2200之间,不大幅超频可入)

散热器:采融B81 208元(非常容易拆装,搭配侧透机箱好看)

主板:(二选一,根据自己喜好和配色选吧)
华硕Z170progaming 1499元
技嘉Z170X-Gaming 5 1499元

显卡:NV新卡1070 预计3299左右(预算足直接1080 5399预定)

内存:选金士顿fury ddr4 2400 8G 239元(觉得小了可以自行再添加8G)
SSD:饥饿鲨(OCZ) Vector180 240G 629元
机械硬盘:自己酌情添加。
机箱:恩杰H440 549元(根据自己配色选黑或者白 H440没有光驱位,特别注意)
电源:台达NX550 499元(备选海韵G550 全汉AS550 海盗船RM550,如用980TI则要选择海盗船RM650或海韵X650)
光驱:先锋DVR-221CHV 125元
键鼠:自选
显示器:
DELLU2414H 1599(16比9,建议自备HDMI线材)
DELLU2415 1999(16比10)

配置贴历史链接:
配置贴第一帖 [/read.php?tid=2411978&_fp=3&forder_by=postdatedesc] (09年5月23日-10年7月3日)
配置贴第二贴 [/read.php?tid=3459224] (10年7月3日-11年5月22日)
配置贴第三贴 [/read.php?tid=4274774&_fp=5] (11年5月23日-12年5月22日)
配置贴第四贴 [/read.php?tid=5183044&_fp=4] (12年5月23日-13年5月22日)
配置贴第五贴 [/read.php?tid=6251146&_fp=2] (13年5月23日-14年5月23日)
配置贴第六贴[/read.php?tid=7088772](14年5月23日-15年5月23日)
配置贴第七贴[/read.php?tid=8192610](15年5月23日-16年5月23日)

WOW优化贴:
WOW6.1视频高级设置介绍[/read.php?tid=7893363]
WOW最优化攻略终极版,专治各种游戏帧数不服不正常 6.0版本[/read.php?tid=7622866]
WOW最优化攻略终极版,专治各种游戏帧数不服不正常(最老版本) [/read.php?tid=6120346&page=1]

外设类:
求人不如求己,自己研究电脑桌椅的一点心得[/read.php?tid=4267632&_fp=1]
人工学座椅长期体验对比贴 [/read.php?tid=8116474&_fp=2]

杂项问题:
DDR3 1333/1600如何设置的图片教程以及我的参考建议(内存小参讲解设置以及优化指南)[/read.php?tid=3147679&_fp=7]

天大的散热专题:百元散热以及安装视频 [/read.php?tid=8276621]

轮子妈的阉割版系统帖子,skylake平台可直接U盘安装(不过不适合4代以前的平台装系统) [http://nga.178.com/read.php?tid=9272958]

http://bbs.ngacn.cc/read.php?&tid=9363428

使用原理视角看 Git

1. Git 的玩法

欢迎来到 Coding 技术小馆,我叫谭贺贺,目前我在 Coding.net 主要负责 WebIDE 与 Codeinsight 的开发。我今天带来的主要内容是 Git 的原理与使用。

谈起 git,大家的第一印象无非是和 svn 一样的版本控制系统,但其实,他们有着非常大的不同,至少 svn 没有像 git 一样这么多的玩法。下面我举几个例子,简略的说一下。

1.1 搭建博客

阮一峰将写 blog 的人分成三个阶段

使用免费空间,比如 CSDN、博客园。
发现免费空间限制太多,于是自己购买域名和空间,搭建独立博客。
独立博客管理太麻烦,最好在保留控制权的前提下,让别人来管,自己负责写文章。

其实第三种阶段指的就是使用 Pages 服务。很多公司比如 Coding、Github 等代码托管平台都推出了 Pages 服务,可以用来搭建个人博客。Pages 服务不需要复杂的配置,就可以完成博客的搭建。

在使用 Pages 的过程中,通过使用标记语言(Markdown)完成博客的编写,推送到服务器上,就可以看到新发布的博客了。

不需要管理服务器,降低了搭建博客的门槛,同时又保持了用户对博客的高度定制权。

1.2 写书

很多牛人喜欢写博客,博客写多了,然后汇集起来就出了本书。比如 Matrix67《思考的乐趣》、阮一峰《如何变得有思想》就是这样的例子。

其实出书距离我们也并不遥远,为什么?因为有 gitbook 这类服务。

对于 git + Pages 服务的用户,gitbook 很容易上手,因为使用 gitbook 就是使用 git 与 markdown。
你完全可以将你 markdown 的博客 copy,汇集起来,形成一本书籍。内容的排版 gitbook 会帮你做,我们只负责内容就可以了。编写好内容,我们就能立刻获得 html、pdf、epub、mobi 四个版本的电子书。这是 html 版的预览:

图片

在 gitbook 上有 explore 频道,上面列出了所有公开的书籍(当然也可以直接搜索)。

图片

实际上,除了写书,还可以连同其他人一起进行外文资料的翻译,举个例子《The Swift Programming Language》中文版,将英文版分成几个部分,然后在开源项目中由参与者认领翻译,每个人贡献一份自己的力量,完成了这样以非常快的相应速度跟随官方文档更新的操作。如果你喜欢的一门语言,或者技术,中文资料缺乏,大家可以发起这样的活动,完成外文资料的翻译。

1.3 人才招聘

人才招聘这一块,至今还并没有形成一定的规模。但仍旧有很多的公司选择在代码托管平台上(比如 Coding、Github)上寻找中意的开发者。

有一些开发者看准了这一块,专门开发了这样的网站,比如 githuber.cn、github-awards.com。

拿 githuber 举例,该网站主要提供两个功能,第一个是星榜,说白了将所有所有用户按照语言分类,然后根据粉丝数(star)排序。

图片

我们可以很容易的看到排行榜上前几位的用户,他们的开源项目,这在一定程度上能代表这门语言的发展趋势。比如我对java比较感兴趣,然后我看了一下前十名,发现大部分都是 android 开发,由此可见android开发的火爆程度。

当然你也可以看到你的排名,会让你有打怪升级的快感。

第二个功能是搜索,输入筛选条件,搜搜程序员!

图片

1.4 WebIDE

Coding WebIDE 是 Coding 自主研发的在线集成开发环境 (IDE)。只要你的项目在代码托管平台存放,就可以导入到 WebIDE。之后就可以在线开发。

图片

WebIDE 还提供 WebTerminal 功能,用户可以远程操作Docker容器,自由安装偏好的软件包、方便折腾。

看起来是不是还挺好玩的,如果想把这些都玩转,git 是肯定要好好学的。接下来,我们就看一下 git 的基本原理。

2. Git 原理

我们可以现在想一下,如果我们自己来设计,应该怎么设计。

传统的设计方案我们可以简单的分成两块:工作目录,远程仓库。

图片

但是作为一个目标明确的分布式版本控制系统,首先要做的就是添加一个本地仓库。

图片

接着我们选择在工作目录与远程仓库中间加一个缓冲区域,叫做暂存区。

图片

加入暂存区的原因有以下几点:

  1. 为了能够实现部分提交
  2. 为了不再工作区创建状态文件、会污染工作区。
  3. 暂存区记录文件的修改时间等信息,提高文件比较的效率。

至此就我们本地而言有三个重要的区域:工作区、暂存区、本地仓库。

接下来我们想一下本地仓库是如何存放项目历史版本。

2.1 快照

图片

这是项目的三个版本,版本1中有两个文件A和B,然后修改了A,变成了A1,形成了版本2,接着又修改了B变为B1,形成了版本3。

如果我们把项目的每个版本都保存到本地仓库,需要保存至少6个文件,而实际上,只有4个不同的文件,A、A1、B、B1。为了节省存储的空间,我们要像一个方法将同样的文件只需要保存一份。这就引入了Sha-1算法。

可以使用git命令计算文件的 sha-1 值。

echo 'test content' | git hash-object --stdin
d670460b4b4aece5915caf5c68d12f560a9fe3e4

SHA-1将文件中的内容通过通过计算生成一个 40 位长度的hash值。

Sha-1的非常有特点:

  • 由文件内容计算出的hash值
  • hash值相同,文件内容相同

对于上图中的内容,无论我们执行多少次,都会得到相同的结果。因此,文件的sha-1值是可以作为文件的唯一 id 。同时,它还有一个额外的功能,校验文件完整性。

有了 sha-1 的帮助,我们可以对项目版本的存储方式做一下调整。

图片

2.1.1 数据库中存储的数据内容

实际上,现在就与git实际存储的结构一致了。我们可以预览一下实际存储在 .git 下的文件。

图片

我们可以看到,在 objects 目录下,存放了很多文件,他们都使用 sha-1 的前两位创建了文件夹,剩下的38位为文件名。我们先称呼这些文件为 obj 文件。

对于这么多的 obj 文件,就保存了我们代码提交的所有记录。对于这些 obj 文件,其实分为四种类型,分别是 blob、tree、commit、tag。接下来,我们分别来看一下。

  1. blob

    首先 A、A1、B、B1 就是 blob 类型的 obj。

    blob: 用来存放项目文件的内容,但是不包括文件的路径、名字、格式等其它描述信息。项目的任意文件的任意版本都是以blob的形式存放的。

  2. tree

    tree 用来表示目录。我们知道项目就是一个目录,目录中有文件、有子目录。因此 tree 中有 blob、子tree,且都是使用 sha-1值引用的。这是与目录对应的。从顶层的 tree 纵览整个树状的结构,叶子结点就是blob,表示文件的内容,非叶子结点表示项目的目录,顶层的 tree 对象就代表了当前项目的快照。

  3. commit

    commit: 表示一次提交,有parent字段,用来引用父提交。指向了一个顶层 tree,表示了项目的快照,还有一些其它的信息,比如上一个提交,committer、author、message 等信息。

2.2 暂存区

暂存区是一个文件,路径为: .git/index

图片

它是一个二进制文件,但是我们可以使用命令来查看其中的内容。
这里我们关注第二列和第四列就可以了,第四列是文件名,第二列指的是文件的blob。这个blob存放了文件暂存时的内容。

第二列就是sha-1 hash值,相当于内容的外键,指向了实际存储文件内容的blob。第三列是文件的冲突状态,这个后面会讲,第四列是文件的路径名。

我们操作暂存区的场景是这样的,每当编辑好一个或几个文件后,把它加入到暂存区,然后接着修改其他文件,改好后放入暂存区,循环反复。直到修改完毕,最后使用 commit 命令,将暂存区的内容永久保存到本地仓库。

这个过程其实就是构建项目快照的过程,当我们提交时,git 会使用暂存区的这些信息生成tree对象,也就是项目快照,永久保存到数据库中。因此也可以说暂存区是用来构建项目快照的区域。

2.3 文件状态

有了工作区、暂存区、本地仓库,就可以来定义文件的状态了。

图片

文件的状态可以分为两类。一类是暂存区与本地仓库比较得出的状态,另一类是工作区与暂存区比较得出的状态。为什么要分成两类的愿意也很简单,因为第一类状态在提交时,会直接写入本地仓库。而第二种则不会。一个文件可以同时拥有两种状态。

比如一个文件可能既有上面的 modified 状态,又有下面 modified 状态,但其实他们表示了不同的状态,git 会使用绿色和红色把这两中 modified 状态区分开来。

2.4 分支

接下来,看一个很重要的概念,分支。

图片

分支的目的是让我们可以并行的进行开发。比如我们当前正在开发功能,但是需要修复一个紧急bug,我们不可能在这个项目正在修改的状态下修复 bug,因为这样会引入更多的bug。

有了分支的概念,我们就可以新建一个分支,修复 bug,使新功能与 bug 修复同步进行。

分支的实现其实很简单,我们可以先看一下 .git/HEAD 文件,它保存了当前的分支。

cat .git/HEAD
=>ref: refs/heads/master

其实这个 ref 表示的就是一个分支,它也是一个文件,我们可以继续看一下这个文件的内容:

cat .git/refs/heads/master
=> 2b388d2c1c20998b6233ff47596b0c87ed3ed8f8

可以看到分支存储了一个 object,我们可以使用 cat-file 命令继续查看该 object 的内容。

git cat-file -p 2b388d2c1c20998b6233ff47596b0c87ed3ed8f8
=> tree 15f880be0567a8844291459f90e9d0004743c8d9
=> parent 3d885a272478d0080f6d22018480b2e83ec2c591
=> author Hehe Tan <xiayule148@gmail.com> 1460971725 +0800
=> committer Hehe Tan <xiayule148@gmail.com> 1460971725 +0800
=> 
=> add branch paramter for rebase

从上面的内容,我们知道了分支指向了一次提交。为什么分支指向一个提交的原因,其实也是git中的分支为什么这么轻量的答案。

因为分支就是指向了一个 commit 的指针,当我们提交新的commit,这个分支的指向只需要跟着更新就可以了,而创建分支仅仅是创建一个指针。

3. 高层命令

在 git 中分为两种类型的命令,一种是完成底层工作的工具集,称为底层命令,另一种是对用户更友好的高层命令。一条高层命令,往往是由多条底层命令组成的。

不知道的人可能一听高层感觉很厉害的样子,其实就是指的是那些我们最常使用的git命令。

3.1 Add & Commit

add 和 commit 应该可以说是我们使用频率最高的高层命令了。

touch README.md
git add README.md
git commit -m "add readme”

touch 指的是创建一个文件,代表了我们对项目文件内容的修改,add 操作是将修改保存到暂存区,commit 是将暂存区的内容永久保存到本地仓库。

每当将修改的文件加入到暂存区,git 都会根据文件的内容计算出 sha-1,并将内容转换成 blob,写入数据库。然后使用 sha-1 值更新该列表中的文件项。在暂存区的文件列表中,每一个文件名,都会对应一个sha-1值,用于指向文件的实际内容。最后提交的那一刻,git会将这个列表信息转换为项目的快照,也就是 tree 对象。写入数据库,并再构建一个commit对象,写入数据库。然后更新分支指向。

3.2 Conflicts & Merge & Rebase

3.2.1 Conflicts

git 中的分支十分轻量,因此我们在使用git的时候会频繁的用到分支。不可不免的需要将新创建的分支合并。

在 git 中合并分支有两种选择:merge 和 rebase。但是,无论哪一种,都有可能产生冲突。因此我们先来看一下冲突的产生。

图片

图上的情况,并不是移动分支指针就能解决问题的,它需要一种合并策略。首先,我们需要明确的是谁和谁的合并,是 2,3 与 4,5,6的合并吗?说到分支,我们总会联想到线,就会认为是线的合并。其实不是的,真实合并的是 3 和 6。因为每一次提交都包含了项目完整的快照,即合并只是 tree 与 tree 的合并。

我们可以先想一个简单的算法。用来比较3和6。但是我们还需要一个比较的标准,如果只是3和6比较,那么3与6相比,添加了一个文件,也可以说成是6与3比删除了一个文件,这无法确切表示当前的冲突状态。因此我们选取他们的两个分支的分歧点(merge base)作为参考点,进行比较。

比较时,相对于 merge base(提交1)进行比较。

首先把1、3、6中所有的文件做一个列表,然后依次遍历这个列表中的文件。现在我们拿列表中的一个文件进行举例,把在提交1、3、6中的该文件分别称为版本1、版本3、版本6。

  1. 版本1、版本3、版本6的 sha-1 值完全相同,这种情况表明没有冲突
  2. 版本3或6至少一个与版本1状态相同(指的是sha-1值相同或都不存在),这种情况可以自动合并。比如1中存在一个文件,3对该文件进行修改,而6中删除了这个文件,则以6为准就可以了
  3. 版本3或版本6都与版本1的状态不同,情况复杂一些,自动合并策略很难生效,需要手动解决。我们来看一下这种状态的定义。

冲突状态定义:

  • 1 and 3: DELETED_BY_THEM;
  • 1 and 6: DELETED_BY_US;
  • 3 and 6: BOTH_ADDED;
  • 1 and 3 and 6: BOTH_MODIFIED

我们拿第一种情况举例,文件有两种状态 1 和 3,1 表示该文件存在于 commit 1(也就是MERGE_BASE),3 表示该文件在 commit 3 (master 分支)中被修改了,没有 6,也就是该文件在 commit 6(feature 分支)被删除了,总结来说这种状态就是 DELETED_BY_THEM。

可以再看一下第四种情况,文件有三种状态 1、3、6,1 表示 commit 1(MERGE_BASE)中存在,3 表示 commit 3(master 分支)进行了修改,6 表示(feature 分支)也进行了修改,总结来说就是 BOTH_MODIFIED(双方修改)。

遇到不可自动合并冲突时,git会将这些状态写入到暂存区。与我们讨论不同的是,git使用1,2,3标记文件,1表示文件的base版本,2表示当前的分支的版本,3表示要合并分支的版本。

3.2.2 Merge

在解决完冲突后,我们可以将修改的内容提交为一个新的提交。这就是 merge。

图片

merge 之后仍可以做出新的提交。

图片

可以看到 merge 是一种不修改分支历史提交记录的方式,这也是我们常用的方式。但是这种方式在某些情况下使用 起来不太方便,比如当我们创建了 pr、mr 或者 将修改补丁发送给管理者,管理者在合并操作中产生了冲突,还需要去解决冲突,这无疑增加了他人的负担。

使用 rebase 可以解决这种问题。

3.2.3 Rebase

假设我们的分支结构如下:

图片

rebase 会把从 Merge Base 以来的所有提交,以补丁的形式一个一个重新达到目标分支上。这使得目标分支合并该分支的时候会直接 Fast Forward,即不会产生任何冲突。提交历史是一条线,这对强迫症患者可谓是一大福音。

图片

如果我们想要看 rebase 实际上做了什么,有一个方法,那就是用“慢镜头”来看rebase的整个操作过程。rebase 提供了交互式选项(参数 -i),我们可以针对每一个patch,选择你要进行的操作。

通过这个交互式选项,我们可以”单步调试”rebase操作。

经过测试,其实 rebase 主要在 .git/rebase-merge 下生成了两个文件,分别为 git-rebase-todo 和 done 文件,这两个文件的作用光看名字就可以看得出来。git-rebase-todo 存放了 rebase 将要操作的 commit。而 done 存放正在操作或已经操作完毕的 commit。比如我们这里,git-rebase-todo 存放了 4、5、6,三个提交。

图片

首先 git 将 sha-1 为 4 的 commit 放入 done。表示正在操作 4,然后将 4 以补丁的形式打到 3 上,形成了新的提交 4’。这一步是可能产生冲突的,如果有冲突,需要解决完冲突之后才能继续操作。

图片

接着讲 sha-1 为 5 的提交放入 done 文件,然后将 5 以补丁的形式打到 4’ 上,形成 5’。

图片

再接着将 sha-1 为 6 的提交放入 done 文件,然后将 6 以补丁的形式打到 5’ 上,形成 6’。最后移动分支指针,使其指向最新的提交 6’ 上。这就完成了 rebase 的操作。

图片

我们看一下真实的 rebase 文件。

pick e0f56d9 update gitignore
pick e370289 add a

# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit

该文件一共有三列,第一列表示要进行的操作,所有可以进行的操作,在下面注释里都列了出来,比如 pick 表示使用该提交,reword 表示使用该提交,但修改其提交的 message,edit 表示使用该提交,但是要对该提交进行一些修改,其它的就不一一说了。

而 done 文件的形式如下,和 git-rebase-todo 是一样的:

pick e0f56d9 update gitignore
pick e370289 add a

从刚才的图中,我们就可以看到 rebase 的一个缺点,那就是修改了分支的历史提交。如果已经将分支推送到了远程仓库,会导致无法将修改后的分支推送上去,必须使用 -f 参数(force)强行推送。

所以使用 rebase 最好不要在公共分支上进行操作。

3.3 Checkout、Revert、Reset

3.3.1 Checkout

对于 checkout,我们一般不会陌生。因为使用它的频率非常高,经常用来切换分支、或者切换到某一次提交。

这里我们以切换分支为例,从 git 的工作区、暂存区、本地仓库分别来看 checkout 所做的事情。Checkout 前的状态如下:

图片

首先 checkout 找到目标提交(commit),目标提交中的快照也就是 tree 对象就是我们要检出的项目版本。
checkout 首先根据tree生成暂存区的内容,再根据 tree 与其包含的 blob 转换成我们的项目文件。然后修改 HEAD 的指向,表示切换分支。

图片

可以看到 checkout 并没有修改提交的历史记录。只是将对应版本的项目内容提取出来。

3.3.2 Revert

如果我们想要用一个用一个反向提交恢复项目的某个版本,那就需要 revert 来协助我们完成了。什么是反向提交呢,就是旧版本添加了的内容,要在新版本中删除,旧版本中删除了的内容,要在新版本中添加。这在分支已经推送到远程仓库的情境下非常有用。

Revert 之前:

图片

revert 也不会修改历史提交记录,实际的操作相当于是检出目标提交的项目快照到工作区与暂存区,然后用一个新的提交完成版本的“回退”。

Revert 之后:

图片

Reset

reset 操作与 revert 很像,用来在当前分支进行版本的“回退”,不同的是,reset 是会修改历史提交记录的。

reset 常用的选项有三个,分别是 —soft, —mixed, —hard。他们的作用域依次增大。

我们分别来看。

soft 会仅仅修改分支指向。而不修改工作区与暂存区的内容,我们可以接着做一次提交,形成一个新的 commit。这在我们撤销临时提交的场景下显得比较有用。

使用 reset –soft 前:

图片

使用 reset –soft 后:

图片

mixed 比 soft 的作用域多了一个 暂存区。实际上 mixed 选项与 soft 只差了一个 add 操作。

使用 reset –mixed 前:

图片

使用 reset –mixed 后:

图片

hard 会作用域又比 mixed 多了一个 工作区。

使用 reset –hard 前:

图片

使用 reset –hard 后:

图片

hard 选项会导致工作区内容“丢失”。

在使用 hard 选项时,一定要确保知道自己在做什么,不要在迷糊的时候使用这条选项。如果真的误操作了,也不要慌,因为只要 git 一般不会主动删除本地仓库中的内容,根据你丢失的情况,可以进行找回,比如在丢失后可以使用 git reset –hard ORIG_HEAD 立即恢复,或者使用 reflog 命令查看之前分支的引用。

3.4 stash

有时,我们在一个分支上做了一些工作,修改了很多代码,而这时需要切换到另一个分支干点别的事。但又不想将只做了一半的工作提交。在曾经这样做过,将当前的修改做一次提交,message 填写 half of work,然后切换另一个分支去做工作,完成工作后,切换回来使用 reset —soft 或者是 commit amend。

git 为了帮我们解决这种需求,提供了 stash 命令。

stash 将工作区与暂存区中的内容做一个提交,保存起来,然后使用reset hard选项恢复工作区与暂存区内容。我们可以随时使用 stash apply 将修改应用回来。

stash 实现思路将我们的修改提交到本地仓库,使用特殊的分支指针(.git/refs/stash)引用该提交,然后在恢复的时候,将该提交恢复即可。我们可以更进一步,看看 stash 做的提交是什么样的结构。

图片

如图所示,如果我们提供了 —include-untracked 选项,git 会将 untracked 文件做一个提交,但是该提交是一个游离的状态,接着将暂存区的内容做一个提交。最后将工作区的修改做一个提交,并以untracked 的提交、暂存区 的提交、基础提交为父提交。

搞这么复杂,是为了提供更灵活地选项,我们可以选择性的恢复其中的内容。比如恢复 stash 时,可以选择是否重建 index,即与 stash 操作时完全一致的状态。

3.5 bisect

最后要讲到一个曾经把我从“火坑”中救出来的功能。

项目发布到线上的项目出现了bug,而经过排查,却找不到问 bug 的源头。我们还有一种方法,那就是先找到上一次好的版本,从上一次到本次之间的所有提交依次尝试,一一排查。直到找到出现问题的那一次提交,然后分析 bug 原因。

git 为我们想到了这样的场景,同样是刚才的思路,但是使用二分法进行查找。这就是 bisect 命令。

使用该命令很简单,

git bisect start
git bisect bad HEAD
git bisect good v4.1

git 会计算中间的一个提交,然后我们进行测试。

图片

根据测试结果,使用 git bisect good or bad 进行标记,git 会自动切换到下一个提交。不断的重复这个步骤,直到找到最初引入 bug 的那一次提交。

图片

我们知道二分法的效率是很高的,2的10次方就已经1024了,因此我们测试一般最多是10次,再多就是11次、12次。其实这就要求我们优化测试的方法,使得简单的操作就能使 bug 重现。如果重新的操作非常简单,简单到我们可以使用脚本就能测试,那就更轻松了,可以使用 git bisect run ./test.sh,一步到位。

如果某一个提交代码跑不起来,可以使用 git bisect skip 跳过当前提交或者使用 visualize 在 git 给出的列表中手动指定一个提交进行测试。

Happy Coding ; )

浅谈我对DDD领域驱动设计的理解

从遇到问题开始

当人们要做一个软件系统时,一般总是因为遇到了什么问题,然后希望通过一个软件系统来解决。

比如,我是一家企业,然后我觉得我现在线下销售自己的产品还不够,我希望能够在线上也能销售自己的产品。所以,自然而然就想到要做一个普通电商系统,用于实现在线销售自己企业产品的目的。

再比如,我是一家互联网公司,公司有很多系统对外提供服务,面向很多客户端设备。但是最近由于各种原因,导致服务经常出故障。所以,我们希望通过各种措施提高服务的质量和稳定性。其中的一个措施就是希望能做一个灰度发布的平台,这个平台可以提供灰度发布的服务。然后,当某个业务系统做了一些修改并需要发布时,可以使用我们的灰度发布平台来非常方便的实现灰度发布的功能。比如在灰度发布平台上方便的定制允许哪些特定的客户端才会访问新服务,哪些客户端继续使用老服务。灰度发布平台可以提供各种灰度的策略。有了这样的灰度发布机制,那即便系统的新逻辑有什么问题,受影响的面也不会很大,在可控范围内。所以,如果公司里的所有对外提供服务的系统都接入了灰度平台,那这些系统的发布环节就可以更加有保障了。

总之,我们做任何一个软件系统,都是有原因的,否则就没必要做这个系统,而这个原因就是我们遇到的问题。所以,通过问题,我们就知道了我们需要一个什么样的系统,这个系统解决什么样的问题。最后,我们就很自然的得出了一个目标,即知道了自己要什么。比如我要做一个论坛、一个博客系统、一个电商平台、一个灰度发布系统、一个IDE、一个分布式消息队列、一个通信框架,等等。

DDD切入点1 – 理解概念

DDD的全称为Domain-driven Design,即领域驱动设计。下面我从领域、问题域、领域模型、设计、驱动这几个词语的含义和联系的角度去阐述DDD是如何融入到我们平时的软件开发初期阶段的。要理解什么是领域驱动设计,首先要理解什么是领域,什么是设计,还有驱动是什么意思,什么驱动什么。

什么是领域(Domain)?

前面我们已经清楚的知道我们现在要做一个什么样的系统,这个系统需要解决什么问题。我认为任何一个系统都会属于某个特定的领域,比如论坛是一个领域,只要你想做一个论坛,那这个论坛的核心业务是确定的,比如都有用户发帖、回帖等核心基本功能。比如电商平台、普通电商系统,这种都属于网上电商领域,只要是这个领域的系统,那都有商品浏览、购物车、下单、减库存、付款交易等核心环节。所以,同一个领域的系统都具有相同的核心业务,因为他们要解决的问题的本质是类似的。

因此,我们可以推断出,一个领域本质上可以理解为就是一个问题域,只要是同一个领域,那问题域就相同。所以,只要我们确定了系统所属的领域,那这个系统的核心业务,即要解决的关键问题、问题的范围边界就基本确定了。通常我们说,要成为一个领域的专家,必须要在这个领域深入研究很多年才行。因为只有你研究了很多年,你才会遇到非常多的该领域的问题,同时你解决这个领域中的问题的经验也非常丰富。很多时候,领域专家比技术专家更加吃香,比如金融领域的专家。

什么是设计(Design)?

DDD中的设计主要指领域模型的设计。为什么是领域模型的设计而不是架构设计或其他的什么设计呢?因为DDD是一种基于模型驱动开发的软件开发思想,强调领域模型是整个系统的核心,领域模型也是整个系统的核心价值所在。每一个领域,都有一个对应的领域模型,领域模型能够很好的帮我们解决复杂的业务问题。

从领域和代码实现的角度来理解,领域模型绑定了领域和代码实现,确保了最终的代码实现就一定是解决了领域中的核心问题的。因为:1)领域驱动领域模型设计;2)领域模型驱动代码实现。我们只要保证领域模型的设计是正确的,就能确定领域模型可以解决领域中的核心问题;同理,我们只要保证代码实现是严格按照领域模型的意图来落地的,那就能保证最后出来的代码能够解决领域的核心问题的。这个思路,和传统的分析、设计、编码这几个阶段被割裂(并且每个阶段的产物也不同)的软件开发方法学形成鲜明的对比。

什么是驱动(Driven)?

上面其实已经提到了,就是:1)领域驱动领域模型设计;2)领域模型驱动代码实现。这个就和我们传统的数据库驱动开发的思路形成对比了。DDD中,我们总是以领域为边界,分析领域中的核心问题(核心关注点),然后设计对应的领域模型,再通过领域模型驱动代码实现。而像数据库设计、持久化技术等这些都不是DDD的核心,而是外围的东西。

领域驱动设计(DDD)告诉我们的最大价值我觉得是:当我们要开发一个系统时,应该尽量先把领域模型想清楚,然后再开始动手编码,这样的系统后期才会很好维护。但是,很多项目(尤其是互联网项目,为了赶工)都是一开始模型没想清楚,一上来就开始建表写代码,代码写的非常冗余,完全是过程是的思考方式,最后导致系统非常难以维护。而且更糟糕的是,出来混总是要还的,前期的领域模型设计的不好,不够抽象,如果你的系统会长期需要维护和适应业务变化,那后面你一定会遇到各种问题维护上的困难,比如数据结构设计不合理,代码到处冗余,改BUG到处引入新的BUG,新人对这种代码上手困难,等。而那时如果你再想重构模型,那要付出的代价会比一开始重新开发还要大,因为你还要考虑兼容历史的数据,数据迁移,如何平滑发布等各种头疼的问题。所以,就导致我们最后天天加班。

虽然,我们都知道这个道理,但是我也明白,人的习惯很难改变的,大部分人都很难从面向过程式的想到哪里写到哪里的思想转变为基于系统化的模型驱动的思维。我想,这或许是DDD很难在中国或国外流行起来的原因吧。但是,我想这不应该成为我们放弃学习DDD的原因,对吧!

概念总结:

  1. 领域就是问题域,有边界,领域中有很多问题;
  2. 任何一个系统要解决的那个大问题都对应一个领域;
  3. 通过建立领域模型来解决领域中的核心问题,模型驱动的思想;
  4. 领域建模的目标针对我们在领域中所关心的问题,即只针对核心关注点,而不是整个领域中的所有问题;
  5. 领域模型在设计时应考虑一定的抽象性、通用性,以及复用价值;
  6. 通过领域模型驱动代码的实现,确保代码让领域模型落地,代码最终能解决问题;
  7. 领域模型是系统的核心,是领域内的业务的直接沉淀,具有非常大的业务价值;
  8. 技术架构设计或数据存储等是在领域模型的外围,帮助领域模型进行落地;

DDD切入点2 – 理解领域、拆分领域、细化领域

理解领域知识是基础

上面我们通过第一步,虽然我们明确了要做一个什么样的系统,该系统主要解决什么问题,但是就这样我们还无法开始进行实际的需求分析和模型设计,我们还必须将我们的问题进行拆分,需求进行细化。有些时候,需求方,即提出问题的人,很可能自己不清楚具体想要什么。他只知道一个概念,一个大的目标。比如他只知道要做一个股票交易系统,一个灰度发布系统,一个电商平台,一个开发工具,等。但是他不清楚这些系统应该具体做成什么样子。这个时候,我认为领域专家就非常重要了,DDD也非常强调领域专家的重要性。因为领域专家对这个领域非常了解,对领域内的各种业务场景和各种业务规则也非常清楚,总之,对这个领域内的一切业务相关的知识都非常了解。所以,他们自然就有能力表达出系统该做成什么样子。所以,要知道一个系统到底该做成什么样子,到底哪些是核心业务关注点,只能靠沉淀领域内的各种知识,别无他法。因此,假设你现在打算做一个电商平台,但是你对这个领域没什么了解,那你一定得先去了解下该领域内主流的电商平台,比如淘宝、天猫、京东、亚马逊等。这个了解的过程就是你沉淀领域知识的过程。如果你不了解,就算你领域建模的能力再强,各种技术架构能力再强也是使不上力。领域专家不是某个固定的角色,而是某一类人,这类人对这个领域非常了解。比如,一个开发人员也可以是一个领域专家。假设你在一个公司开发和维护一个系统已经好几年了,但是这个系统的产品经理(PD)可能已经换过好几任了,这种情况下,我相信这几任产品经理都没有比你更熟悉这个领域。

拆分领域

上面我们明白了,领域建模的基础是要先理解领域,让自己成为领域专家。如果做到了这点,我们就打好了坚实的基础了。但是,有时一个领域往往太复杂,涉及到的领域概念、业务规则、交互流程太多,导致我们没办法直接针对这个大的领域进行领域建模。所以,我们需要将领域进行拆分,本质上就是把大问题拆分为小问题,然后各个击破的思路。然后既然把一个大的领域划分为了多个小的领域(子域),那最关键的就是要理清每个子域的边界;然后要搞清楚哪些子域是核心子域,哪些是非核心子域,哪些是公共支撑子域;然后,还要思考子域之间的联系是什么。那么,我们该如何划分子域呢?我的个人看法是从业务相关性的角度去思考,也就是我们平时说的按业务功能为出发点进行划分。还是拿经典的电商系统来分析,通常一个电商系统都会包含好几个大块,比如:

  • 会员中心:负责用户账号登录、用户信息的管理;
  • 商品中心:负责商品的展示、导航、维护;
  • 订单中心:负责订单的生成和生命周期管理;
  • 交易中心:负责交易相关的业务;
  • 库存中心:负责维护商品的库存;
  • 促销中心:负责各种促销活动的支持;

上面这些中心看起来很自然,因为大家对电子商务的这个领域都已经非常熟悉了,所以都没什么疑问,好像很自然的样子。所以,领域划分是不是就是没什么挑战了呢?显然不是。之所以我们觉得子域划分很简单,是因为我们对整个大领域非常了解了。如果我们遇到一个冷门的领域,就没办法这么容易的去划分子域了。这就需要我们先去努力理解领域内的知识。所以,我个人从来不相信什么子域划分的技巧什么的东西,因为我觉得这个工作没有任何诀窍可以使用。当我们不了解一个东西的时候,如何去拆解它?当我们对整个领域有一定的熟悉了,了解了领域内的相关业务的本质和关系,我们就自然而然的能划分出合理的子域了。不过并不是所有的系统都需要划分子域的,有些系统只是解决一个小问题,这个问题不复杂,可能只有一两个核心概念。所以,这种系统完全不需要再划分子域。但不是绝对的,当一个领域,我们的关注点越来越多,每个关注点我们关注的信息越来越多的时候,我们会不由自主的去进一步的划分子域。比如,也许我们一开始将商品和商品的库存都放在商品中心里,但是后来由于库存的维护越来越复杂,导致揉在一起对我们的系统维护带来一定的困难时,我们就会考虑将两者进行拆分,这个就是所谓的业务垂直分割。

细化子域

通过上面的两步,我们了解了领域里的知识,也对领域进行了子域划分。但这样还不够,凭这些我们还无法进行后续的领域模型设计。我们还必须再进一步细化每个子域,进一步明确每个子域的核心关注点,即需求细化。我觉得我们需要细化的方面有以下几点:

  1. 梳理领域概念:梳理出领域内我们关注的概念、概念的关系,并统一交流词汇,形成统一语言;
  2. 梳理业务规则:梳理出领域内我们关注的各种业务规则,DDD中叫不变性(invariants),比如唯一性规则,余额不能小于零等;
  3. 梳理业务场景:梳理出领域内的核心业务场景,比如电商平台中的加入购物车、提交订单、发起付款等核心业务场景;
  4. 梳理业务流程:梳理出领域内的关键业务流程,比如订单处理流程,退款流程等;

从上面这4个方面,我们从领域概念、业务规则、交互场景、业务流程等维度梳理了我们到底要什么,整理了整个系统应该具备的功能。这个工作我觉得是一个非常具有创造性和有难度的工作。我们一方面会主观的定义我们想要什么;另一方面,我们还会思考我们要的东西的合理性。我认为这个就是产品经理的工作,产品经理必须要负起职责,把他的产品充分设计好,从各个方面去考虑,如何设计一个产品,才能更好的解决用户的核心诉求,即领域内的核心问题。如果对领域不够了解,如果想不清楚用户到底要什么,如果思考问题不够全面,谈何设计出一个合理的产品呢?

关于领域概念的梳理,我觉得可以采用四色原型分析法,这个分析法通过系统的方法,将概念划分为不同的种类,为不同种类的概念标注不同的颜色。然后将这些概念有机的组合起来,从而让我们可以清晰的分析出概念和概念之间的关系。有兴趣的同学可以在网上搜索下四色原型

注意:上面我说的这四点,重点是梳理出我们要什么功能,而不是思考如何实现这些功能,如何实现是软件设计人员的职责。

DDD切入点3 – 领域模型设计

这部分内容,我想学习DDD的人都很熟悉了。DDD原著中提出了很多实用的建模工具:聚合、实体、值对象、工厂、仓储、领域服务、领域事件。我们可以使用这些工具,来设计每一个子域的领域模型。最终通过领域模型图将设计沉淀下来。要使用这些工具,首先就要理解每个工具的含义和使用场景。不要以为很简单哦,比如聚合的划分就是一个非常具有艺术的活。同一个系统,不同的人设计出来的聚合是完全不同的。而且很有可能高手之间的最后设计出来的差别反而更大,实际上我认为是世界观的相互碰撞,呵呵。所以,要领域建模,我觉得每个人都应该去学学哲学知识,这有助于我们更好的认识世界,更好的理解事物的本质。

关于这些建模工具的概念和如何运用我就不多展开了,我博客里也有很多这方面的介绍。下面我再讲一下我认为比较重要的东西,比如到底该如何领域建模?步骤应该是怎么样的?

领域建模的方法

通过上面我介绍的细化子域的内容,现在再来谈该如何领域建模,我觉得就方便很多了。我的主要方法是:

  1. 划分好边界上下文,通常每个子域(sub domain)对应一个边界上下文(bounded context),同一个边界上下文中的概念是明确的,没有任何歧义;
  2. 在每个边界上下文中设计领域模型,具体的领域模型设计方法有很多种,如以场景为出发点的四色原型分析法,或者我早期写的这篇文章;这个步骤最核心的就是找出聚合根,并找出每个聚合根包含的信息;关于如何设计聚合,可以看一下我写的这篇文章
  3. 画出领域模型图,圈出每个模型中的聚合边界;
  4. 设计领域模型时,要考虑该领域模型是否满足业务规则,同时还要综合考虑技术实现等问题,比如并发问题;领域模型不是概念模型,概念模型不关注技术实现,领域模型关心;所以领域模型才能直接指导编码实现;
  5. 思考领域模型是如何在业务场景中发挥作用的,以及是如何参与到业务流程的每个环节的;
  6. 场景走查,确认领域模型是否能满足领域中的业务场景和业务流程;
  7. 模型持续重构、完善、精炼;

领域模型的核心作用:

  1. 抽象了领域内的核心概念,并建立概念之间的关系;
  2. 领域模型承担了领域内的状态的维护;
  3. 领域模型维护了领域内的数据之间的业务规则,数据一致性;

下图是我最近做个一个普通电商系统的商品中心的领域模型图,给大家参考:

领域模型设计只是软件设计中的一小部分

需要特别注意的是,领域模型设计只是整个软件设计中的很小一部分。除了领域模型设计之外,要落地一个系统,我们还有非常多的其他设计要做,比如:

  • 容量规划
  • 架构设计
  • 数据库设计
  • 缓存设计
  • 框架选型
  • 发布方案
  • 数据迁移、同步方案
  • 分库分表方案
  • 回滚方案
  • 高并发解决方案
  • 一致性选型
  • 性能压测方案
  • 监控报警方案

等等。上面这些都需要我们平时的大量学习和积累。作为一个合格的开发人员或架构师,我觉得除了要会DDD领域驱动设计,还要会上面这么多的技术能力,确实是非常不容易的。所以,千万不要以为会DDD了就以为自己很牛逼,实际上你会的只是软件设计中的冰山一角而已。

总结

本文的重点是基于我个人对DDD的一些理解,希望能整理出一些自己总结出来的一些感悟和经验,并分享给大家。我相信很多人已经看过太多DDD书上的东西,我总是感觉书上的东西看似都太”正规“,很多时候我们读了之后很难消化,就算理解了书里的内容,当我们想要运用到实践中时,总是感觉无从下手。本文希望通过通俗易懂的文字,介绍了一部分我对DDD的学习感悟和实践心得,希望能给大家一些启发和帮助。

如何给软件开发项目估价?

“兄弟,你看做这样一个软件需要多少钱?” 这估计是所有软件从业人员被问的最多也是最无奈的一个问题。这个问题等同于,“你看装修一个100平米的房子需要多少钱?”。软件开发你不懂,装修你总懂吧,100平米的房子装修从10万到100万均有可能,取决于你找什么级别的设计公司,买什么样的材料,请什么样的施工队……所以,我真的没有办法回答你“做这样一个软件需要多少钱?”的问题。

图片

评估一个软件开发的费用,你首先需要理清楚一些基本概念。

1. 招聘一个开发者的成本
如今(2015年) IT 行业蓬勃发展,对软件开发工程师的需求很大,导致工程师的工资一路水涨船高,以一线城市为例,一个能实际干活的应届开发者的月薪在10000元左右,3年以上工作经验的基本能达到20000元。我们姑且把三年工作经验定义为靠谱的开发者,再加上其他福利和管理成本,一个靠谱全职开发者的成本在30000元左右。这还没有算上你招聘的成本,想想是不是很肉疼?没办法,行情就是这样,就跟这房价一样。

2. 外包项目费用的计算方式
外包分为两种,人力外包和项目外包。人力外包是指外包公司派一个人去你公司工作,你按天支付这个人的费用给外包公司。目前这种外派的基本要价是1000元每天,好一点的人员在2000元以上。项目外包是指做完一个项目多少钱,不管外包公司投入多少人。有点类似于装修队的点工和包工。项目外包的价格虽然是打包价,但也是通过估算工时算出来的。例如一个项目预计需要两个人开发20天,那就是40人天的工作量,按照1500元/人天算(这已经是良心价了),这个项目就是60000元。

看到这里你一定会觉得,外包好贵,怎么比招一个人的成本贵那么多!君不见,用人除了硬性成本还有很多软性成本的。例如招聘的时间成本,招来不合适开人的成本。而通过外包,你可以做到召之即来,挥之即去,这些软性成本都是外包公司承担了,你要算单价,自然会贵一些。

好了,下面我们回到正题,“开发这样一个软件需要多少钱?”。这里的核心问题是如何定义“这样”。你需要准确的估价,那就需要把需求定义清楚,否则估价就是耍流氓,最后一定导致纠纷。需求定义包含以下几个方面:
1. 设计要求
一个好的设计是很贵的,因为涉及到创意,而且不好评估,见仁见智。就跟你请大师画一幅画,还是请普通画师画一幅画一样,看你想要什么了。在我看来,绝大部分软件项目设计中规中矩就好了,请一个有经验的设计师,按照最新流行的设计风格设计一套 UI 都不会差到哪里去。而且价格都比较便宜的,一个 APP 的 UI 设计,一般在10000 – 20000之间,应该能有不错的效果。当然,你对设计没有要求的话,你找一个应届生做一套 UI,几千块就搞定了,也不会太丑的。

2. 功能要求
我不止一次被问到,“我想做一个类似于微信的 APP……”,然后我就呵呵了。其实你不是真的想做一个微信,我相信你想要的只是微信的部分功能,例如聊天部分。所以你应该更加准确的描述你对功能的要求,例如:类似于微信的聊天功能,可以发文字,图片,语音还有视频,可以多人拉群对话。有新消息会弹出通知,聊天记录保存在服务器端……。在这一点上不能懒,你需要强迫自己去描述这些功能,你不要以为你自己不懂就不去仔细思考,其实你可以的。有些功能看起来差不多,其实有很大的区别,比如聊天是否需要支持表情,表情是否支持动画这些其实工作量都是很不一样的。

3. 性能要求
性能问题其实不是特别需要关注,因为在目前的技术发展水平上,性能都不会有太大的问题,特别是在项目初期,但也还是要说一说。同样的功能,但是性能要求不一样,工作量是完全不一样的。还拿聊天来举例子,这个功能是比较常见的,但是你说要像微信一样支持几亿用户同时聊天,那就是两码事了。同样是个车,QQ和奔驰还是很不一样的。

在明确了以上信息以后,你找一个有经验的开发者或者项目监理就能给你一个明确的估价了。值得注意的是,软件开发是一件非常不标准的事情,跟装修很像,要留有余地,你把费用卡的太死,最后别人只能偷工减料了。

当然还有一种估价方式,你先确定预算,然后再来定细节功能。例如你打算花50000来做一个 APP,具有类似微信的聊天功能,还有相互关注晒照片功能。你把详细的功能需求给到开发者或者项目监理,他会去判断你的预算能否实现你的要求,如果不能的话,你们再商量哪些功能可以先不做,例如聊天发表情功能不是很重要就先不做了,可以节约一些成本。

无论何种方式,都需要你明确需求,明确需求,明确需求!重要的事情说三遍。所以你找别人报价的时候,千万不要只扔过去“开发一个类似于 xxxx 这样的 APP 需要多少钱?”,你不会得到你想要的答案的,回答这样的问题是不负责任的。不过,这倒不失为一种过滤服务方的一种方法:)

(完)
*注:所有配图来源于互联网

来自 Google 的高可用架构理念与实践

在 Google 我参与了两个比较大的 Project。

第一个是 YouTube,其中包括 Video transcoding,streaming 等。Google 的量很大,每个月会有 1PB 级别的存储量。存储、转码后,我们还做 Global CDN。到 2012 年的时候,峰值流量达到 10 TBps,全球 10 万个节点,几乎每台机器都是 16/24 核跑满, 10G uplink 也是跑满的状态。

然后我加入了 Google Cloud Platform Team, 也就是 Borg 团队。这个团队的主要工作是就是管理 Google 全球所有的服务器,全球大概有 100 万台左右。另外就是维护 Borg 系统,同时我也是 Omega 系统运维的主要负责人,很可惜这个项目最后由于各种各样的原因在内部取消了。

下面我想跟大家分享的是关于可用性、可靠性上面的一些理念和思考。

一、决定可用性的两大因素

谈可用性不需要绕来绕去,大家只谈 SLA 即可。大家可以看下面这个图:

图片

要谈可用性,首先必须承认所有东西都有不可用的时候,只是不可用程度而已。一般来说,我们的观念里一个服务至少要做到 99.9% 才称为基本上可用,是合格性产品。否则基本很难被别人使用。

从 3 个 9 迈向 4 个 9,从 8 小时一下缩短到 52.6 分钟的不可用时间,是一个很大的进步。Google 内部只有 4 个 9 以上的服务才会配备 SRE,SRE 是必须在接到报警 5 分钟之内上线处理问题的,否则报警系统自动升级到下一个 SRE。如果还没有,直接给老板发报警。

大家之前可能听说谷歌搜索服务可用度大概是全球 5 个 9,6 个 9 之间。其实这是一个多层,多级,全球化的概念,具体到每个节点其实没那么高。比如说当年北京王府井楼上的搜索集群节点就是按 3 个 9 设计的。

有关 SLA 还有一个秘密,就是一般大家都在谈年 SLA,但是年 SLA 除了客户赔款以外,一般没有任何实际工程指导意义。 Google 内部更看重的是季度 SLA,甚至月 SLA,甚至周 SLA。这所带来的挑战就更大了。

为什么说看这个图有用,因为 99%、99.9% 是基本可以靠运气搞定的哦。到 3 个 9 可以靠堆人,也就是 3 班倒之类的强制值班基本搞定。但是从 3 个 9 往上,就基本超出了人力的范畴,考验的是业务的自愈能力,架构的容灾、容错设计,灾备系统的完善等等。

说了这么多,作为一个架构者,我们如何来系统的分解“提升 SLA”这一个难题呢。

这里我引入两个工业级别的概念 MTBF 和 MTTR。

MTBF: Mean time between Failures。 用通俗的话讲,就是一个东西有多不可靠,多长时间坏一次。
MTTR: Mean time to recover。意思就是一旦坏了,恢复服务的时间需要多长。

有了这两个概念, 我们就可以提出:

图片

一个服务的可用度,取决于 MTBF 和 MTTR 这两个因子。从这个公式出发,结合实际情况,就很好理清高可用架构的基本路数了。那就是: 要么提高 MTBF, 要么降低 MTTR。除此之外别无他法。

要注意的是,考虑 MTBF 和 MTTR 的时候都不能脱离现实。

理论上来说,作为一个正常人类,收到突发报警、能正确的分析出问题所在、找到正确的解决方案、并且 【正确实施】的时间极限大概是 【两分钟】。这个标准我个人觉得是高到天上去了。作为一个苦练多年的 Oncall 工程师,我 2 分钟能看清报警,上了 VPN,找到 dashboard,就不错了。就算是已知问题,有应对方案,能敲对命令,完全成功,也至少需要 15 – 20 分钟。所以如果按照这个标准的话,管理的服务如果想达到 4 个 9,那么一年只能坏 1 次,2 次就超标了。实现高可用基本靠运气~

回过来接着说说 MTBF 吧。请各位想一下,影响服务MTBF的三大因素!

  1. 发布
  2. 发布
  3. 还是发布!

这个术语上叫 Age Mortality Risk。

一般一个服务只要你不去碰他一年都不会坏一次。更新越频繁,坏的可能性就越大。凡是 Software 都有 BUG,修 BUG 的更新也会引入新的 BUG。发布新版本,新功能是 MTBF 最大的敌人。

二、高可用性方案

说了 MTBF 和 MTTR 这两个定义,那么具体究竟应该如何落地实践来提高可用性呢?

首先说几个大家可能都听腻了的方案

一、提高冗余度,多实例运行,用资源换可用性。

虽然道理很简单,实现起来可不简单,有很多很多细节上的东西需要考虑。

第一个细节:N + 2 应该是标配。

N + 2 就是说平时如果一个服务需要 1 个实例正常提供服务,那么我们就在生产环境上应该部署 1 + 2 = 3 个节点。大家可能觉得 N + 1 很合理,也就是有个热备份系统,比较能够接受。但是你要想到:服务 N + 1 部署只能提供热备容灾,发布的时候就失去保护了。

因为刚才说了, 发布不成功的几率很高!

从另一个角度来讲,服务 N + 2 说的是在丢失两个最大的实例的同时,依然可以维持业务的正常运转。

这其实就是最近常说的两地三中心的概念有点像。

第二个细节: 实例之间必须对等、独立。

千万不要搞一大一小,或者相互依赖。否则你的 N + 2 就不是真的 N + 2。如果两地三中心的一个中心是需要 24 小时才能迁移过去的,那他就不是一个高可用性部署,还是叫异地灾备系统吧。

第三个细节:流量控制能力非常重要。

想做到高可用,必须拥有一套非常可靠的流量控制系统。这套系统按常见的维度,比如说源 IP,目标 IP 来调度是不够的,最好能按业务维度来调度流量。比如说按 API, 甚至按用户类型,用户来源等等来调度。

为什么?因为一个高可用系统必须要支持一下几种场景:

  1. Isolation。A 用户发来的请求可能和 B 用户发来的请求同时处理的时候有冲突,需要隔离。
  2. Quarantine。用户 A 发来的请求可能资源消耗超标,必须能将这类请求钉死在有限的几个节点上,从而顾全大局。
  3. Query-of-death。大家都遇到过吧。上线之后一个用户发来个一个异常请求直接搞挂服务。连续多发几个,整个集群都挂没了,高可用还怎么做到?那么,对这种类型的防范就是要在死掉几台服务器之后可以自动屏蔽类似的请求。需要结合业务去具体分析。

但是想要达到高可用,这些都是必备的,也是一定会遇到的场景。还是那句话,靠人是没戏的。

二、变更管理(Change Management)

还记得影响 MTBF 最大的因子吗?发布质量不提高,一切都是空谈。

第一点: 线下测试(Offline Test)

线下测试永远比线上调试容易一百倍,也安全一百倍。

这个道理很简单,就看执行。如果各位的团队还没有完整的线下测试环境,那么我的意见是不要再接新业务了,花点时间先把这个搞定。这其中包括代码测试、数据兼容性测试、压力测试等等。

台上一分钟,台下十年功。

可用性的阶段性提高,不是靠运维团队,而是靠产品团队。能在线下完成的测试,绝不拍脑门到线上去实验。

第二点:灰度发布

这个道理说起来好像也很普通,但是具体实施起来是很有讲究的。

首先灰度发布是速度与安全性作为妥协。他是发布众多保险的最后一道,而不是唯一的一道。如果只是为了灰度而灰度,故意人为的拖慢进度,反而造成线上多版本长期间共存,有可能会引入新的问题。

做灰度发布,如果是匀速的,说明没有理解灰度发布的意义。一般来说阶段选择上从 1% -> 10% -> 100% 的指数型增长。这个阶段,是根据具体业务不同按维度去细分的。

这里面的重点在于1%并不全是随机选择的,而是根据业务特点、数据特点选择的一批有极强的代表性的实例,去做灰度发布的小白鼠。甚至于每次发布的 第一阶段用户(我们叫 Canary / 金丝雀) ,根据每次发布的特点不同,是人为挑选的。

如果要发布一个只给亚洲用户使用的功能,很明显用美国或欧洲的集群来做发布实验,是没有什么意义的。从这个角度来想,是不是灰度发布可做的事情很多很多?真的不只是按机器划分这么简单。

回到本质:灰度发布是上线的最后一道安全防护机制。即不能过慢,让产品团队过度依赖,也不能过于随机,失去了他的意义。

总之,灰度发布,全在细节里。

第三点:服务必须对回滚提供支持

这点不允许商量!

这么重要的话题,我还要用一个感叹号来强调一下!

但是估计现实情况里,大家都听过各种各样的理由吧。我这里有三条买也买不到的秘籍,今天跟大家分享一下,保证药到病除。

理由1:我这个数据改动之后格式跟以前的不兼容了,回退也不能正常!
秘籍1:设计、开发时候就考虑好兼容性问题!!!比如说数据库改字段的事就不要做,改成另加一个字段就好。数据存储格式就最好采用 protobuf 这种支持数据版本、支持前后兼容性的方案。最差的情况,也要在变更实施『之前』,想清楚数据兼容性的问题。没有回滚脚本,不给更新,起码做到有备而战。

理由2:我这个变更删掉东西了!回退之后数据也没了!
秘籍2:你一定是在逗我。把这个变更打回去,分成两半。第一半禁止访问这个数据。等到发布之后真没问题了,再来发布第二半,第二半真正删掉数据。这样第一半实施之后需要回滚还可以再回去。

理由3:我这个变更发布了之后, 其他依赖这个系统的人都拿到了错误的数据,再回退也没用了,他们不会再接受老数据了!
秘籍3:这种比较常见出现在配置管理、缓存等系统中。对这类问题,最重要的就是, 应该开发一种跟版本无关的刷新机制。触发刷新的机制应该独立于发布过程。 要有一个强制刷新数据的手段。

以上三个秘籍覆盖了100%的回滚兼容性问题,如果有不存在的,请务必告诉我!

回滚兼容性问题,是一个整体难题。只有开发和运维都意识到这个问题的严重性,才能从整体上解决这个问题。而解决不了回滚难题,就不可能达到高可用。

三、可用性 7 级图表

说完了变更管理,给大家带来一个7级图表,可以看看自己的服务到底在哪个可用性的级别上。

当一个服务挂了的时候……

第一级:Crash with data corruption, destruction.

内存数据库就容易这样。出现个意外情况,所有数据全丢。写硬盘写到一半,挂了之后,不光进程内数据没了,老数据都丢光了。碰上这样的系统,我只能对你表示同情了。

第二级:Crash with new data loss.

一般来说 正常的服务都应该做到这一点…… 。挂了之后最多只丢个几秒之内的数据。

第三级:Crash without data loss.

要达到这一级,需要付出一定程度的技术投入。起码搞清楚如何绕过 OS 各种 Cache,如何绕过硬件的各种坑。

第四级:No crash, but with no or very limited service, low service quality.

做的好一点的系统,不要动不动就崩溃了…… 如果一个程序能够正常处理异常输入,异常数据等,那么就给刚才说的高级流控系统创造了条件。可以把其他的用户流量导入过来,把问题流量发到一边去,不会造成太大的容量损失。

第五级:Partial or limited service, with good to medium service quality.

这一级就还好了,如果多个业务跑在同一个实例上,那么起码不要全部坏掉。有部分服务,比完全没有服务要好

第六级:Failover with significant user visible delay, near full quality of service

上升到这一级别,才摸到高可用的门,也就是有容灾措施。但是可能自动化程度不高,或者是一些关键性问题没有解决,所以业务能恢复,就是比较慢。

第七级:Failover with minimal to none user visible delay, near full quality

of service.

这边蝴蝶扇了一下翅膀,天空落了个打雷,打掉了一整个机房,结果业务完全没受影响。蓝翔技校一铲子下去,互联网都要抖一抖。嘿嘿, 高可用就是为了这种事情做准备。

Q & A

1. 有什么评测系统吗?

评测系统的第一步是收集足够的信息。想知道自己的服务是不是高可用,必须得先监测啊!不光黑盒监测,还要有白盒监测。如果有一个自动化的 SLA 监控系统,能显示实时的 SLA 变化 ,会对系统的开发计划有很强烈的指导作用。

2. 能详细说一下做到 “crash without data loss” 需要在哪些点上下功夫吗?

这个事情说起来简单,实际实现起来非常复杂。 因为很多东西深究起来都有无数的坑。 比如说:

OS 的 Cache 如何绕过。
系统硬件可能也有内置的 Cache,Firmware 也可能有 BUG 等等等等。还有一些集群系统为了所谓的性能实现的 fake sync。

这里是列不全的。我提出这个等级的意思,是想让大家有这个意识去系统化的应对这个问题。比如说关键数据是不是要多存几分,然后做一些 destruction 测试。比如多模拟断电等等的极端情况,这样才能有备无患。扫雷比触雷要容易多了。

3. 现在 Coding.net 到几个9了,7张图中第几级了,改造花了多长时间,有哪些坑分享下?

首先高可用是按业务来的,不是所有业务都能做到高可用,也不是所有都需要做到高可用。我们下了很大精力在关键业务上,比如说 Git 系统的流控,数据安全等等,其他的就没办法啦。

4. 开发团队要怎样配合?周期怎么样配合?侧重点各自在哪 (开发更侧重业务)?

首先就是要确定一个共同目标。高可用是有代价的,你的业务需要做到什么程度,一定是一个系统性的考虑。给大家举一个例子,Youtube 这么多视频, 但是每个视频的每种格式,只存了1份。所以可用性肯定受影响了。但是,数据量实在是太大了,然后各种小猫视频实在是不重要。相比之下,广告视频经常存8 份。所以!想要提高可用性,必须要和开发团队找到一个共同目标。这里再给大家一个秘籍,那就是 error budget。跟开发团队确定一个可用度,比如说 99% 。 如果业务团队搞出来的东西很烂,各种状况,最后达不到这个标准。那么对不起,暂时别发新功能,只修 BUG。

5. 谷歌的 SRE 工程师用了哪些开源工具来管理百万机器?

比较惭愧,我们没用什么开源工具,都是内部自己开发的。企业内部管理用了Puppet,但是生产系统上没有。

6. 请问一下实现独立对等的N+2服务使用什么架构比较好,LVS+Keepalive 的双机热备是否合适?

莫非现在不都用 haproxy / nginx 之类的7层代理?但是其实这个原理都差不多。只要达到你的目的,可以动态切换就好。

7. “可以把其他的用户流量导入过来。把问题流量发到一边去,不会造成太大的容量损失。” 这句话怎么理解呢? 另外如何区分问题流量?

这句话说的是刚才提到的高可用必不可少的流控系统。任何一个系统都不是完美的,总会有各种各样的 hot spot,weak spot。问题流量的定义是跟业务紧密相关的。我再举一个例子:当年 Youtube 的 CDN 服务器有个问题,后端存储慢了之后,前端的请求会聚在一起,就像水管一样,于是内存就爆了。突然压力过高,肯定就挂了。如何处理这个问题? 最后流控系统升级,每个实例自己汇报自己的内存状况,超标之后流控系统自动绕过他。把这个问题变成了自动化处理的方案,问题面大大缩小了。再举一个例子,搜索系统是典型的热点密集型系统。有的冷僻词, 查一次要去各种读硬盘。而热词,消耗很小。所以流控系统做了个功能每个请求回复都带了 cost 值,流控系统自动均衡了整个集群。

8. 关于回滚那里,如果我要新增一个删除功能,怎么做到把这个操作拆成两半,用户做了删除操作,可是禁止删除数据,那是否会产生数据不一致的?

这个是刚才说的那个秘籍第二条。其实秘籍第二条就是拆!没有什么发布是不能拆的。 拆到可以安全的往前滚再往后滚。

9. 100W台服务器如何自动化管理、及时发现故障、自动修复、做出报警,能否简单介绍介绍?

这个问题其实没那么复杂。就是在每个机器上运行一个agent,这个agent定期进行检查操作,有问题就通知管理系统自动下线。只要注意平时收集问题现象就行了。比如说线上突然出现了一个时间不同的问题,那么就把他加到这个agent里去,下次这个问题就是自动检测自动修复的了。

10. 有没有什么好办法处理 query to death?

这个问题比较难,一般是要做一层智能一点的业务 proxy 。业务 proxy 检测到请求发到哪,哪个后端挂,就可以进行一些处理了。还有一个办法是在挂之前后端记log,处理之前记上。我要处理这个请求了,然后处理一半挂掉了。重启之后,检查 log 发现上次是处理这个请求挂了,那么就可以屏蔽掉这个请求。

转载自”高可用架构(ArchNotes)”微信公众号

GitHub 上有哪些值得推荐的开源电子书?

语言无关类操作系统

web服务器

版本控制

编辑器

MySQL

NoSQL

项目相关

设计模式

Web

大数据

编程艺术

语言相关类AWK

SED

Java

Android

C/C++

CSS

Go

Groovy

Haskell

iOS

JavaScript

LaTeX

LISP

Lua

Perl

PHP

Prolog

Python

R

Ruby

Scala

Scheme

Shell

Swift

作者:EZLippi
链接:https://www.zhihu.com/question/38836382/answer/88744155
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

37个最好的学习新东西的网站(译)

忘掉那些在学校或者课堂上学习反而收获甚微的方式吧。这些网站或者APP涵盖科学、艺术和技术。它们会教你一些特别的东东,像用node.js构建APP, 而且大部分是免费的。这不会强制你掌握一个新技能,却能扩展你的知识,甚至促进你的职业。你可以在你喜欢的地方学习或者是你自己的舒服的家里。真的不能再简单了。你还等什么呢?

1、在线课程

edX – 世界上最好的大学的在线课程
Coursera  – 获取世界上最好的课程,在线,免费

Coursmos – 任何时间获取你想要的微课程,任何设备可看
Highbrow – 订阅小的每日课程到收件箱
Skillshare – 激发你的创造力的在线课程和项目
Curious – 在线视频课程来提高你的技能
lynda.com – 学习技术、创造性和商业技能
CreativeLive – 获取世界顶级专家的创造性课程
Udemy – 在线学习现实世界的有用技能

2、学习编程

Codecademy-交互式学习编码,免费
Stuk.io-零基础学习编程
Udacity-获取可被业界承认的技能
Platzi-在线学习设计、市场推广、编码
Learnable-最好的方式学习web开发
Code Scool-亲自动手学习编程
Thinkful-一对一的辅导
Code.org-根据指南现在就开始学习
BaseRails-掌握Ruby on Rails和其他web技术
Treehouse-学习HTML,CSS ,iPhone apps和更多
One Month-一个月内学习编程并构建web应用
Dash-学习制作酷炫的网站

3、和数据打交道

DataCamp-R语言的指南和数据课程
DataQuest-浏览器里学习数据科学
DataMonkey-简单有趣的方式开发你的分析技能

4、学习新的语言

Duolingo-免费学习新语言
Lingvist-200小时内学习一门新的语言
Busuu-免费的语言学习社区
Memrise-用识字卡来学习词汇

5、扩展你的知识

TED-Ed-找到辅助的教育视频
Khan Academy-可交互的非常全面的图书馆
Guides.co-最大的在线指南的搜索
Squareknot-漂亮的指引,一步步的指南
Learnist-学习更专业的内容通过web、纸质、视频
Prismatic-学习社会推荐的一些有趣的内容

6、其它红利

Chesscademy-免费学习国际象棋
Pianu-新的方式学习钢琴,可交互
Yousician-数字时代下你的个人吉他教程

阅读原文

推荐阅读