All posts by dotte

机器学习驱动编程:新世界的新编程

如果今天要重新建立Google,这家公司的大部分系统将会是通过学习得来的,而非编写代码而来。Google的25,000名开发者中原本有大概10%精通机器学习,现在这一比例可能会达到100% — Jeff Dean

和天气一样,大家都会抱怨编程,但谁也没有为此做点什么。这种情况正在发生变化,就像突如其来的暴风雨一样,这些变化也来自一个出乎意料的方向:机器学习/深度学习。

我知道很多人对深度学习都听厌了。谁不是呢?但是编程技术很长时间来都处在一成不变的情况下,是时候做点什么改变这一情况了。

各种有关编程的“战斗”还在继续,但解决不了任何问题。函数还是对象,这种语言还是那种语言,这朵公有云还是那朵公有云或者这朵私有云亦或那朵“填补了空白”的云,REST还是Unrest,这种字节级编码还是另一种编码,这个框架还是那个框架,这种方法论还是那种方法论,裸机还是容器或者虚拟机亦或Unikernel,单层还是微服务或者NanoService,最终一致还是事务型,可变(Mutable)还是不可变(Immutable),DevOps还是NoOps或者SysOps,横向扩展还是纵向扩展,中心化还是去中心化,单线程还是大规模并行,同步还是异步。诸如此类永无止境。

年复一年,天天如此。我们只是创造了调用函数的不同方法,但最终的代码还需要我们人类来编写。更强大的方法应该是让机器编写我们需要的函数,这就是机器学习大展拳脚的领域了,可以为我们编写函数。这种年复一年天天如此的无聊活动还是交给机器学习吧。

机器学习驱动的编程

我最初是和Jeff Dean聊过之后开始接触用深度学习方式编程的。当时我针对聊天内容写了篇文章:《Jeff Dean针对Google大规模深度学习的看法》。强烈建议阅读本文了解深度学习技术。围绕本文的主题,本次讨论的重点在于深度学习技术如何有效地取代人工编写的程序代码:

Google的经验是对于大量子系统,其中一些甚至是通过机器学习方式获得的,使用更为通用的端到端机器学习系统取代它们。通常当你有大量复杂的子系统时,必须通过大量复杂代码将它们连接在一起。Google的目标是让大家使用数据和非常简单的算法取代这一切。

机器学习将成为软件工程的敏捷工具

Google研究总监Peter Norvig针对这个话题进行过详细的讨论:用深度学习与可理解性对抗软件工程和验证。他的大致想法如下:

  • 软件。你可以将软件看作为函数构建的规范,而实现相应的函数就可以满足规范的要求。
  • 机器学习。以(x,y)对为例,你会猜测某一函数会使用x作为参数并生成y作为结果,这样就能很好地概括出x这个新值。
  • 深度学习。依然是以(x,y)对为例,可以通过学习知道你所组建的表征(Representation)具备不同级别的抽象,而非简单直接的输入和输出。这样也可以很好地概括出x这个新值。

软件工程师并不需要介入这个循环,只需要将数据流入机器学习组件并流出所需的表征。

表征看起来并不像代码,而是类似这样:

这种全新类型的程序并非人类可以理解的函数分解(Functional decomposition),看起来更像是一堆参数。

在机器学习驱动的编程(MLDP)世界里,依然可以有人类的介入,不过这些人再也不叫“程序员”了,他们更像是数据科学家。

可以通过范例习得程序的部分内容吗?可以。

  • 有一个包含超过 2000 行代码的开源拼写检查软件的例子,这个软件的效果始终不怎么好。但只要通过包含 17 行代码的朴素贝叶斯分类器就能以同样性能实现这个软件的功能,但代码量减少了100倍,效果也变得更好。
  • AlphaGo是另一个例子,该程序的结构是手工编写的,所有参数则是通过学习得到的。

只通过范例可以习得完整的程序吗?简单的程序可以,但大型传统程序目前还不行。

  • 在Jeff Dean的讲话中,他介绍了一些有关使用神经网络进行序列学习的顺序的细节。借助这种方法可以从零开始构建最尖端的机器翻译程序,这将是一种端到端学习获得的完整系统,无需手工编写大量代码或机器学习的模型即可解决一系列细节问题。
  • 另一个例子是学习如何玩Atari出品的游戏,对于大部分游戏机器可以玩得和人一样好,甚至比人玩得更好。如果按照传统方式对不同组件进行长期的规划,效果肯定不会像现在这么好。
  • 神经图灵机(Neural Turing Machine)也是一次学习如何用程序编写更复杂程序的尝试,但Peter认为这种技术不会走的太远。

正如你所期待的,Norvig先生的这次讲话非常棒,很有远见,值得大家一看。

Google正在以开源代码的方式从GitHub收集数据

深度学习需要数据,如果你想要创建一个能通过范例学习如何编程的AI,肯定需要准备大量程序/范例作为学习素材。

目前Google和GitHub已经开始合作让开源数据更可用。他们已经从GitHub Archive将超过3TB的数据集上传至BigQuery,其中包含超过280万个开源GitHub代码库中包含的活动数据,以及超过1.45亿次提交,和超过20亿不同的文件路径。

这些都可以当作很棒的训练数据。

就真的完美无缺吗?

当然不是。神经网络如同“黑匣子”般的本质使其难以与其他技术配合使用,这就像试图将人类潜意识行为与意识行为背后的原因结合在一起一样。

Jeff Dean还提到了Google搜索评级团队在搜索评级研究工作中运用神经网络技术时的犹豫。对于搜索评级,他们想要了解整个模型,了解做出某一决策的原因。当系统出现错误后他们还想了解为什么会出现这样的错误。

为了解决这样的问题,需要创建配套的调试工具,而相关工具必须具备足够的可理解性。

这样的做法会有效的。针对搜索结果提供的机器学习技术RankBrain发布于2015年,现在已成为第三大最重要的搜索评级指标(指标共有100项)。详情可访问:Google将利润丰厚的网页搜索技术交给AI计算机处理

Peter还通过一篇论文《机器学习:技术债的高利率信用卡》进一步介绍了相关问题的更多细节。缺乏明确的抽象层,就算有Bug你也不知道到底在哪。更改任何细节都要改变全局,很难进行纠正,纠正后的结果更是难以预测。反馈环路,机器学习系统生成数据后会将这些数据重新送入系统,导致反馈环路。诱惑性损害(Attractive Nuisance),一旦一个系统使得所有人都想使用,这样的系统很可能根本无法在不同上下文中使用。非稳态(Non-stationarity),随着时间流逝数据会产生变化,因此需要指出到底需要使用哪些数据,但这个问题根本没有明确答案。配置依赖性,数据来自哪里?数据准确吗?其他系统中出现的改动是否会导致这些数据产生变化,以至于今天看到的结果和昨天不一样?训练用数据和生产用数据是否不同?系统加载时是否丢弃了某些数据?缺乏工具,标准化软件开发有很多优秀的工具可以使用,但机器学习编程是全新的,暂时还没有工具可用。

MLDP是未来吗?

这并不是一篇“天呐,世界末日到了”这样的文章,而是一篇类似于“有些事你可能没听说过,世界又将为此产生变化,这多酷啊”的文章。

这种技术依然处于非常早期的阶段。对程序的部分内容进行学习目前已经是可行的,而对大规模复杂程序进行学习目前还不实用。但是当我们看到标题类似于Google如何将自己重塑为一家“机器学习为先”的公司这样的文章,可能还不明白这到底真正意味着什么。这种技术不仅仅是为了开发类似AlphaGo这样的系统,最终结果远比这个还要深刻。

相关文章

查看英文原文Machine Learning Driven Programming: A New Programming for a New World

from:http://www.infoq.com/cn/articles/machine-learning-programing

Pinterest谈实战经验:如何在两年内实现零到数百亿的月访问

Pinterest一直保持着指数增长,每一个半月都会翻一翻。在两年内,他们实现了从0到数百亿的月PV;从开始的两个创始人加一个工程师增长到现在超过40个工程师,从一个小型的MySQL服务器增长到180个Web Enigne、240个API Enigne、88个MySQL DB(cc2.8xlarge,每个DB都会配置一个从属节点)、110个Redis Instance以及200个Mmecache Instance。

在一个名为 《Scaling Pinterest》 的主题演讲上,Pinterest的Yashwanth NelapatiMarty Weiner为我们讲述了这个戏剧性的过程。当然扩展到当下规模,Pinterest在众多选择中不可避免的走了许多的弯路,而Todd Hoff认为其中最宝贵的经验该归结于以下两点:

  1. 如果你的架构应对增长所带来的问题时,只需要简单的投入更多的主机,那么你的架构含金量十足。
  2. 当你把事物用至极限时,这些技术都会以各自不同的方式发生故障,这导致他们对工具的选择有着特殊的偏好:成熟、简单、优秀、知名、被更多的用户喜爱、更好的支持、稳定且杰出的表现、通常情况下无故障以及免费。使用这些标准,他们选择了MySQL、Solr、Memcache、Redis、Cassandra,同时还抛弃了MongoDB。

同样这两个点是有关联的,符合第二个原则的工具就可以通过投入更多的主机进行扩展。即使负载的增加,项目也不会出现很多故障。即使真的出现难以解决的问题,至少有一个社区去寻找问题解决的方案。一旦你选择过于复杂和挑剔的工具,在扩展的道路上将充满荆棘。

需要注意的是所有他们选择的工具都依靠增加分片来进行扩展,而非通过集群。讲话中还阐述了为什么分片优于集群以及如何进行分片,这些想法可能是之前你闻所未闻的。

下面就看一下Pinterest扩展的阶段性时间轴:

项目背景

  • Pins是由其它零零碎碎信息集合成的图片,显示了对客户重要的信息,并且链接到它所在的位置。
  • Pinterest是一个社交网络,你可以follow(关注)其他人以及board。
  • 数据库:Pinterest的用户拥有board,而每个board都包含pin;follow及repin人际关系、验证信息。

1. 2010年3月发布——寻找真我的时代

在那时候,你甚至不知道需要建立一个什么样的产品。你有想法,所以你快速的迭代以及演变。而最终你将得到一些很小的MySQL查询,而这些查询在现实生活中你从未进行过。

Pinterest初期阶段的一些数字:

  • 2个创始人
  • 1个工程师
  • Rackspace
  • 1个小的网络引擎
  • 1个小的MySQL数据库
  • 2011年11月

仍然是小规模,产品通过用户反馈进行演变后的数字是:

  • Amazon EC2 + S3 + CloudFront
  • 1 NGinX, 4 Web Engines (用于冗余,不全是负载)
  • 1 MySQL DB + 1 Read Slave (用于主节点故障情况)
  • 1 Task Queue + 2 Task Processors
  • 1 MongoDB (用于计数)
  • 2 Engineers

2. 贯穿2011年——实验的时代

迈上疯狂增长的脚步,基本上每1个半月翻一翻。

  • 当你增长的如此之快,每一天每一星期你可能都需要打破或者抛弃一些东西。
  • 在这个时候,他们阅读大量的论文,这些论文都阐述着只需要添加一台主机问题就会得以解决。他们着手添加许多技术,随后又不得不放弃。
  • 于是出现了一些很奇怪的结果
  • Amazon EC2 + S3 + CloudFront
  • 2NGinX, 16 Web Engines + 2 API Engines
  • 5 Functionally Sharged MySQL DB + 9 read slaves
  • 4 Cassandra Nodes
  • 15 Membase Nodes (3 separate clusters)
  • 8 Memcache Nodes
  • 10 Redis Nodes
  • 3 Task Routers + 4 Task Processors
  • 4 Elastic Search Nodes
  • 3 Mongo Clusters
  • 3个工程师
  • 5个主数据库技术,只为了独立其中的数据。
  • 增长太快以至于MySQL疲于奔命,所有其它的技术也达到了极限。
  • 当你把事物用至极限时,这些技术都会以各自不同的方式出错。
  • 开始抛弃一些技术,并且自我反省究竟需要些什么,基本上重做了所有的架构。

3. 2012年2月——成熟的时代

  • 在重做了所有的架构后,系统呈现了如下状态
  • Amazon EC2 + S3 + Akamai, ELB
  • 90 Web Engines + 50 API Engines
  • 66 MySQL DBs (m1.xlarge) +,每个数据库都配备了从属节点
  • 59 Redis Instances
  • 51 Memcache Instances
  • 1 Redis Task Manager + 25 Task Processors
  • Sharded Solr
  • 6个工程师
  • 现在采用的技术是被分片的MySQL、Redis、Memcache和Solr,有点在于这些技术都很简单很成熟。
  • 网络传输增长仍然保持着以往的速度,而iPhone传输开始走高。

4. 2012年10月12日 —— 收获的季节

大约是1月份的4倍

  • 现在的数据是:
  • Amazon EC2 + S3 + Edge Cast,Akamai, Level 3
  • 180 Web Engines + 240 API Engines
  • 88 MySQL DBs (cc2.8xlarge) ,同样每个数据库都有一个从属节点
  • 110 Redis Instances
  • 200 Memcache Instances
  • 4 Redis Task Manager + 80 Task Processors
  • Sharded Solr
  • 40个工程师(仍在增长)
  • 需要注意的是,如今的架构已趋近完美,应对增长只需要投入更多的主机。
  • 当下已开始转移至SSD

下面一览该演讲中的干货,决策的制定:

为什么会选择EC2和S3

  1. 相当好的可靠性,即使数据中心发生故障。多租户会增加风险,但是也不是太坏。
  2. 良好的报告和支持。它们(EC2和S3)有着良好的架构,并且知道问题所在。
  3. 完善的周边设施,特别是在你需要快速增长时。你可以从APP Engine处获得maged cache、负载均衡、MapReduce、数据库管理以及其它你不想自己动手编写的组件,这可以加速你应用程序的部署,而在你工程师空闲时,你可以着手编写你需要的一切。
  4. 新的实例可以在几秒内就绪,这就是云的力量;特别是在只有两个工程师的初期,不需要去担心容量规划,更不需要花两个星期去建立自己的Memcache,你可以在数分钟内添加10个Memcached。
  5. 缺点:有限的选择。直到最近,才可以选择使用SSD,同时无法获得太大的内存配置。
  6. 优点:你不需要给大量的主机进行不同的配置。

为什么会选择MySQL

  1. 非常成熟。
  2. 非常稳定。不会宕机,并且不会丢失数据。
  3. 在招聘上具有优势,市场上有大把的人才。
  4. 在请求呈直线上升时,仍能将相应时间控制在一定的范围内,有些数据库技术在面对请求的飙升时表现并不是很好。
  5. 非常好的周边软件支持——XtraBackup、Innotop、Maatkit。
  6. 可以从类似Percona这样的公司得到优秀的技术支持。
  7. 开源(免费)——这一点非常重要,特别是在资金缺乏的初期

为什么使用Memcache

  • 非常成熟。
  • 非常简单。可以当成是一个socket哈希表
  • 杰出稳定的表现
  • 知名并为大量用户喜爱
  • 永不崩溃
  • 开源

为什么选择Redis

  • 虽然还不够成熟,但是非常简单及优秀
  • 提供了大量的数据结构类型
  • 提供多种的选择进行持久化和备份:你可以备份而非持久化,选择备份的话你还可以选择多久备份一次;同样你还可以选择使用什么方式进行持久化,比如MySQL等。
  • Home feed被储存在Redis上,每3个小时保存一次;然而并不是3个小时持久化一次,只是简单的每3个小时备份一次。
  • 如果你存储数据的主机发生故障,丢失的也只是备份周期内的数据。虽然不是完全可靠,但是非常简单。避免了复杂的持久化及复制,这样的架构简单且便宜。
  • 知名并为大量用户喜爱
  • 稳定且杰出的表现
  • 很少出故障。有一些专有的故障模型,你需要学会解决。这也是成熟的优势,只需要学习就可以解决。
  • 开源

Solr

  1. 只需要几分钟的安装时间,就可以投入使用
  2. 不能扩展到多于一台的机器上(最新版本并非如此)
  3. 尝试弹性搜索,但是以Pinterest的规模来说,可能会因为零碎文件和查询太多而产生问题。
  4. 选择使用Websolr,但是Pinterest拥有搜索团队,将来可能会开发自己的版本。

集群vs.分片

  • 在迅速扩展的过程中,Pinterest认识到每次负载的增加,都需要均匀的传播他们的数据。
  • 针对问题先确定解决方案的范围,他们选择的范围是集群和分片之间的一系列解决方案。

集群——所有的操作都是通过自动化

  • 比如:Cassandra、MemBase、HBase
  • 结论:没有安全感,将来可能会比较成熟,但是当下这个解决方案中还存在太多的复杂性和故障点。
  • 特性:
  • 数据自动分布
  • 节点间转移数据
  • 需要平衡分配
  • 节点间的相互通信,需要做很多措施用于防止干扰、无效传递及协商。
  • 优点:
  • 自动扩展你的数据存储,最起码论文中是这么说的。
  • 便于安装
  • 数据上的空间分布及机房共置。你可以在不同区域建立数据中心,数据库会帮你打理好一切。
  • 高有效性
  • 负载平衡
  • 不存在单点故障
  • 缺点:
  • 仍然不成熟。
  • 本质上说还很复杂。一大堆的节点必须对称协议,这一点非常难以解决。
  • 缺少社区支持。社区的讨论因为产品方向的不同而不能统一,而在每个正营中也缺乏强有力的支持。
  • 缺乏领域内资深工程师,可能大多数的工程师都还未使用过Cassandra。
  • 困难、没有安全感的机制更新。这可能是因为这些技术都使用API并且只在自己的领域内通行,这导致了复杂的升级路径。
  • 集群管理算法本身就用于处理SPOF(单点故障),如果存在漏洞的话可能就会影响到每个节点。
  • 集群管理器代码非常复杂,并且需要在所有节点上重复,这就可能存在以下的故障模式:
  • 数据平衡失控。当给集群中添加新的主机时,可能因为数据的拷贝而导致集群性能下降。那么你该做什么?这里不存在去发现问题所在的工具。没有社区可以用来求助,同样你也被困住了,这也是Pinterest回到MySQL的原因。
  • 跨节点的数据损坏。如果这里存在一个漏洞,这个漏洞可能会影响节点间的日志系统和压缩等其它组件?你的读延时增加,所有的数据都会陷入麻烦以及丢失。
  • 错误负载平衡很难被修复,这个现象十分普遍。如果你有10个节点,并且你注意到所有的负载都被堆积到一个节点上。虽然可以手动处理,但是之后系统还会将负载都加之一个节点之上。
  • 数据所有权问题,主次节点转换时的数据丢失。集群方案是非常智能的,它们会在特定的情况下完成节点权利的转换,而主次节点切换的过程中可能会导致数据的部分丢失,而丢失部分数据可能比丢失全部还糟糕,因为你不可能知道你究竟丢失了哪一部分。

分片——所有事情都是手动的

  • 结论:它是获胜者。Todd Hoff还认为他们的分片架构可能与Flickr架构类似。
  • 特性:
  • 分片可以让你摆脱集群方案中所有不想要的特性。
  • 数据需要手动的分配。
  • 数据不会移动。Pinterest永远都不会在节点间移动,尽管有些人这么做,这让他们在一定范围内站的更高。
  • 通过分割数据的方式分配负载。
  • 节点并没有互相通信,使用一些主节点控制程序的运行。
  • 优点:
  • 可以分割你的数据库以提高性能。
  • 空间分布及放置数据
  • 高有效性
  • 负载平衡
  • 放置数据的算法非常简单。主要原因是,用于处理单点故障的代码只有区区的半页,而不是一个复杂的集群管理器。并且经过短暂的测试就知道它是否能够正常工作。
  • ID生成非常简单
  • 缺点:
  • 不可以执行大多数的join。
  • 失去所有事务的能力。在一个数据库上的插入可能会成功,而在另一个上会失败。
  • 许多约束必须放到应用程序层。
  • 模式的转变需要从长计议。
  • 报告需要在所有分片上执行查询,然后需要手动的进行聚合。
  • Join在应用程序层执行。
  • 应用程序必须容忍以上所有问题。

什么时候进行分片

  1. 如果你的项目拥有PB级的数据,那么你需要立刻对其进行分片。
  2. Pin表格拥有百万行索引,索引大小已经溢出内存并被存入了磁盘。
  3. Pinterest使用了最大的表格,并将它们(这些索引)放入自己的数据库。
  4. 然后果断的超过了单数据库容量。
  5. 接着Pinterest必须进行分片。

分片的过渡

  • 过渡从一个特性的冻结开始。
  • 确认分片该达到什么样的效果——希望尽少的执行查询以及最少数量的数据库去呈现一个页面。
  • 剔除所有的MySQL join,将要做join的表格加载到一个单独的分片去做查询。
  • 添加大量的缓存,基本上每个查询都需要被缓存。
  • 这个步骤看起来像:
  • 1 DB + Foreign Keys + Joins
  • 1 DB + Denormalized + Cache
  • 1 DB + Read Slaves + Cache
  • Several functionally sharded DBs+Read Slaves+Cache
  • ID sharded DBs + Backup slaves + cache
  • 早期的只读从属节点一直都存在问题,因为存在slave lag。读任务分配给了从属节点,然而主节点并没有做任何的备份记录,这样就像一条记录丢失。之后Pinterest使用缓存解决了这个问题。
  • Pinterest拥有后台脚本,数据库使用它来做备份。检查完整性约束、引用。
  • 用户表并不进行分片。Pinterest只是使用了一个大型的数据库,并在电子邮件和用户名上做了相关的一致性约束。如果插入重复用户,会返回失败。然后他们对分片的数据库做大量的写操作。

如何进行分片

  • 可以参考Cassandra的ring模型、Membase以及Twitter的Gizzard。
  • 坚信:节点间数据传输的越少,你的架构越稳定。
  • Cassandra存在数据平衡和所有权问题,因为节点们不知道哪个节点保存了另一部分数据。Pinterest认为应用程序需要决定数据该分配到哪个节点,那么将永远不会存在问题。
  • 预计5年内的增长,并且对其进行预分片思考。
  • 初期可以建立一些虚拟分片。8个物理服务器,每个512DB。所有的数据库都装满表格。
  • 为了高有效性,他们一直都运行着多主节点冗余模式。每个主节点都会分配给一个不同的可用性区域。在故障时,该主节点上的任务会分配给其它的主节点,并且重新部署一个主节点用以代替。
  • 当数据库上的负载加重时:
  • 先着眼节点的任务交付速度,可以清楚是否有问题发生,比如:新特性,缓存等带来的问题。
  • 如果属于单纯的负载增加,Pinterest会分割数据库,并告诉应用程序该在何处寻找新的节点。
  • 在分割数据库之前,Pinterest会给这些主节点加入一些从属节点。然后置换应用程序代码以匹配新的数据库,在过渡的几分钟之内,数据会同时写入到新旧节点,过渡结束后将切断节点之间的通道。

ID结构

  • 一共64位
  • 分片ID:16位
  • Type:10位—— Board、User或者其它对象类型
  • 本地ID——余下的位数用于表中ID,使用MySQL自动递增。
  • Twitter使用一个映射表来为物理主机映射ID,这将需要备份;鉴于Pinterest使用AWS和MySQL查询,这个过程大约需要3毫秒。Pinterest并没有让这个额外的中间层参与工作,而是将位置信息构建在ID里。
  • 用户被随机分配在分片中间。
  • 每个用户的所有数据(pin、board等)都存放在同一个分片中,这将带来巨大的好处,避免了跨分片的查询可以显著的增加查询速度。
  • 每个board都与用户并列,这样board可以通过一个数据库处理。
  • 分片ID足够65536个分片使用,但是开始Pinterest只使用了4096个,这允许他们轻易的进行横向扩展。一旦用户数据库被填满,他们只需要增加额外的分片,然后让新用户写入新的分片就可以了。

查找

  • 如果存在50个查找,举个例子,他们将ID分割且并行的运行查询,那么延时将达到最高。
  • 每个应用程序都有一个配置文件,它将给物理主机映射一个分片范围。
  • “sharddb001a”: : (1, 512)
  • “sharddb001b”: : (513, 1024)——主要备份主节点
  • 如果你想查找一个ID坐落在sharddb003a上的用户:
  • 将ID进行分解
  • 在分片映射中执行查找
  • 连接分片,在数据库中搜寻类型。并使用本地ID去寻找这个用户,然后返回序列化数据。

对象和映射

  • 所有数据都是对象(pin、board、user、comment)或者映射(用户由baord,pin有like)。
  • 针对对象,每个本地ID都映射成MySQL Blob。开始时Blob使用的是JSON格式,之后会给转换成序列化的Thrift。
  • 对于映射来说,这里有一个映射表。你可以为用户读取board,ID包含了是时间戳,这样就可以体现事件的顺序。
  • 同样还存在反向映射,多表对多表,用于查询有哪些用户喜欢某个pin这样的操作。
  • 模式的命名方案是:noun_verb_noun: user_likes_pins, pins_like_user。
  • 只能使用主键或者是索引查找(没有join)。
  • 数据不会向集群中那样跨数据的移动,举个例子:如果某个用户坐落在20分片上,所有他数据都会并列存储,永远不会移动。64位ID包含了分片ID,所以它不可能被移动。你可以移动物理数据到另一个数据库,但是它仍然与相同分片关联。
  • 所有的表都存放在分片上,没有特殊的分片,当然用于检测用户名冲突的巨型表除外。
  • 不需要改变模式,一个新的索引需要一个新的表。
  • 因为键对应的值是blob,所以你不需要破坏模式就可以添加字段。因为blob有不同的版本,所以应用程序将检测它的版本号并且将新记录转换成相应的格式,然后写入。所有的数据不需要立刻的做格式改变,可以在读的时候进行更新。
  • 巨大的胜利,因为改变表格需要在上面加几个小时甚至是几天的锁。如果你需要一个新的索引,你只需要建立一张新的表格,并填入内容;在不需要的时候,丢弃就好。

呈现一个用户文件界面

  1. 从URL中取得用户名,然后到单独的巨型数据库中查询用户的ID。
  2. 获取用户ID,并进行拆分
  3. 选择分片,并进入
  4. SELECT body from users WHERE id = <local_user_id>
  5. SELECT board_id FROM user_has_boards WHERE user_id=<user_id>
  6. SELECT body FROM boards WHERE id IN (<boards_ids>)
  7. SELECT pin_id FROM board_has_pins WHERE board_id=<board_id>
  8. SELECT body FROM pins WHERE id IN (pin_ids)
  9. 所有调用都在缓存中进行(Memcache或者Redis),所以在实践中并没有太多连接数据库的后端操作。

脚本相关

  1. 当你过渡到一个分片架构,你拥有两个不同的基础设施——没有进行分片的旧系统和进行分片的新系统。脚本成为了新旧系统之间数据传输的桥梁。
  2. 移动5亿的pin、16亿的follower行等。
  3. 不要轻视项目中的这一部分,Pinterest原认为只需要2个月就可以完成数据的安置,然而他们足足花了4至5个月时间,别忘了期间他们还冻结了一项特性。
  4. 应用程序必须同时对两个系统插入数据。
  5. 一旦确认所有的数据都在新系统中就位,就可以适当的增加负载来测试新后端。
  6. 建立一个脚本农场,雇佣更多的工程师去加速任务的完成。让他们做这些表格的转移工作。
  7. 设计一个Pyres副本,一个到GitHub Resque队列的Python的接口,这个队列建立在Redis之上。支持优先级和重试,使用Pyres取代Celery和RabbitMQ更是让他们受益良多。
  8. 处理中会产生大量的错误,用户可能会发现类似丢失board的错误;必须重复的运行任务,以保证在数据的处理过程中不会出现暂时性的错误。

开发相关

  • 开始尝试只给开发者开放系统的一部分——他们每个人都拥有自己的MySQL服务器等,但是事情改变的太快,以至于这个模式根本无法实行。
  • 转变成Facebook模式,每个人都可以访问所有东西,所以不得不非常小心。

未来的方向

  • 基于服务的架构
  • 当他们发现大量的数据库负载,他们开始布置大量的应用程序服务器和一些其它的服务器,所有这些服务器都连接至MySQL和Memcache。这意味着在Memcache上将存在3万的连接,这些连接将占用几个G的内存,同时还会产生大量的Memcache守护进程。
  • 为了解决这个问题,将这些工作转移到了一个服务架构。比如:使用一个follower服务,这个服务将专注处理follower查询。这将接下30台左右的主机去连接数据库和缓存,从而减少了连接的数量。
  • 对功能进行隔离,各司其职。让一个服务的开发者不能访问其它的服务,从而杜绝安全隐患。

学到的知识

  1. 为了应对未来的问题,让其保持简单。
  2. 让其变的有趣。只要应用程序还在使用,就会有很多的工程师加入,过于复杂的系统将会让工作失去乐趣。让架构保持简单就是大的胜利,新的工程师从入职的第一周起就可以对项目有所贡献。
  3. 当你把事物用至极限时,这些技术都会以各自不同的方式发生故障。
  4. 如果你的架构应对增长所带来的问题时,只需要简单的投入更多的主机,那么你的架构含金量十足。
  5. 集群管理算法本身就用于处理SPOF,如果存在漏洞的话可能就会影响到每个节点。
  6. 为了快速的增长,你需要为每次负载增加的数据进行均匀分配。
  7. 在节点间传输的数据越少,你的架构越稳定。这也是他们弃集群而选择分片的原因。
  8. 一个面向服务的架构规则。拆分功能,可以帮助减少连接、组织团队、组织支持以及提升安全性。
  9. 搞明白自己究竟需要什么。为了匹配愿景,不要怕丢弃某些技术,甚至是整个系统的重构。
  10. 不要害怕丢失一点数据。将用户数据放入内存,定期的进行持久化。失去的只是几个小时的数据,但是换来的却是更简单、更强健的系统!

原文链接: Scaling Pinterest – From 0 To 10s Of Billions Of Page Views A Month In Two Years (编译/仲浩 审校/王旭东)

from:http://www.csdn.net/article/2013-04-16/2814902-how-pinterest-scaling-0-to-billions-pv

Amazon’s AWS

原文链接:A Beginner’s Guide To Scaling To 11 Million+ Users On Amazon’s AWS

译者:杰微刊–汪建

 

一个系统从一个用户到多于1100万用户访问,你将如何对你的系统进行扩展?Amazon的web服务解决方案架构师乔尔?威廉姆斯就此话题给出了一个精彩的演讲:2015扩展你的第一个一千万用户。
如果你是一个拥有较丰富的AWS使用经验的用户,这个演讲将不太适合你,但如果你作为一个刚接触云、刚接触AWS的新用户,或者你还没有跟上Amazon源源不断对外发布的AWS新特性,它将是一个很好的入门资料。
正如大家所期望的,这个演讲讨论Amazon服务如何针对问题提出先进且主流的解决方案,Amazon平台总是令人印象深刻且拥有指导性。对于如何把所有产品组合在一起Amazon做了大量工作去提取出用户需要的是什么,并且确保Amazon对于每个用户的需求都拥有一个产品能满足这部分的需求。
演讲的一些有趣的要点:

1、一般刚开始时使用SQL而在必要时刻转向NoSQL。
2、一致的观点是通过引入组件去解耦系统,使用组件便于扩展并且组件故障不会影响到其他模块。组件便于使系统分层和构建微服务。
3、只把区别于已有任务的部分作为你的业务逻辑,不要重复发明轮子。
4、可伸缩性和冗余性不是两个互相独立的概念,你经常要将两个概念同时放在一起考虑。
5、没有提及成本,成为AWS解决方案被批评的一个主要方面。

 

基本情况
AWS覆盖全世界12个国家区域

1. 每个区域都对应着世界上的一个物理位置,每个位置都有弹性计算云提供多个可用区域(Availability Zones),这些区域包含北美、南美、欧洲、中东、非洲、亚太等地区。
2. 每个可用区域(AZ)实质上是单个数据中心,尽管它可由多个数据中心构造。
3. 每个可用区域都拥有很强的隔离性,他们各自拥有独立的电源和网络。
4. 可用区域之间只能通过低延迟网络互相连接,它们可以相距5或15英里,但网络的速度相当快以至于你的应用程序像在同一个数据中心。
5. 每个区域至少有2个可用区域,可用区域总共有32个。
6. 借助若干可用区域即可构建一个高可用的架构供你的应用使用。
7. 在即将到来的2016年将会增加至少9个可用区域和4个区域。

 

AWS在世界上拥有53个边缘位置
1. 这些边缘位置被用于Amazon的内容分发网络CDN、Route53、CloudFront以及Amazon的DNS管理服务器。
2. 边缘位置使用户可以在世界的任何角落低延迟地访问网页。
构建块服务
1. AWS已经使用多个可用区域构架了大量服务供使用,这些服务内部拥有高可用性和容错性。以下是可供使用的服务列表。
2. 你可以在你的应用中直接使用这些服务,它们是收费的,但使用它们你可以不必自己考虑高可用性。
3. 每个可用区域都提供很多服务,包括CloudFront, Route 53, S3, DynamoDB, 弹性负载均衡, EFS, Lambda, SQS, SNS, SES, SWF。
4. 即使这些服务只存在于一个单一的可用区域,通过使用这些服务任然可以构建一个高可用架构。
一个用户
在这种情况下,你是作为仅有的用户,你仅仅只想让web应用跑起来。
你的架构看起来像下面几点:

1. 运行在单独的实例上,可能是t2.micro型。实例类型包括了CPU、内存、存储和网络的不同组合,通过选择这些不同实例类型组成一个适合你的web应用的资源。
2. 在单独的实例上运行整个web栈,例如web应用程序、数据库以及各种管理系统等。
3. 使用Amazon的Route53作为DNS服务。
4. 在此实例上添加一个的弹性IP。
5. 在一段时间内运行的良好。
纵向扩展
1、你需要一个更大的容器放置你的应用,最简单的扩展方法是选择一个更大的实例类型,例如c4.8xlarge或者m3.2xlarge。
2、这种方法称为纵向扩展。
3、需要做的仅仅是选择一个新型实例取代原来的实例,应用跑起来即可以更加强大。
4、提供多种不同的硬件配置混搭选择,可以选择一个244G内存的系统(2TB的RAM即将到来),也可以选择40个CPU内核的系统,可以组成I/0密集型实例、CPU密集型实例以及高存储型实例。
5、Amazon的一些服务使用可配置的IOPS选项来保证性能,你可以使用小一点的实例去跑你的应用,对于需要扩展的服务独立使用Amazon的可扩展服务,例如DynamoDB。
6、纵向扩展有一个很大的问题:它不具备failover功能,同时也不具备冗余性。就像把所有鸡蛋都放在同一个篮子里,一旦实例发生故障你的web也会宕掉。
7、一个单独的实例最终能做到的也就这些,想要更加强大需要其他的措施。
10+用户
将单个主机分为多个主机
1. Web应用使用一台主机。
2. 数据库使用一台主机,你可以在上面跑任意数据库,只要负责数据库的管理。
3. 将主机分离成多个主机可以让web应用和数据库各自独立对自己进行扩展,例如在某种情况下可能你需要的数据库比web应用更大的规模。
或者你可以不自己搭建数据库转而使用Amazon的数据库服务
1. 你是一个DBA吗?你真的想要担心数据备份的问题吗?担心高可用?担心数据库补丁?担心操作系统?
2. 使用Amazon数据库服务有一大优势,你只要简单一点击即可完成多可用区域的数据库的安装,而且你不必担心这些可用区域之间的数据备份或其他类似的事情,这些数据库具备高可用性高可靠性。
正如你所想,Amazon有几种类型的完全托管数据库服务供出售:
1. Amazon RDS(Relational Database Service),可供选择的数据库类型相当多,包括Microsoft SQL Server, Oracle, MySQL, PostgreSQL, MariaDB, Amazon Aurora.
2. Amazon DynamoDB,一个NoSQL数据库。
3. Amazon Redshift,一个PB级的数据仓库系统。
更多Amazon 特性
1. 拥有自动扩展存储到64TB的能力,你不再需要限定你的数据存储。
2. 多大15个读副本。
3. 持续增量备份到S3。
4. 多达6路备份到3个可用区域,有助于处理故障。
5. MySQL兼容。
用SQL数据库取代NoSQL数据库
1. 建议使用SQL数据库。
2. SQL数据库相关技术完善。
3. 存在大量开源源码、社区、支持团队、书籍和工具。
4. 千万用户级别系统的还不足以拖垮SQL数据库,除非你的数据非常巨大。
5. 具有清晰的扩展模式。
什么时候你才需要使用NoSQL数据库
1. 如果你一年需要存储超过5TB的数据,或者你有一个令人难以置信的数据密集任务。
2. 你的应用具有超低延迟需求。
3. 你的应用需要一个非常高的吞吐量,需要在数据的读写I/O上进行优化。
4. 你的应用没有任何关系型数据。
100+用户
在web层进行主机分离。
使用Amazon RDS存储数据,它把数据库的所有工作都揽下了。
上面两点做好即可。

 

1000+用户
现在你构建的应用存在可用性问题,你的web应用将会宕掉如果你web服务的主机宕掉了。
你需要在另外一个可用区域上搭建另外一个web实例,由于可用区域之间拥有毫秒级别的低延迟,他们看起来就像互相挨着。
同样,你需要在另外一个可用区域上搭建一个RDS数据库slave,组成主备数据库,一旦主数据库发生故障你的web应用将会自动切换到slave备数据库。由于你的应用总是使用相同的端,failover不会带给应用任何改变。
在两个可用区域中分布着两个web主机实例,使用弹性负载均衡器(ELB)将用户访问分流到两个web主机实例。
弹性负载均衡器(ELB)
1. ELB是一个高可用的负载均衡器,它存在于所有的可用区域中,对于你的应用来说它是一个DNS服务,只需要把他放到Route53即可,它就会在你的web主机实例中进行负载分发。
2. ELB有健康检查机制,这个机制保证流量不会分发到宕掉的主机上。
3. 不用采取任何措施即可完成扩展,当它发现额外流量时它将在后台通过横向和纵向扩展,随着你的应用不断扩展,它也会自动不断扩展,而且这些都是系统自动完成的,你不必对ELB做任何管理。
10000到100000用户
前面例子中说到ELB后面挂载两个web主机实例,而实际上你可以在ELB后面挂载上千个主机实例,这就叫横向扩展。
添加更多的读副本到数据库中,或者添加到RDS中,但需要保持副本的同步。
通过转移一些流量到web层服务器减轻web应用的压力,例如从你的web应用中将静态内容抽离出来放到Amazon S3和Amazon CloudFront上,CloudFront是Amazon的CDN,它会将你的静态内容保存在全世界的53个边缘地区,通过这些措施提高性能和效率。
Amazon S3是一个对象仓库。
1. 它不像EBS,它不是搭载在EC2实例上的存储设备,它是一个对象存储而不是块存储。
2. 对于静态内容如JavaScript、css、图片、视频等存放在Amazon S3上再合适不过,这些内容没必要放到EC2实例上。
3. 高耐用性,11个9的可靠性。
4. 无限制的可扩展,只要你想可以往里面扔尽可能多的数据,用户在S3上存储了PB级别的数据。
5. 支持最大5TB的对象存储。
6. 支持加密,你可以使用Amazon的加密,或者你自己的加密,又或者第三方的加密服务。
Amazon CloudFront对你的内容提供缓存
1. 它将内容缓存在边缘地区以便供你的用户低延迟访问。
2. 如果没有CDN,将导致你的用户更高延迟地访问你的内容,你的服务器也会因为处理web层的请求而处于更高的负载。
3. 例如有个客户需要应对60Gbps的访问流量,CloudFront将一切都处理了,web层甚至都不知道有这么大的访问流量存在。
你还可以通过转移session状态减轻你的web层的负载
1. 将session状态保存到ElastiCache或DynamoDB。
2. 这个方法也让你的系统在未来可以自动扩展。
你也可以将数据库的一些数据缓存在ElastiCache减轻应用负载
数据库没有必要处理所有获取数据的请求,缓存服务可以处理这些请求从而让宝贵的数据库资源处理更加重要的操作。
Amazon DynamoDB——全托管的NoSQL数据库
1. 根据你自己想要的吞吐量,定制你想要的读写性能。
2. 支持高性能。
3. 具备分布式和容错性,它部署在多个可用区域中。
4. 它以kv结构存储,且支持JSON格式。
5. 支持最大400k大的文件。
Amazon Elasticache ——全托管的Memcached或Redis
1. 维护管理一个memcached集群并不会让你赚更多的钱,所以让Amazon来做。
2. Elasticache集群会自动帮你扩展,它是一个具备自我修复特性的基础设施,如果某些节点宕掉了其它的新节点即会自动启动。
你也可以转移动态内容到CloudFront减轻负载
众所周知CloudFront能处理静态内容,例如文件,但除此之外它还还能处理某些动态内容,这个话题不再进行深入的探讨,可以看看这个链接。
自动扩展
对于黑色星期五,假如你不用做任何扩展就足够处理这些峰值流量,那么你是在浪费钱。如果需求和计算能力相匹配自然是最好的,而这由自动扩展帮你实现,它会自动调整计算集群的大小。
作为用户,你可以决定集群的最小实例数和最大实例数,通过实例池中设置最小和最大实例数即可。
云监控是一种嵌入应用的管理服务
1. 云监控的事件触发扩展。
2. 你准备扩展CPU的数量吗?你准备优化延迟吗?准备扩展带宽吗?
3. 你也可以自定义一些指标到云监控上,如果你想要指定应用针对某些指标自动扩展,只需将这些指标放到云监控上,告诉根据云监控根据这些指标分别扩展哪些资源。
500000+用户
前面的配置可以自动扩展群组添加到web层,在两个可用区域里自动扩展群组,也可以在三个可用区域里扩展,在不同可用区域中的多实例模式不经可以确保可扩展性,同时也保证了可用性。
论题中的案例每个可用区域只有3个web层实例,其实它可以扩展成上千个实例,而你可以设置实例池中最小实例数为10最大实例数为1000。
ElastiCache用于承担数据库中热点数据的读负载。
DynamoDB用于Session数据的负载。
你需要增加监控、指标以及日志。
1. 主机级别指标,查看自动扩展的集群中的某一CPU参数,快速定位到问题的位置。
2. 整体级别指标,查看弹性负载均衡的指标判断整个实例集群的整体性能。
3. 日志分析,使用CloudWatch日志查看应用有什么问题,可以使用CloudTrail对这些日志进行分析管理。
4. 外部站点监控,使用第三方服务例如New Relic或Pingdom监控作为终端用户看到了什么情况。
你需要知道你的用户的反馈,他们是不是访问延迟很慢,他们在访问你的web应用时是不是出现了错误。
从你的系统结构中尽可能多地排出性能指标,这有助于自动扩展的决策,你可不希望你的系统CPU使用率才20%。
自动化运维
随着基础设施越来越大,它扩展到了上千个实例,我们有读副本,我们有水平横线扩展,对于这些我们需要一些自动化运维措施去对他们进行管理,我们可不希望对着每个实例一个一个单独地管理。
动化运维工具分为两个层级
1. DIY层,包括Amazon EC2和AWS CloudFormation。
2. 更高层次的服务,包括AWS Elastic Beanstalk和AWS OpsWorks。
AWS Elastic Beanstalk,为你的应用自动管理基础设施,很方便。
AWS OpsWorks,应用程序管理服务,用于部署和操作不同形态规模的应用程序,它还能做到持续集成。
AWS CloudFormation
1. 提供了最大的灵活性,它提供了你的应用栈的模板,它可以构建你的整个应用栈,或者仅仅是应用栈中的某个组件。
2. 如果你要更新你的应用栈你只要更新CloudFormation模板,它将更新你的整个应用。
3. 它拥有大量的控制,但缺乏便利性。
AWS CodeDeploy,部署你的程序到整个EC2实例集群
1. 可以部署一到上千个实例。
2. Code Deploy可以指向一个自动扩展配置。
3. 可连同Chef和Puppet一起使用。
解耦基础设施
使用SOA/微服务,从你的应用抽离出不同服务,就像前面你将web层与数据库层分离出来那样,再分别创建这些服务。
这些独立出来的服务就可以根据自己需要扩展,它给你系统的扩展带来了灵活性,同时也保证了高可用性。
SOA是Amazon搭建架构关键的组成部分。
松耦合解放了你
1. 你可以对某些服务单独地扩展和让它失效。
2. 如果一个工作节点从SQS拉取数据失败,没有没关系?没有,只要重启另外一个工作节点即可,所有操作都有可能发生故障,所以一定要搭建一个可以处理故障的架构,提供failover功能。
3. 将所有模块设置成黑盒。
4. 把交互设计成松耦合方式。
5. 优先考虑内置了冗余性和可扩展性的服务,而不是靠自己构建实现。
不要重复发明轮子
只需把你区别于已有任务的部分作为你的业务逻辑。
Amazon的很多服务本身具备容错能力,因为他们跨多个可用区域,例如:队列、邮件、转码、搜索、数据库、监控、性能指标采集、日志处理、计算等服务,没有必要自己搭建。
SQS:队列服务
1. Amazon提供的第一个服务。
2. 它是跨可用区域的所以拥有容错性。
3. 它具备可扩展性、安全性、简单性。
4. 队列可以帮助你的基础设施上的不同组件之间传递消息。
5. 以图片管理系统为例,图片收集系统和图片处理系统是两个不同的系统,他们各自都可以独立地扩展,他们之间具备松耦合特性,摄取照片然后扔进队列里面,图片处理系统可以拉取队列里面的图片再对其进行其他处理。
AWS Lambda,用于代码部署和服务管理。
1. 提供解耦你的应用程序的工具。
2. 在前面图片系统的例子中,Lambda可以响应S3的事件,就像S3中某文件被增加时Lambda相关函数会被自动触发去处理一些逻辑。
3. 已经在EC2上集成,供应用扩展。
百万级别用户
当用户数量达到百万级别时,这就要求前面提到的所有方案都要综合考虑。
1. 扩展多为可用区域。
2. 在所有层之间使用弹性负载均衡,不仅在web层使用,而且还要在应用层、数据层以及应用包含的其他所有层都必须使用弹性负载均衡。
3. 自动伸缩能力。
4. 面向服务的架构体系。
5. 巧妙使用S3和CloudFront部署一部分内容。
6. 在数据库前面引入缓存。
7. 将涉及状态的对象移除出Web层。
使用Amazon SES发送邮件。
使用CloudWatch监控。

 

千万级别用户
当我们的系统变得越来越大,我们会在数据层遇到一些问题,你可能会遇到竞争写主库的数据库问题,这也就意味着你最多只能发送这么多写流量到一台服务器上。
你如何解决此问题?
1. Federation,根据你的应用功能把数据库分成多个库。
2. Sharding,分表分片,使用多个服务器分片。
3. 把部分数据迁移到其他类型的数据库上,例如NoSQL、graph等。
Federation——根据应用功能切分成多个库
1. 例如,创建一个论坛数据库、一个用户数据库、一个产品数据库,你可能之前就是一个数据库包含这所有类型的数据,所以现在要将他们拆分开。
2. 按照功能分离出来的数据库可以各自独立进行扩展。
3. 缺点:不能做跨数据库查询。
Sharding——将数据分割到多主机上
1. 应用层变得更加复杂,扩展能力更强。
2. 例如,对于用户数据库,三分之一的用户被发送到一个分片上,三分之一发到另一个分片上,最后三分之一发到第三个分片。
将数据迁移到其他类型的数据库上
1. 考虑NoSQL数据库。
2. 如果你的数据不要求复杂的join操作,比如说排行榜,日志数据,临时数据,热表,元数据/查找表等等,满足这些情况可以考虑迁移到NoSQL数据库上。
3. 这意味着他们可以各自单独扩展。
11000000用户
扩展是一个迭代的过程,当你的系统变得越来越大,你总有更多的事情需要你解决。
调整你的应用架构。
更多的SOA特性和功能。
从多可用区域到多区域。
自定义解决方案去解决你的特定问题,当用户量到达十亿级别时自定义解决方案是必要的。
深入分析你的整个应用栈。
回顾
使用多可用区域的基础设施提升可靠性。
使用自带扩展能力的服务,比如ELB,S3,SQS,SNS,DynamoDB等等。
每一层级都建立冗余,可扩展性和冗余性不是两个分开单独的概念,经常需要同时考虑两者。
刚开始使用传统关系型数据库。
在你的基础设施的里面和外面都考虑缓冲数据。
在你的基础设施中使用自动化工具。
确保你的应用有良好的指标采样、系统监控、日志记录,确保收集你的用户访问你的应用过程中产生的问题。
将各个层分拆成独立的SOA服务,让这些服务能保持最大的独立性,可以各自进行扩展,及时发生故障也不波及其他。
一旦做了足够的准备及可使用自动扩展功能。
不重复发明轮子,尽量使用托管服务而不是自己构建,除非非要不可。
必要的情况下转向NoSQL数据库。

参考资料
On HackerNews / On Reddit

http://aws.amazon.com/documentation

http://aws.amazon.com/architecture

http://aws.amazon.com/start-ups

http://aws.amazon.com/free

From:http://www.jfh.com/jfperiodical/article/1242

 

数据挖掘

基本概念

相关话题:大数据 数据分析 

白话区块链技术栈与应用

内容概要
现如今说起比特币,相信不少朋友已是耳熟能详了,尤其是这两年随着其价格飙升,甚至超过了黄金 ,超过了房地产,各大财经媒体乃至央视都有所关注报道;

在很多朋友心目中,比特币似乎就是一个类似于游戏币、邮币卡这样的炒作标的物,除了惊叹于它的价格上升速度外,对其了解还是寥寥。

然而,这一切的背后,到底是什么在支撑,现如今除了比特币,还有很多其他的类似系统, 比如莱特币、以太坊、 比特股等等,不胜其多,但凡介绍这些内容的软文, 大体都会提到一个名词:区块链 

一切似乎都是由区块链引起的,那么,就让我们剖开迷雾,揭开神秘的面纱,来看看这里头到底是个什么,它有什么特点,能有什么用处。
白话区块链技术栈与应用

导读:本章内容主要介绍区块链本身的含义以及代表性的技术组成,并由此介绍比特币是怎么通过这样的技术产生的。

1. 什么是区块链

1.1  一个有趣的数据记录格式

区块链,拆开来就是“区块+链”,实际上是一种数据的记录格式,软件在处理数据的时候,总是需要按照某种格式来读写,比如我们通常使用的关系型数据库,数据是按照一条一条的记录保存,或者再通俗的说,就像会计记账,将每一笔发生的业务都记在账本中,每一笔记录的账务称之为是凭证,一个月下来,将记录的一堆凭证数据汇总成 一个账簿,每过一个月就月结一下。区块链的格式,跟会计的这种记账方法很类似,所谓区块也就是一大坨数据的意思,我们可以将会计每个月所有记录的记账凭证看成是一个个的区块,区块之间通过年 月串联起来,这样看起来就像是一条数据链一样,区块链其实就是这么简单的一个格式,我们看个示意图:

如图所示,就是区块链格式的样子了 ,在比特币中,不是每个月存储一个区块, 而是大约每10分钟一个区块(注意只是大约,不是精确的10分钟),区块中存储的数据是最近的10分钟内发 生的交易 事务(最近的10分钟这个说法其实并不严谨,现在可以就这么理 解,在下面另有解释),可以理解为就是流水账。

大家看到这样的格式后,不知道是否有些似曾相识的联想,其实这样的数据格式,在生活中是有很多相似的;

比如工厂仓库的出入库记录,这个跟会计账本是类似的,还有家谱或者族谱,每一代人之间的关系是一个区块,到了下一代 又是一个区块,区块之间是父辈与子 女的关系连接,等等;而如果是计算机专业的朋友,一眼看上去,这不就是个线性表吗?是的,这就是比特币软件的主要数据存储格式,也是其他所有基于区块链技术的系统存取数据的格式。

这是一个很有趣的数据格式,它将连续不断的发生的数据分成了一个 一个的数据块,这样每个区块就都有自己的数字编号,也可以有自己的身份证号(通过哈希算法计算得到),在下载同步这些数据的时候,可以并行的从各个节点来获得,无论数据先后,到达本地后再根据区块号或者身份证号来组装起来就行 。

另外,这种格式是一种链条的格式,链条最大的特点就是一环扣一环,很难从中间去破坏, 比如有人篡改了中间的5号区块,那么如果要让数据看起来是完整的,就得同步把5号区块后续的所有区块都要更改掉,这个难度就大了,这也是区块链数据格式不可篡改的其中一个原因(当然了,如果仅仅只是本机的数据,也没什么不可篡改的,区块链系统真正的防篡改能力是通过无数个区块链系统运行的节点网络以及共识算法来实现的,这个在下面再介绍)。

这种格式还要个妙处,如果这个数据总是由一个人来记录的,那自然也没什么,但是如果放到网络中, 大家共同来记录这个数据,那就有点意思了,每个区块数据由谁来记录或者说打包,是可以设置一个游戏规则的,比如说掷骰 子,大家约定谁能连续3次掷出6,那就让他来记这个数据,为了补偿 一下他的劳动投入,奖励给他一些收益, 比特币正是使用了这样的原理来不断的发行新的比特币出来,奖励给打包的那个人的比特币就是新发行的比特币。

说到这里,大家觉得有点意思了吧?

1.2  一组技术的代表称呼

刚刚我们说了,区块链是一种数据的记录格式,可如果仅仅如此的话,实在不算是什么大不了的创新,事实上,在技术上区块链是一组技术的代名词,我们通常都说使用了区块链技术就是这个意思,那么既然是一组技术,那是由哪些技术组合起来的呢?我们来看一组关键词:

  • 公开密钥算法
  • 网络共识算法(挖矿)
  • 梅克尔数据证明
  • 可编程脚本合约
  • 区块链账本

1.公开密钥算法

属于计算机密码学⾥面传统的技术,公开密钥算法是⼀种不对称的加密算法,拥有两个密钥,可以互相加解密,通常其中的一个密钥是公开的称之为公钥,另外一个密钥是保密的称之为私钥;

2.哈希算法

也是属于计算机密码学中传统的技术,应⽤就更广泛了,主要⽤来对⼀段数据进行计算,得出⼀个摘要信息,通俗点说就是给一段数据⽣成⼀个身份证号;不同的消息生成的摘要数据是不⼀样的(某些抗碰撞能力弱的哈希算法可能在这⽅面会有些问题,但是使⽤广泛的⼀些知名的哈希算法,发⽣碰撞的概率很低),相当于给⼀段数据⽣成了一个身份证号这么个意思,在区块链系统中,哈希算法的使⽤很多,⽐如区块与区块之间,就是通过区块头的哈希关联起来的,⽽区块中的每⼀笔交易事务也都会⽣成⼀个哈希值作为交易易数据的ID,通过这些身份证号可以⽅便的检索或者关联区块,也能⽅便的指定某⼀笔交易事务。

哈希算法还可以用来生成梅克尔树,在下面我们再详细介绍,我们说了,哈希算法的特点是,只要目标数据有哪怕⼀点点的改动,生成的哈希值就会完全不不一样,因此可以⽤用来验证数据是否被改动过。

3.⽹络共识算法

在很久前就有计算机科学家研究过,并且提出过一些模型,⽐如拜占庭容错算法之类,比特币、以太坊这些使用的是⼀种工作量证明算法,其它的一些区块链系统有使用其他各种衍⽣的算法,⽽算法的原理都很简单,就是约定⼀个规则,通过共同执行这个规则,让每个分布式的节点数据都保持最终一致;

4.梅克尔数据证明

这是利用哈希算法将⼀组数据创建为⼀棵哈希树结构,⽤于验证数据完整性的一种结构,同时也应⽤在了轻量级钱包中。不同的区块链系统对梅克尔树的应⽤不尽相同,比特币中是⼆叉梅克尔树,比较简单,通过交易事务的哈希值两两配合生成一棵树,以太坊这种就复杂的多了,称之为梅克尔.帕特⾥夏树,这里暂时不赘述。

5.可编程脚本合约

什么叫合约?就是⼀组约定的规则,⽐如银行的结算系统,⼩明转账100给小王,在这么⼀个过程中,银⾏系统就会根据⼀组规则自动执行,规则包含⽐如检测⼩明的密码是否正确,余额是否⾜够,⼩王的账号是否正确,检测通过则分别更改两者的账户⾦额并写⼊事务⽇志。是的,这就是合约的意思了,当然,如果范围再⼴泛些,各种商业合约也都是这么个意思,因此可编程脚本合约也没什么好稀奇的,然⽽,如果将这种编程合约放到区块链的环境中,就⽐较有趣了,看两个特点:

第⼀个,区块链系统是⽆中⼼的分布式⽹络,没有边界

第⼆个,区块链系统通过⼀系列的技术实现了可信任⽹络

加起来,就是⽆边界的可信任⽹络,在这样的⼀个⽹络中执⾏既定的合约,成本低⽽而且安全,⽐特币在本质上也是属于这么⼀种脚本合约,只不过在⽐特币软件中,合约中处理的事情是⽐特币的转账,如果扩展这个概念,众筹、担保、分润等各种合约种类都能应⽤在这上⾯,⽤户也可以⾃行编写合约规则,以太坊便是这⽅面的⼀个典型代表,并由此带出了智能合约的应⽤。

这些技术的具体解释,我们在下⾯⼀一详述。

其中的【区块链账本】我们已经介绍过了,不再赘述,那么其他的技术都具体是什么意思呢,它们是怎么与区块链账本结合起来的?我们来一一说明一下:

1.3 创世应用“比特币”

说了这么多,我们知道,区块链技术反正就是一套软件开发技术,跟我们平时的网站开发技术、游戏开发技术、手机APP开发技术类似,只不过,与其他的开发技术不同的是,它能开发出一款软件,这种软件能制造“货币”出来,这就让人觉得有些不可思议了,比特币正是区块链技术的第一个应用软件,因此我们称它为“创世应用”。

正是比特币把区块链的技术理念带到了我们的视野中,虽然⽐特币的创始人中本聪⼀直都是⼀个谜,没有搞得清楚他到底是⼀个⼈人还是⼀个组织,但这些都不重要,重要的是⽐特币系统以⼀种极其天才的创新设计,解决了人们⼀直以来都难以解决的问题,那就是异步⽹络环境中实现数据的可信任共识的⽅案。我们抛开⽐特币这个货币的概念,纯粹站在软件或者⽹络的⻆度来看⼀下,假设我们是当初的中本聪,模拟⼀下当时的想法,⾸先,希望实现⼀套系统,可以联⽹,并且通过网络传递数据,如果是使⽤中心服务器这个结构的话,那显然是不够安全的,只要服务器上的数据损坏或者被攻击,系统等于就被瘫痪了,因此,决定采⽤分布式的结构,可是分布式结构有几个问题;

第一个,这些分布式的系统节点运⾏在哪呢,谁愿意提供计算机设施来运⾏行,靠⾃己来部署,那个成本就没底了;

第⼆个,分布式的节点,那么数据的⼀致性就是个问题,没有了服务器,数据来源也就没有权威的保证了;

第三个,怎么来验证⽹络中的数据呢?

对于第⼀个问题,站在经济⻆度,如果系统提供⼀种激励措施,让运⾏节点的⼈有利可图应该就能解决了,因此设计这个系统,得要有⼀个奖励或者激励的规则,在⽐特币中,打包区块的矿⼯工能够获得⼀定数量量的⽐特币奖励,这就是激励措施了。

对于第⼆个,这个问题是个难点,比特币要运⾏在公⽹上,各种情况都有,数据可能被篡改,⽹络可能不稳定,就连节点什么时候运⾏也不在控制之中,如何来解决这些问题呢?得要有⼀个机制,这个机制必须要有公正性,既然网络是可能不可靠不稳定的,那这个机制中就不能有太多对其他节点的依赖,得是⼀个主要依靠本机就能实⾏的⼀个做法。

换成是我,还真的很难想到⼀个好方法,传统的⼀些技术都有些问题,如果是在⼀个节点明确,网络也较为良好的场合,还好处理理⼀些,可是⽐特币的情况要⽐这个复杂的多。著名的CAP原理,阐述了这么⼀个结论:分布式计算系统不可能同时确保⼀致性、可⽤性和分区容忍性。看下这三个术语分别是是什么意思吧:

【⼀致性】:这⾥是指强⼀致性,发⽣在后⾯的事件能看到前⾯事件发⽣导致的结果

【可⽤性】:在有限时间内,任何⾮失败节点都能应答请求

【分区容忍性】:也就是说⽹络有可能发⽣分区,也就是说节点之间的通信不可保障不能同时确保,那就只能靠弱化某⼀个或者某两个特性,⽽而增强其中⼀个特性了。

中本聪在实现的时候,设计了⼀个工作量证明,很有意思,设置⼀个难度值,大家都通过⼀个类似于掷骰⼦的算法来命中⼀个结果,若结果符合预期的要求,就成功,成功者可以获得数据的记账权也就是区块数据打包,打包完毕后⼴广播给其他⼈,其他⼈验证后写⼊⾃己的数据中。

在这个过程中,由于使⽤的算法是⼀个类似于暴力破解的算法,除了靠提⾼计算机算力没有更高的办法去讨巧(这就⼀定程度上实现了⼀定程度的公正,当然了,⼟豪有能⼒购买更高性能的计算机设施,从⽽比普通⽤户更加具有抢得打包权的能力,这也是⼀个问题,不过⼀种技术总是只能解决⼀定范围的技术问题),但是大家需要注意的是,能够算出⼀个命中的值的,可并不⼀定只有⼀个⼈,如果出现了多个呢?那大家就只能进⾏区块的⼴播竞争了,谁被其他的节点接收的多,谁就被最终认可,⽽其他同样挖矿成功的就会被丢弃,从⽽得不到奖励。

因此,比特币中的这种数据⼀致性的算法是最终⼀致性而不是实时的⼀致性,这个大家⼀定要注意了。

对于第三个问题,怎么验证⽹络中的数据,在⽐特币⽹络中,每个节点都是独⽴的验证数据的,在验证过程不需要⽹络中其他节点提供依赖的服务。

2. 区块链技术栈

 

2.1 记录格式—区块.链

见【1.1  一个有趣的数据记录格式

2.2  网络结构-P2P

现如今,⼤概很少软件是单机版的了,就连输⼊法⽐如搜狗输⼊法、讯飞输⼊法也都是要通过联⽹来更新词库以及提供其他⼀些智能功能的,那么,既然是联⽹的软件,就避不开⼀个问题,那就是⽹络结构,就好⽐我们要造房⼦,总得设计下房屋的结构吧,砖瓦结构呢还是框架结构,单独的平⽅呢还是连⽚的⼩区。

迄今为⽌,⽆论什么样的⽹络结构,总体来区分⼀下的话,就是两种:客户端-服务器结构、P2P结构。

P2P也就是peer to peer的意思,中⽂点对点,也就是对等的意思。

区块链中的特点之⼀就是分布式,每个节点都维持完整的账本数据,可以独⽴的进⾏数据验证,独立的发送数据接收数据,彼此之间通过共识来实现数据的不可篡改和⼀致性,⽽每个节点都独⽴的按照规则做着⾃己的事情。任何⼀个节点的损坏或者图退出都不⾜以影响整个⽹络的正常使⽤,尤其当节点数量很多的事情,这也就避免了单点故障。

由于不存在⼀个服务器,也因此对等⽹络结构中的节点,是需要有⼀个认识彼此的机制的,这就是⽹络路由功能,简单来说,就是每个节点都会负责为其他节点提供地址信息,同时也会去索取和更新有效的节点地址。

就个⼈理解来说,对等⽹络结构最核⼼的就是⽹络共识机制,每个节点既当客户端也当服务器器,通过共识机制来协同。

2.3 同步机制-共识算法

区块链系统是对等⽹络结构,每个运⾏的节点都各⾃保存⾃⼰的数据副本,那么问题就来了,怎么来保证彼此之间的数据统⼀呢,既然没有⼀个中⼼服务器,⾃然也就没有⼀个传统意义上的权威数据来源了,⽽且对等⽹络中的每个节点都是平等的,那要是彼此的数据不⼀致,以谁的为准呢?这就要使⽤到⼀个同步机制,也就是共识算法。

共识算法的主要⽬的就是通过⼀种机制,使得⽹络中产⽣的数据让⼤家都能认可也就是所谓的共识,⽽对于那些⾮法的⽆效的数据会被丢弃掉,可以说,共识算法是确保区块链⽹络数据同步以及数据安全的重要环节。每⼀种不同的区块链系统都会有⾃⼰的⼀套共识算法,⽐如PoW(proof of work,⼯作量量证明)、PoS(proof of stake,权益证明)、DPoS(Delegated proof of stake,股份授权证明)、PBFT(Practical Byzantine Fault Tolerance,拜占庭容错算法)等等,很多,每种不同的算法也各有特点和优劣。

再具体说明之前,有朋友可能会有疑问,就算是对等⽹络,没有⼀个服务器来权威的提供数据来源,但只要节点之间彼此都连接,随时保持⼀致不就⾏了,如果是在⼀个⽹络良好的局域⽹中,并且运⾏的节点是受到严格的管理的,那⼤概也就没什么问题了,可事实上是,类似⽐特币这样的区块链系统是运⾏在互联⽹上的,⽽且谁也不能保证⽹络是个什么状况,甚⾄就连运⾏的节点什么时候启动什么时候会关闭掉都不知道,⽐如我们使⽤微信聊天,假设没有⼀个微信服务器存在,当⼩明发消息给⼩王时,⼩王正好没开微信,或者⼩王正好在地下停⻋场,没⽹络,那怎么办?种种情况,都不能保证节点之间能够随时连接在⼀起,因此区块链中的共识算法,要解决的是这样⼀个情况异常复杂的⽹络环境中的数据同步问题。

为了让⼤家⽐较能够形象的理解,我们还是以⽐特币为例,⽐特币中使⽤的是⼀种⼯作量量证明算法,其原理很简单,如下:

我们还是以⽐特币为例来说明,⽐特币中的⽹络共识算法的过程原理相对简单,理解了这部分,再去理解其他的共识算法就会⽐较有基础。

在⽐特币中,使⽤的共识算法是⼀种⼯作量量证明算法,说通俗点,⼤家通过⼀种竞争算法来抢夺区块数据的打包权,谁抢到了谁就能将发⽣的交易易数据打包成区块,并且⼴播出去,其他节点验证后没有问题就保存到⾃⼰的区块链账本中,这种竞争算法的原理很简单,系统会计算出⼀个难度⽬标值,然后⼤家通过对区块头进⾏⼀个加入了随机数的哈希计算,直到算出的值⼩于难度⽬标值,那就算是成功拿到记账权了,就跟掷骰子差不多意思,谁掷出了⼀组符合条件的数字谁就赢了。

有朋友可能问,那要是不⽌⼀个⼈算出了那么⼀个数字呢,以谁的为准呢?呵呵,这个时候,就要靠运⽓了,假如A和B都得到了符合条件的⽬标数据,都打包,都⼴播了,这个时候就看谁⼴播的范围最⼤,影响最⻓远了,最后⽐特币⽹络会保留⼴播范围最⼤的那个。

⼤家看到在这个⼩节的标题上放了个“挖矿”的字样,是不是共识算法都称之为是挖矿算法呢?答案是否定的。在这⾥之所以放⼀个“挖矿”的字样,是因为在不少的公链系统中,⽐如⽐特币、莱特币、以太坊等,都是通过这样的⼀个共识算法来发行新币的,怎么发⾏呢,就是奖励⼀定数量量的币给成功挖到区块的矿⼯。

2.4 完整证明-梅克尔树

梅克尔树是一种数据结构,跟区块链账本数据格式一样,是用于维护 一类数据的,区块链的账本格式是一条链,梅克尔树,顾名思义是 一种树结构,梅克尔树的目的是为了实现完整性证明,在不同的区块链系统中,对梅克尔树的使 用不尽相同,比特币中使用的称之为二叉梅克尔树,而比如以太坊系统中使用的则是梅克尔-帕特里夏树,相对来说, 二叉梅克尔树要简单许多,咱们就从简单的开始介绍吧,还是以比特币中的为例 。

既然是树结构,那就有一个个的树节点,那么比特币中的树节点中都是哪些数据呢?实际上,在比特币中,每个区块中都包含有一颗梅 克尔树,我们来看看,这棵树是怎么种出来的。

在每个区块中都包含有很多交易事务,每条事务都有一个身份证号,这是通过哈希算法计算而来的,可以唯一的表示某条事务记录,假如说某个区块中有6条事务记录,那我们就拿出6条事务记录的身份证号也就是哈希值,进行两两配对,然后分别再计算出两两配对的事务哈希值,依次往上,直到最后计算出一个根哈希,我们来看个图示:

 

 

在⽐特币中,每个区块都能⽣成⼀颗梅克尔树,是通过什么来⽣成的呢?是通过交易事务,在⼀个区块中,每条交易事务都会被计算⼀个哈希值,假设某个区块有4条事务,则如图所示,Hash1到Hash4就是这4条事务的哈希值,接下来再次对事务的哈希值两两哈希,直到最后⽣成⼀个根哈希,如此,⼀棵梅克尔树就⽣成了。那么,这样的⼀棵树⽣成后有什么⽤呢?

⾸先,⽐特币的节点在进⾏数据同步的时候,会向多个节点下载数据,这个时候,就会有个问题,怎么来验证获得的数据是完整的还是不完整的呢,是有问题还是没问题的呢?在点对点⽹络中进⾏数据传输的时候,显然并不只是从⼀台服务器上下载数据,⽽且其中的⼀些机器还可能是不稳定的,甚⾄是不可信的,这个时候,通过上述的⼀个⼤文件⼀个哈希值的⽅式就不太能起作⽤了。

然后通过梅克尔树,假设图中的2号事务数据下载有问题,则计算出的Hash12必然是与其他节点不⼀致的,很快就能定位到问题块,除了能够快速定位到数据块外,还有⼀个作⽤,就是对SPV(Simplified Payment Verification, 简单⽀付验证)的支持,我们知道,⽐特币核⼼钱包是要搭配完整的区块链数据使⽤的,包含了所有发⽣的交易事务,也因此,可以对接收或者发起的交易事务进⾏完整的验证,⽐如是否包含⾜够的余额,是否双花等,但是这种却也有个很⼤的问题,它必须要带上⼀个数据量很⼤的账本副本,这就限制了⽐特币钱包的使⽤,有时候我们只是想验证⼀下⽀付是否发⽣过就⾏了,完整的交易可以交给核心节点,那怎么办呢?可以通过如下的过程来实现:

1.  ⾸先下载完整的区块头数据,注意是区块头不是所有的区块链数据,区块头中包含有区块的梅克尔根

2.  如果是想要验证某笔⽀付交易,则计算出这笔交易事务的哈希值txHash

3.  找到txHash所在的区块,验证⼀下所在区块的区块头是否包含在区块链账本中

4.  获得所在区块中计算梅克尔根所需要的哈希值,注意我们并不需要所有的事务哈希值,如图所示,如果是要校验Hash1的话,我们只需要再搜集Hash2、Hash34即可

5.  计算出梅克尔根

6.  若计算结果与所在区块的梅克尔根相等,则⽀付交易是存在的。

7.  根据该block header所处的位置,还可以确定该交易得到了多少个确认

从中我们可以看到,梅克尔树是相当重要的。⼤家可以设想⼀下,这种结构还能应⽤在哪些场景下。

2.5 账户管理 -公开密钥算法

我们在使用通常的网络服务时,都会注册一个用户名,无论是使用淘宝、京东、微信等,还是玩网络游戏之类,都会去注册一个用户名,那么区块链系统中是怎么来注册用户名的呢?实际上在区块链系统中 一般是没有用户名这个概念的,而只有一个账户地址的概念, 无论是使用比特币还是以太坊还是其他的,基本都是通过一个地址来表示的,对于支持数字货币的区块链系统这个地址也称之为是钱包地址,那么这个地址是从何而来的呢?我们先来了解一下公开密钥算法:

这是⼀种加密算法,通常的加密算法,密钥只有⼀个,举个例子,我们希望对⼀串串数字进⾏行加密,约定将每⼀个数字都加上2,⽐如1,2,3,4,5就变成了3,4,5,6,7,如果有谁知道了这种加密⽅法,那同时也就知道了解密算法,这种⼀般称之为叫对称密码算法;

如果希望加密的⽅法与解密的⽅法是可以独⽴的且⽆无法互相直接推倒出来,那么,这种算法就是不对称加密算法,也就是所说的公开密钥算法,为什么叫公开密钥呢,因为这种拥有两种密钥,⼀个是保密的称之为私钥,⼀个是可以公开的,称之为公钥,使⽤用私钥加密的数据可以通过公钥解密,反过来使⽤公钥加密的数据可以通过私钥解密,⽬目前这种算法应⽤比较多的有RSA算法ECC椭圆曲线算法,前者是利用了⼤素数分解难度的原理理,后者是利用了椭圆曲线离散对数的计算难度,具体细节基于篇幅这⾥不再展开,区块链系统中,通常椭圆曲线算法应⽤的最多。

以⽐特币为例,⽤户可以在⾃己的钱包中创建地址,这个地址类似于银⾏账号,我们可以将⽐特币从⼀个地址发往另外⼀个地址,那么,这个地址从何⽽来的呢,实际上,从本质上来讲,并没有⽐特币地址这么⼀个东⻄存在,为什么这么说?⽤户在创建钱包地址时,实际上是创建了⼀对公钥和私钥,⽽所谓的地址只是公钥的⼀种格式化表示。 ⽤户通过私钥签名证明⾃己拥有某笔⽐特币,⽽通过公开的公钥可以验证⾃己的身份,只要⾃己通过私钥签名⼀笔交易或者签名⼀笔消息,任何⼈人都可以通过公开的公钥来确认是否是合法的用户。也就是说,公开密钥算法不但⽤来识别某个地址用户,也是⽤来完成交易事务的,不但是⽐特币,其他的区块链系统也是同样的原理。

2.6 智能合约-可编程状态逻辑

这是区块链系统⾮常重要的特点,我们知道,区块链系统可以创建⼀个可信任的⽹络,在这样⼀个可信任的网络中可以放心的通过⼀组代码编写的既定规则,转移数据的所有权,变更数据的状态。⽐特币⽹络中可以转移⽐特币,以太坊⽹络中可以转移以太坊还可以通过其他的智能合约实现按规则的状态变更。

这些到底是什么意思呢?

通常,在⼀个传统系统中,⽐如银⾏行的账户系统,是怎么来表明⼀笔钱是谁的呢?是通过账户和密码,⽐如⼩明转了了100元给⼩王,这100的⾦金金额数值就会写⼊到⼩王的账户,然后扣除掉⼩明账户⾥100,⼩王的账户只有通过⼩王⾃己的密码才能验证通过使⽤,这个逻辑看起来很正常,⼀直以来我们都是来的。然⽽而,区块链系统中却不是这么来实现的。

让我们来站在⼀个⽐较⾼的⻆角度来看待⼀下,以银⾏账户为例,⽆论是转账,存钱还是扣除费⽤等,不管是什么样的业务,对于账户来说,站在数据的层⾯,无⾮就是数据状态的不断变更,⽽每⼀次的变更都是通过⼀系列的规则验证的,这么⼀来,我们可以将这个账户看成是⼀个状态机,如下:

 

这个图很好理解,那么我们可以看到,最主要的不是状态本身,⽽是状态变更的触发条件,在这个图中,每个状态之间的变更都是有条件的,区块链系统中通常会怎么来实现这么⼀个条件的触发呢?我们以转账来说明:

1. 发送⽅发起⼀个转账交易,类似于开了⼀张⽀票,然后签上⾃⼰的名字(私钥签名)

2. 在⽀票上写上对⽅的账户地址(对⽅的钱包地址,我们知道钱包地址就是通过公钥转换⽽来的)

3. 向⽹络中发送这笔交易,每个节点都可以来验证这条交易是否有效(⽐如发送⽅的余额是否⾜足够,私钥签名是否合法等)

4. 节点如果验证没问题就能通过,这条交易事务最终会被矿⼯打包到区块(相当于正式的记了个账)

5. 接收⽅可以通过⾃⼰的私钥来验证⾃⼰对这条转账交易的拥有权(这句话⼀定要理解⼀下),通过⾃⼰的私钥和⽀票上的公钥转成的地址匹配,若能成功,就表明⾃⼰拥有这条交易事务转账的所有权,那么⾃⼰就能花这笔钱了。

这样的⼀个过程是通过什么来实现的呢,是通过⼀组脚本程序,在⽐特币中是⼀对锁定与解锁脚本,在以太坊中是更为复杂的编程脚本,总之,就是通过这样的程序逻辑实现了状态变更的触发条件,只要脚本程序写好,达到触发条件,程序就会严格的执⾏,刚正不阿,不留留半点情⾯面^_^。

那么,我们可以发现,这个程序,实际上相当于就是⼀份合约,大家约定了⼀个规则,符合规则了就照章办事,⽽具体是什么样的规则,这个是可以事先编写的(⽐特币中功能⽐较受限,⼀般也就能实现转账交易,以太坊则可以⾃定义编写各种合约规则),将这样的⼀份合约放在这样的⼀个去中⼼,分布式的环境中,由⽹络共识来保证不可篡改,这是多么创新的⼀个思路啊,这种可编程合约的思想可以⼴泛的应⽤于各种商业环境之下包括金融领域。

3. 应用特点

 

3.1 分布式网络

P2P⽹络本身就是⼀个分布式⽹络,区块链⽹络中并没有⼀个真正意义上的服务器,内部的运⾏逻辑也并不假设有服务器的存在。在区块链之前,也有过不少的分布式⽹络系统,⽐如⼤家很熟悉的电驴下载、BT下载,互联⽹初期的时候,⼤家都是到⽹站服务器去下载,下载的⼈多了,速度就会慢,因为占流量了或者说服务器更繁忙了,然而BT下载这种,确实下载的⼈越多,速度越快,我们不来详细的解析BT下载的具体技术细节,就光从⽹络结构上来讲,分布式的⽹络结构,使每个节点都既是使⽤者也是服务的提供者,也就形成了⼈多力量⼤的效果。

分布式⽹络中,首要的⼀个问题就是,如何保证数据的⼀致性,有些对数据的⼀致性要求不⾼⽐如⽹⻚资源,⽂件服务,早点晚点影响也不⼤;有些则希望在⼀个能承受的时间范围内达成⼀致,⽐特币就是这种,通常会建议发送⼀笔交易事务后,等待⾄少6个区块,原因就是6个区块后,数据基本上被⼤部分节点收纳的概率就很⼤了,还有⼀些对⼀致性的要求很即时,⽐如银⾏结算,不可能说要等段时间,账本才能⼀致,那对银⾏来说不能接受。

针对不同的使⽤场景,分布式⽹络也会不同的扩展,⼤家要注意的是,分布式⽹络并不是说完全没有中心,而是说在整个⽹络结构上是分散的,分布式的,但是每个单元还是有可能会存在中⼼的,毕竟在某些效率要求⾼的场合,中⼼结构的效率是最⾼的,这两者之间并不是互相对立的,⽽是互补的。

3.2 数据不可篡改性

我们可以反过来看⼀下,什么情况下数据是可篡改的。

⽐如数据都管理在⼀个服务器上,那⾃然是可篡改的,再怎么设置身份认证之类,只要突破进去就是⼀马平川了;

再⽐如数据虽然不在⼀个服务器上,但是对数据的验证是⼀个人说了了算的,⽐如现在很多的⽹站服务,⽐如各种电商⽹站啊,甚⾄包括银行(当然,不是说这些系统就会被随意的修改,这⾥只是参照⼀个例子),数据的管理权在⼀个管理员⼿中,数据怎么改并不需要得到其他不受⾃⼰控制的系统验证; 数据的记录权限在⼀个管理员⼿中,跟第二点类似,⾃⼰说了算;

区块链系统怎么保证数据不可篡改性的,对于第⼀点,区块链系统是分布式的,因此不存在⼀个明显的服务器目标;第二点,区块数据需要被⽹络中其他节点验证,⼤家都认可才会被记录在账本中由此达成共识,除非控制了大部分的节点,否则是不现实的;

对于第三点,区块链系统中使⽤各种共识算法,记账权不会掌握在⼀家⼿中,⽐如⽐特币的挖矿算法。

这种特性对于⼀些公众数据的记录是很有意义的,⽐如公证类数据,⽐如众筹账务,慈善款项等。

3.3 规则强制执行性

  • 代码即法律
  • 智能合约的条件执行

3.4  无边界价值转移

区块链网络可以创造一个可信任网络,可信任就表示有信用,而信 用是一切金融传递的基础

区块链系统可以自带金融属性,通过比特币的例子我们也能看到,它可以通过网络在全球各地进行转账交易,通过这种原理,不但可以传递货币,也可以传递其他任何的数字资产。

传统的比如游戏币,游戏道具,某平台的积分等,一定程度上也可以转移价值,但都是很难做到无边界传递的,而且其本身的信用程度也并不高,区块链⽹络⽆无边界,并且可以维持⼀个可信任的网络,这就为资产或者说价值的传递构造了一个成本相当低廉且传播很广泛的⽹络基础设施。

3.5  自治网络系统

这个其实是一个未来的愿景展望,可编程社会的一个基础模型

4. 应用场景

 

4.1 数字代币

比特币、莱特币、以太坊以及基于以太坊的各种合约代币

4.2 众筹合约

属于智能合约的 一种

4.3 跨境 支付

无边界的价值转移能力以及智能合约的特点,很适合应用在金融的跨境支付领域,目前的跨境支付手续繁杂,等待时间也很长,效率不  高,可以考虑在各国银行之间建立一个基于区块链的支付系统。

R3联盟

swift应用超级正本的fabric建立支付网络

4.4身份证明

使用区块链来构建身份管理系统

4.5去中心交易

目前的案例,Bitshares以及Openledger

基于区块链的交易系统,通过预言机创建链上资产,通过代码规则运行公开透明的交易逻辑

5.主流技术平台

5.1比特币

历史上第一个区块链系统,第一个加密数字货币系统,其他的系统基本都是在比特币的基础上开发的

5.2以太坊

数字货币+智能合约,既是一个数字货币系统,也是一个智能合约的开发平台

5.3超级账本

包含一系列的项目

比较著名的就是fabric,是一个面向商业的区块链系统开发框架,其本身其实并不是一个运行的区块链系统而是一套开发框架,一套开发用的半成品基础设施,是由Linux基金会主导的项目。
from:https://mp.weixin.qq.com/s/kuNtNekdsBYxoTtP6xxQqw