第一章:从游戏币开始说起

在正式介绍区块链之前,我们先简单回顾一下在没有它的世界里,一切是怎样运行的。有人说区块链是伟大的创新,也有人说区块链会改变世界,这些说法我们都不太在意。硬币有正反两面,区块链技术也一样,有它的优点和缺点,我们只想搞明白它是如何工作的。为了达到这个目的,本书虚构了一家游戏公司。这家公司刚开始采用的也是传统技术,但是我们会一步一步,逐渐让它过渡到区块链技术。我们一起来了解这家公司吧。
虚构公司
这家游戏公司名字叫做Q公司,它发行了多款特别火爆的游戏,有休闲游戏,也有FPS(第一人称射击)游戏。但是不管哪款游戏,都有一个特点,那就是想让玩家付费。简单来说,玩家需要花钱购买该公司的虚拟Q币,然后再通过Q币在各种游戏里购买装备,提升游戏体验。
友情提示,这个Q游戏公司完全是虚构的,用字母Q只是因为该字母很可爱。请不要把它和现实世界中的某家游戏公司联系起来。如有雷同,纯属巧合。下面我们来看一下这家公司的技术架构是什么样的。
服务架构
和大部分游戏公司一样,Q公司采用的也是传统的C/S架构。这里C代表客户端(Client),S代表服务器(Server)。服务器主要是用来处理业务逻辑的,相关的数据则是存储在专门的数据库(Database,简称DB)里。为了简化讨论,我们姑且认为Q公司只有一台服务器,以及一个数据库,如下图所示:

从上图可以看出,所有的客户端都向同一台服务器发送请求。不难想象,这台服务器就是这些客户端的中心。我们把这样的架构叫做中心化架构。像这种中心化的架构是有很多好处的,例如好管理、好维护、好扩展。这里好扩展尤其重要,具体而言又分为两种扩展方式:横向扩展和纵向扩展。
我们知道,一台服务器的处理能力是有限的,比如说可以服务一万个用户。假如某一天我们想服务三万个用户,那么就需要对服务器和数据库进行扩展。我们可以去购买性能更强大的服务器和数据库,比如都是原来的三倍,然后换掉老的服务器和数据库,这样就可以顶住三倍的压力。这样的扩展方式就叫做纵向扩展,如下图所示:

纵向扩展也不是无限的,总有一天我们会把市面上性能最强的服务器给买回来,这时候就没法再扩展了。所以,我们还可以使用更多的服务器一起来处理用户请求,一堆廉价的机器堆起来形成一个集群也可以顶住更大的压力。这样的扩展方式就叫做横向扩展,如下图所示:

由于中心化C/S架构具有上面这种可扩展性,Q公司可以给玩家提供非常好的游戏服务,具体而言就是低延迟、高TPS(每秒可处理交易数量)。当然中心化架构肯定也是有它的缺点的,这个我们留到本章的结尾再说。为了便于讨论,我们需要先把Q公司处理的业务简化一下。
考虑到读者很可能不是程序员或相关技术人员,在我们进一步讨论前,先简单介绍一下数据库。你或许听说过“数据库”这个词,但未必清楚它的工作原理,其实完全不用纠结细节,也把它当成一个“黑盒子”就好了。不过如果你用过或了解Excel表格,那理解数据库也很容易。它本质上就是功能更强大的“Excel表格”,核心都是用结构化的方式存数据、管数据,只不过Excel通常由人直接手动编辑,而数据库主要靠服务器通过SQL语言来完成查询、修改、存储等操作,效率和稳定性也更高。数据库与Excel的相似之处,如下图所示:

专业的数据库软件通常需保证“事务”的ACID特性(即原子性、一致性、隔离性、持久性),这些特性不影响对本书核心内容的理解,因此我们不展开讨论,只需了解“事务”的定义及“原子性”这一关键属性即可,具体内容将在下一小节介绍。
简化业务
虽然我们虚构了一家游戏公司Q,但我们完全不关心它的游戏业务。我们只关心它的用户注册和登录业务,以及Q币的充值、提现和转账业务。这两类一共五个业务,见下面这张表:
| 类别 | 业务 | 说明 |
|---|---|---|
| 账户 | 注册 | 新用户注册 |
| 登录 | 用户登录 | |
| Q币 | 充值 | 用户充值,其Q币增加 |
| 提现 | 用户提现,其Q币减少 | |
| 转账 | 用户A给用户B转N个Q币 |
我们前面也说了,所有的数据都是存在数据库服务器里的。如果是大型业务,需要很多张表(Table)来存储数据。但是对于我们简化后的这五个业务,用一张数据库表就足够了。这张表需要存储用户名、密码、Q币余额,以及其它一些必要数据,如下图所示:

这张用户表应该挺好理解的,但是关于数据库也有三点需要说明。
第一,原子交易。我们可以将数据库中的多次操作打包成一个不可分割的集合,这个集合在数据库领域被称为“事务”(Transaction)。事务最核心的特性是原子性(Atomicity),简单来说,一笔事务包含的所有操作要么全部执行成功,要么全部执行失败并回滚,绝不会出现“部分成功、部分失败”的中间状态。事务的原子性由数据库自动保障,无需我们额外处理。在本书后续内容中,为了表述更通俗,我们通常会将“事务”直接称为“交易”。
你可以联想现实中的转账场景来理解原子性:比如从A账户扣钱、给B账户加钱,这两步必须同时成功或同时失败,绝不可能出现“扣了钱没加钱”的情况。就像张三给李四转Q币,这个过程其实包含两个关键操作:一,从张三的账户里扣减对应数量的Q币;二,给李四的账户里增加同等数量的Q币。要是这个转账交易没有原子性,就可能出现两种麻烦情况:要么张三扣了款但李四没收到,张三会不满;要么张三没扣款但李四多收到了Q币,Q公司会蒙受损失。这两种情况无论发生哪一种,都不符合正常的业务逻辑。
第二,精度有限。我们都知道,计算机可以精确表示整数,但是绝大部分小数它都没办法精确表示。举个极端的例子,圆周率
由于这个原因,所有的Q币余额在用户表里都是按整数存储的,计算时也是按整数计算,计算结果当然也都是整数。我们假设每枚Q币最小可以分成一百份,且张三在表中的Q币余额为5000,于是我们知道张三实际上的Q币余额是50.00。我们称Q币有两位小数精度,或者更简单点,我们说Q币的精度是2。
第三,数据泄漏。数据库中不能以明文方式存储密码,否则一旦数据库被黑客攻破所有人的密码都会泄漏。这一点我们在下一章会进一步讨论。
问题总结
前面我们讨论了游戏公司Q采用的C/S架构,这种传统的中心化架构有很多优点,特别是良好的可扩展性,使其可以同时服务大量的客户端。但是这种架构也是有很多缺点的,我随便举一些例子:
- Q币是游戏公司发行的,用户按一定的价格购买,然后在游戏内使用。如果某一天该公司突然增发了许多的Q币,并且以极低的价格卖给用户,会发生什么事情?可想而知,游戏内的装备也会迅速贬值。这就是Q币的通货膨胀,对大部分的游戏玩家来说是一场灾难。
- 用户的Q币是存在游戏公司的数据库里的,如果游戏公司随意修改用户的Q币余额会怎么办?如果你的Q币余额突然变多了你当然很开心,但是如果突然变少了,你可能只能寄希望于游戏公司的客服了,期待对方能帮你找回消失的Q币。
- 用户的账户数据是存在游戏公司的数据库里的,如果某一天游戏公司突然删除或者冻结了你的账号怎么办?你花真金白银辛苦升级的装备先不说,就连你剩余的那些Q币可能也取不出来了。
- 你很喜欢Q公司的某款游戏,也很想注册一个账户自己上去玩。但是由于某种原因,Q公司就是不让你注册,你该怎么办?你只能眼睁睁地看着别人玩游戏,自己却无法获得乐趣。
- 如果Q公司的服务器或者数据库突然被黑客攻破了怎么办?黑客把我的Q币转走还算好的,万一Q公司在数据库里用明文保存了我的密码,而我(就像很多人一样)不管啥网站都是用相同的密码,那就糟糕了。
- 如果由于某种原因,Q公司的服务器突然宕机怎么办?这个其实倒没啥问题,只是可能有段时间用户无法玩游戏了而已。利用这些时间去学习一下(例如读一下本书)也不错。
- 等等等等......
以上的问题大致可以分为两类:(1)游戏公司作恶,(2)系统出现故障。系统故障或者程序bug都是客观问题,是在所难免的,影响也不大。但如果是主观作恶,那用户的麻烦就大了。当然了,以上都是我的猜测,尤其是主观作恶。我们有理由相信现实世界中的游戏公司都是有责任感的,是不会轻易去干坏事的。
但是有一个人不相信这些公司,他就是中本聪(这是化名,没人知道他究竟是谁)。他不仅不相信,还设计了另外一套架构,来从根本上避免这些问题。他的解决方案当然也是有缺点的,要付出很多代价。但同时也是开创性的,值得我们去深入了解和学习。那么他的方案怎么解决上述这些问题的?又做了什么样的取舍?请读者继续阅读其余的章节,听我慢慢分解。
本章小结
本章介绍了虚构的游戏公司Q,它发行的虚拟游戏Q币,它的服务架构,以及简化后的业务逻辑,我们还讨论了中心化C/S架构的优点和缺点。得益于该架构的种种优点,尤其是其可扩展性,Q公司可以同时为大量的游戏玩家提供服务。但是这个架构也存在很多缺点,有可能会使玩家蒙受损失。
鱼和熊掌不可兼得。游戏玩家享受了极致的服务,同时也要承担一定的潜在风险。还好本书虚构的这家Q公司愿意让用户来做出选择,它打算把服务分为两类。第一类服务维持现状,留给那些追求极致游戏体验的用户。另外一类服务会进行一些取舍,通过适当降低游戏体验来提高账户的安全性。
但一口吃不成胖子。Q公司打算先把原先的中心化架构复制一份,然后逐步对它进行修改,每次只前进一小步。接下来的几章将详细介绍Q公司是如何一步一步改造这艘“忒修斯之船”的。