Fabric-Order-启动流程

流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
graph TB
Enter(入口 - `peer/main.go` **) --> Init(加载环境变量)
Init --> NodeCMD(Init Node子命令)
NodeCMD --> PreRun(PreRun `common.InitCmd` *)
PreRun --> RunCheck(检查MSP类型)
RunCheck --> aclProvider(生成ACL控制器)
aclProvider --> platforms(平台环境-Node,Java,Go控制器)
platforms --> DeployedCCInfoPrivider(部署链码控制器)
DeployedCCInfoPrivider --> identityDeserializerFabtory(获取身份检查工厂)
identityDeserializerFabtory --> metricsProvider(指标控制器)
metricsProvider --> ledgermgmt(初始化账本)
ledgermgmt --> serverConfig(加载服务端配置)
serverConfig --> NewPeerServer(生成节点通信服务)
NewPeerServer --> NewDeliverEventsServer(生成区块分发和块事件处理服务)
NewDeliverEventsServer --> startChaincodeServer(启动容器链码服务)
startChaincodeServer --> startAdminServer(启动管理服务)
startAdminServer --> NewEndorserServer(生成背书服务)
NewEndorserServer --> initGossipService(初始化流言服务)
initGossipService --> DeploySysCCs(部署系统链码)
DeploySysCCs --> NewLifeCycle(生成链码生命周期管理)
NewLifeCycle --> peer.Initialize(节点初始化)
peer.Initialize --> registerDiscoveryService(注册节点发现服务)
registerDiscoveryService --> RegisterEndorserServer(注册背书服务)
RegisterEndorserServer --> peerServer.Start(节点启动)

节点启动流程

启动流程

  • Fabric使用cobra的命令行工具库,viper作为参数配置库。
    • 入口peer/main.go
      • 设置加载的环境变量前置。
      • 初始化子命令,节点启动命令位于子命令node.Cmd()
    • 节点命令peer/node/node.go
      • 节点启动之前执行common.InitCmd
      • 节点启动命令peer/node/start.go:serve()
        • 检查MSP类型mgmt.GetLocalMSP().GetType()
        • Idemix零知识证明的MSP类型目前是不支持,因此非标准类型MSP直接退出。
      • 生成aclProvideraclmgmt.NewACLProvider
      • Peer操作服务newOperationsSystem,提供版本,健康检查,测试接口访问。
      • platforms相关Registry
      • lsscc.DeployedCCInfoPrivider{}
      • identityDeserializerFabtory
      • OperationsSystem.Start()
      • metricsProvider
      • membershipInfoProvider
      • 初始化ledgermgmt位于core/ledger/ledermgmt/ledger_mgmt.go:initialize()
        • 完成账本操作相关的初始化工作。
      • chaincodeDevMode
        • 链码开发模式重写配置。
      • peer.CacheConfiguration() 配置信息缓存。
      • serverConfig 加载服务端配置
      • NewPeerServer 生成用户节点通信服务。
      • NewDeliverEventsServer 生成传输区块和块事件服务
      • startChaincodeServer 启动链码服务
        • setup local chaincode install path
        • create chaincode specific tls CA
        • start the chaincode specific gRPC listening service
      • startAdminServer 启动admin操作服务默认公用peer节点端口
      • NewEndorserServer 生成背书服务
      • initGossipService 初始化流言服务
      • sccp.DeploySysCCs("", ccp) 部署系统链码
      • NewLifeCycle 初始化生命周期管理服务
      • peer.Initialize 节点初始化
      • registerDiscoveryService 注册节点发现服务
      • LoadPreResetHeight 检查节点账本是否重设
      • RegisterEndorserServer 注册背书服务
      • peerServer.Start() 节点服务启动

流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
graph TB
Enter(入口 - `peer/main.go` **) --> Init(加载环境变量)
Init --> NodeCMD(Init Node子命令)
NodeCMD --> PreRun(PreRun `common.InitCmd` *)
PreRun --> RunCheck(检查MSP类型)
RunCheck --> aclProvider(生成ACL控制器)
aclProvider --> platforms(平台环境-Node,Java,Go控制器)
platforms --> DeployedCCInfoPrivider(部署链码控制器)
DeployedCCInfoPrivider --> identityDeserializerFabtory(获取身份检查工厂)
identityDeserializerFabtory --> metricsProvider(指标控制器)
metricsProvider --> ledgermgmt(初始化账本)
ledgermgmt --> serverConfig(加载服务端配置)
serverConfig --> NewPeerServer(生成节点通信服务)
NewPeerServer --> NewDeliverEventsServer(生成区块分发和块事件处理服务)
NewDeliverEventsServer --> startChaincodeServer(启动容器链码服务)
startChaincodeServer --> startAdminServer(启动管理服务)
startAdminServer --> NewEndorserServer(生成背书服务)
NewEndorserServer --> initGossipService(初始化流言服务)
initGossipService --> DeploySysCCs(部署系统链码)
DeploySysCCs --> NewLifeCycle(生成链码生命周期管理)
NewLifeCycle --> peer.Initialize(节点初始化)
peer.Initialize --> registerDiscoveryService(注册节点发现服务)
registerDiscoveryService --> RegisterEndorserServer(注册背书服务)
RegisterEndorserServer --> peerServer.Start(节点启动)

常见问题

  • 调用peer channel create的时候,会创建$CHANNEL_NAME.block的文件在程序目录。

    • 调试超时,order程序通道创建成功,但是没有把数据返回回去。
    • 后续在调用的的时候,会因为版本原因,调用失败。
    • 临时解决版本,就是order程序把对应生成的本地目录删除,在启动,重新执行。这个问题先记录。
  • 容器内安装ping

    • apt-get update
    • apt-get install iputils-ping
    • apt-get install net-tools
    • apt-get install telnet
    • telnet host.docker.internal 7052
  • 调试环境下启动链码容器,链码会连接节点的端口,会导致访问不了,因此需要调整启动容器的参数。把peer的地址修改下。

    • 修改环境CORE_PEER_CHAINCODEADDRESS=host.docker.internal:7052
  • 实例化链码调用在账本中无法查询。

Fabric基础概念

Organization 组织

组织(organization)代表一组拥有共同信任的根证书(可以为根CA证书或中间CA证书)的成员。

这个概念很重要,因为Fabric的共识是基于组织为单位的,并不是成员的节点为单位。

这些成员由于共享同样的信任根,彼此之间信任度很高,可以相互交换比较敏感的内容。同一个组织的成员节点在网络中可以被认为是同一个身份,代表组织进行签名。组织中成员可以为普通成员角色或者管理员角色,后者拥有更高的权限,可以对组织配置进行修改。

组织一般包括名称、ID、MSP信息、管理策略、认证采用的密码库类型、一组锚点节点位置等信息。通常情况下,多个组织为了进行数据沟通,可以加入到同一个通道中。

这里就涉及到一些细化领域的定义问题:

组织以行业为单位,比如中国银行、建设银行所有的银行作为一个组织。即每个银行是一个成员,节点服务托管。
组织以银行为单位,比如中国银行、建设银行分别为一个组织。

  • 这个问题的,本质上还是数据问题。

    • 情况一:银行没有节点。

    • 网络层面是同一个身份,当这个行业都没有自建节点的时候,并且是被三方托管的时候,就没有必要单独成为一个组织。

    • 情况二:银行有节点,并且每个银行之间数据私有,不期望别的银行知道。

    • 银行自建区块链节点,参与共识认证过程,那么每个银行都可以作为一个单独的组织。

    • 银行要参与链码的管理相关的事务,比如,确认链码升级、共识策略变化等操作。

    • 本质上是对区块链节点数据存在安全要求,期望独立开发区块链操作相关的应用,并且数据存储在自己的服务器上的时候。

Fabric证书结构

工具默认生成结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
├── ordererOrganizations [排序组织]
│ └── order.com
│ ├── ca
│ │ ├── 51d4e0177748d40336debef3e543521f442f82b548b109cd90cbe151ef669212_sk
│ │ └── ca.order.com-cert.pem
│ ├── msp
│ │ ├── admincerts
│ │ │ └── Admin@order.com-cert.pem
│ │ ├── cacerts
│ │ │ └── ca.order.com-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.order.com-cert.pem
│ ├── orderers
│ │ └── orderer.order.com
│ │ ├── msp
│ │ │ ├── admincerts
│ │ │ │ └── Admin@order.com-cert.pem
│ │ │ ├── cacerts
│ │ │ │ └── ca.order.com-cert.pem
│ │ │ ├── keystore
│ │ │ │ └── 180a6d9f4754eaaac2cd648668623be47e35e5c0018b927b5f82efef58a650d1_sk
│ │ │ ├── signcerts
│ │ │ │ └── orderer.order.com-cert.pem
│ │ │ └── tlscacerts
│ │ │ └── tlsca.order.com-cert.pem
│ │ └── tls
│ │ ├── ca.crt
│ │ ├── server.crt
│ │ └── server.key
│ ├── tlsca
│ │ ├── d98956ded7c42a4e35b668adb498ee18b93dd4d1f99e4d39a0dc8f3f78dc969f_sk
│ │ └── tlsca.order.com-cert.pem
│ └── users
│ └── Admin@order.com
│ ├── msp
│ │ ├── admincerts
│ │ │ └── Admin@order.com-cert.pem
│ │ ├── cacerts
│ │ │ └── ca.order.com-cert.pem
│ │ ├── keystore
│ │ │ └── 94738b964081e602b6043f0975b9b64799e450c506681d0660b047d458196462_sk
│ │ ├── signcerts
│ │ │ └── Admin@order.com-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.order.com-cert.pem
│ └── tls
│ ├── ca.crt
│ ├── client.crt
│ └── client.key
└── peerOrganizations [节点组织]
├── government.peer.com
│ ├── ca [组织Government的根证书和私钥]
│ │ ├── ca.government.peer.com-cert.pem [ca.government.peer.com]
│ │ └── d7a91d3adecd49c742f6cec9287783f5412d865310311de6dde3041eff432231_sk [私钥]
│ ├── msp [组织身份证书信息]
│ │ ├── admincerts
│ │ ├── cacerts
│ │ │ └── ca.government.peer.com-cert.pem [CA根证书]
│ │ ├── config.yaml
│ │ └── tlscacerts
│ │ └── tlsca.government.peer.com-cert.pem [TLS根证书]
│ ├── peers [存放属于该组织的所有Peer节点]
│ │ └── peer0.government.peer.com
│ │ ├── msp
│ │ │ ├── admincerts
│ │ │ │ └── Admin@government.peer.com-cert.pem [组织管理员的身份验证证书,节点使用此证书验证管理员。]
│ │ │ ├── cacerts
│ │ │ │ └── ca.government.peer.com-cert.pem [CA根证书]
│ │ │ ├── config.yaml
│ │ │ ├── keystore
│ │ │ │ └── 6900d2e33c34cfe8bc8b6413e0d587cb057337de654133ab6813eaba4bc07f17_sk [本节点的身份私钥,节点标识签名]
│ │ │ ├── signcerts
│ │ │ │ └── peer0.government.peer.com-cert.pem [节点的证书]
│ │ │ └── tlscacerts
│ │ │ └── tlsca.government.peer.com-cert.pem [TLS根证书]
│ │ └── tls
│ │ ├── ca.crt == tlsca.government.peer.com-cert.pem [TLS通信CA证书]
│ │ ├── server.crt [TLS通信服务端证书]
│ │ └── server.key [TLS通信服务私钥]
│ ├── tlsca
│ │ ├── 927e236a93f0581a92ccb1c4d65dd8e9bae1e1557725d79747d60f26b874d55c_sk [TLS根证书私钥]
│ │ └── tlsca.government.peer.com-cert.pem [TLS根证书]
│ └── users [存放属于该组织的用户的实体]
│ └── Admin@government.peer.com
│ ├── msp
│ │ ├── admincerts
│ │ ├── cacerts
│ │ │ └── ca.government.peer.com-cert.pem [管理员签发CA根证书]
│ │ ├── config.yaml
│ │ ├── keystore
│ │ │ └── d0c1b5d5d6a88ea0a477b2799c8702fe4704765c8f192aadddb626e8e4128cf1_sk [组织管理员私钥]
│ │ ├── signcerts
│ │ │ └── Admin@government.peer.com-cert.pem [组织管理员证书]
│ │ └── tlscacerts
│ │ └── tlsca.government.peer.com-cert.pem
│ └── tls
│ ├── ca.crt == tlsca.government.peer.com-cert.pem [组织tls根证书]
│ ├── client.crt [TLS通信客户端证书]
│ └── client.key [TLS通信客户端私钥]
└── public.peer.com
├── ca
│ ├── c4752a7c5c82202eb60f2776edd506f8a12fc18a263c98333908b7982cecc348_sk
│ └── ca.public.peer.com-cert.pem
├── msp
│ ├── admincerts
│ ├── cacerts
│ │ └── ca.public.peer.com-cert.pem
│ ├── config.yaml
│ └── tlscacerts
│ └── tlsca.public.peer.com-cert.pem
├── peers
│ └── peer0.public.peer.com
│ ├── msp
│ │ ├── admincerts
│ │ │ └── Admin@public.peer.com-cert.pem
│ │ ├── cacerts
│ │ │ └── ca.public.peer.com-cert.pem
│ │ ├── config.yaml
│ │ ├── keystore
│ │ │ └── c3d1f75d9e6a4ab2c80ea6a27e3dd26aeb2b8a47b35ef9e39d66a6e915f33577_sk
│ │ ├── signcerts
│ │ │ └── peer0.public.peer.com-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.public.peer.com-cert.pem
│ └── tls
│ ├── ca.crt
│ ├── server.crt
│ └── server.key
├── tlsca
│ ├── 4898d32e49c06d7045a9d2f6e5ef047ab2ec472a76fd83bcd243c36f90d9c09b_sk
│ └── tlsca.public.peer.com-cert.pem
└── users
└── Admin@public.peer.com
├── msp
│ ├── admincerts
│ ├── cacerts
│ │ └── ca.public.peer.com-cert.pem
│ ├── config.yaml
│ ├── keystore
│ │ └── 2f4c9c32ff8ec24d7ef680407ef636b6c5802108fc16e655525939ad01a87364_sk
│ ├── signcerts
│ │ └── Admin@public.peer.com-cert.pem []
│ └── tlscacerts
│ └── tlsca.public.peer.com-cert.pem
└── tls
├── ca.crt
├── client.crt
└── client.key

查看节点证书信息

1
openssl x509 -in peers/peer0.government.peer.com/msp/signcerts/peer0.government.peer.com-cert.pem -text -noout

验证节点证书的签发机构

1
2
3
4
5
6
7
openssl verify -CAfile ca/ca.government.peer.com-cert.pem peers/peer0.government.peer.com/msp/signcerts/peer0.government.peer.com-cert.pem
peers/peer0.government.peer.com/msp/signcerts/peer0.government.peer.com-cert.pem: OK

openssl x509 -text -in peers/peer0.government.peer.com/msp/signcerts/peer0.government.peer.com-cert.pem | grep OU=
Subject: C=CN, ST=Sichuan, L=Chengdou, OU=peer, CN=peer0.government.peer.com

OU类型是peer。

验证Government组织的管理员证书签发机构。

1
2
3
4
5
6
7
openssl verify -CAfile ca/ca.government.peer.com-cert.pem users/Admin@government.peer.com/msp/signcerts/Admin@government.peer.com-cert.pem 
users/Admin@government.peer.com/msp/signcerts/Admin@government.peer.com-cert.pem: OK

openssl x509 -text -in users/Admin@government.peer.com/msp/signcerts/Admin@government.peer.com-cert.pem | grep OU
Subject: C=CN, ST=Sichuan, L=Chengdou, OU=admin, CN=Admin@government.peer.com

OU类型是admin。

在Fabric中CA有2类,一类是通信层面的TLS证书。另外一个层面是节点,用户层面的证书,这块证书是涉及节点权限,用户访问权限的控制。

TLS的CA表示着,访问端口的时候,需要带上对应端口使用的TLSCA证书文件。

Fabric-Order-Broadcast处理

Broadcast,广播
客户端将请求消息(例如完成背书后的交易)通过 gRPC 接口发送给 Ordering 服务。Orderer 进行本地验证处理后,会转化为入队消息发给后端共识模块(如 Kafka)。

发给 Orderer 的 Broadcast 请求消息包括链码的实例化、调用;通道的创建、更新。

FabricSDK相关

整理一些看SDK实现时候有意思的代码

在Fabric的SDK的新的版本,引入了Gateway在后续版本中建议使用此模块来访问Fabric网络,因为这个库简化了高可以的访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// fabric-network/lib/gateway.js

constructor() {
this.options = {
queryHandlerOptions: {
strategy: QueryStrategies.MSPID_SCOPE_SINGLE
},
eventHandlerOptions: {
commitTimeout: 300, // 5 minutes 这个是修改SDK等待超时行为。
strategy: EventStrategies.MSPID_SCOPE_ALLFORTX
},
discovery: {
enabled: Client.getConfigSetting('initialize-with-discovery', true)
},
checkpointer: {
factory: CheckpointFactories.FILE_SYSTEM_CHECKPOINTER,
options: {}
},
eventHubSelectionOptions: {
strategy: EventHubSelectionStrategies.MSPID_SCOPE_ROUND_ROBIN,
}
};
}

// 其中QueryStrategies.MSPID_SCOPE_SINGLE
/**
* @typedef DefaultQueryHandlerStrategies
* @memberof module:fabric-network
* @property {function} MSPID_SCOPE_SINGLE Query any one of the event hubs for the connected organisation. Continue
* to use the same event hub for all queries unless it fails. 查询通过所连接组织的任何一个活动节点。每次查询都使用相同的节点,除非发生查询失败。
* @property {function} MSPID_SCOPE_ROUND_ROBIN Query any one of the event hubs for the connected organisation.
* Use the next available peer for each successive query. 查询通过所连接组织的任何一个活动节点。在每次成功查询之后使用下一个有效的节点。
*/

module.exports = {
MSPID_SCOPE_SINGLE,
MSPID_SCOPE_ROUND_ROBIN
};

// 事件策略,默认是等待同一个组织下的所有节点响应事件。
/**
* @typedef DefaultEventHandlerStrategies
* @memberof module:fabric-network
* @property MSPID_SCOPE_ALLFORTX Listen for transaction commit events from all peers in the client identity's
* organization. 侦听来自客户端标识组织中所有对等方的事务提交事件。
* The [submitTransaction]{@link module:fabric-network.Contract#submitTransaction} function will wait until successful
* events are received from <em>all</em> currently connected peers (minimum 1). 函数将等待,直到从所有当前连接的对等方接收到成功的事件(至少1个)。
* @property MSPID_SCOPE_ANYFORTX Listen for transaction commit events from all peers in the client identity's
* organization.
* The [submitTransaction]{@link module:fabric-network.Contract#submitTransaction} function will wait until a
* successful event is received from <em>any</em> peer. 函数将一直等到从任何对等方接收到成功的事件。
* @property NETWORK_SCOPE_ALLFORTX Listen for transaction commit events from all peers in the network.
* 侦听来自网络中所有对等方的事务提交事件。
* The [submitTransaction]{@link module:fabric-network.Contract#submitTransaction} function will wait until successful
* events are received from <em>all</em> currently connected peers (minimum 1). 函数将等待,直到从所有当前连接的对等方接收到成功的事件(至少1个)。
* @property NETWORK_SCOPE_ANYFORTX Listen for transaction commit events from all peers in the network.
* The [submitTransaction]{@link module:fabric-network.Contract#submitTransaction} function will wait until a
* successful event is received from <em>any</em> peer. 函数将一直等到从任何对等方接收到成功的事件。
*/

module.exports = {
MSPID_SCOPE_ALLFORTX,
MSPID_SCOPE_ANYFORTX,
NETWORK_SCOPE_ALLFORTX,
NETWORK_SCOPE_ANYFORTX
};
1
2
3
4
5
6
7
8
9
10
11
/**
* Handles events for a given transaction. Used to wait for a submitted transaction to be successfully commited to
* the ledger.
* Delegates to an event strategy to decide whether events or errors received should be interpreted as success or
* failure of a transaction.
* 委托给事件策略,以决定接收到的事件或错误是应解释为事务成功还是事务失败。
* @private
*/
class TransactionEventHandler {

}

区块链交互本质上和网络交互存在一个相同的问题,当发生在区块链层面的数据提交发生成功或者失败的时候。
业务层面,应该如何避免数据不一致的问题。
例如:
A程序,发出一个请求。
B程序开始处理。
A程序崩溃。
A程序重启后,如何处理在崩溃瞬间的任务处理策略,是应该重试还是修正。
联盟链本质上存在一个问题,CAP问题,没有事务,如何解决最终一致性问题,并且有效的返回前端用户正确的响应,是我们应该考虑和解决的问题。
传统的分布式事务和区块链存在差异,传统事务是可以重试,在业务过程失败, 区块链执行成功的情况,理论上是不应该重试,重试会导致区块链网络存在新的交易记录。

整个本质上还是分布式事务处理问题

CAP在区块链上的问题,个人觉得使用ebay的方案就可以了。支付宝DTS方案,基于2PC模式肯定也不适合区块链场景。

蘑菇街的方案个人感觉比较适合常规的分布式事务的处理,理解起来比较简单,不过在真实的场景实现应该还有很多细节问题。

执行操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Generate Blockchain Transaction Id

Begin Transaction
Insert Into TransactionRecord (Transaction Id, Transaction Data)
Queue Message (Transaction Id, Transaction Data)
End Transaction

Result = Execte Blockchain Commit

If Result Failed
# 如果发生失败,移除队列信息。
Begin Transaction
Remove Queue Transaction Id
return Failed Message
End Transaction
Else
Begin Transaction
Get Other Data Form Query Result
Insert Into Other Data To DB
Remove Queue Transaction Id
return Success Message
End Transaction
End

重启后执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
For each message in queue

Peek message

# 区块链网络上查询对应的区块ID。
Execte Blockchain Query Transaction ID

# 存在表示交易执行成功
If Exist
Begin Transaction
Get Other Data Form Query Result
Insert Into Other Data To DB
Remove Queue Transaction Id
End Transaction
# 这里不在执行重试。
Else
Begin Transaction
Remove Queue Transaction Id
End Transaction
End If
End for

浏览器接口行为,当多台负载的情况下,一个崩溃后会导致数据重试到其它服务器,这个时候区块链层面的交易ID是不同的。
因此,不能在崩溃重启的时候,直接重写旧的交易数据,因此区块链只兜底,在区块链数据已经写入的情况,中心化数据库没有写入时的数据一致。

基于用户会话的接口控制,必须保证用户同时只能登录一个地方,这个有可能不符合需求,比如需要浏览器,手机同时登录,这个时候,如果不是公用Token的处理模式,就会导致存在问题。

  • 执行太久导致重试,并且请求定向负载均衡的其它服务。
  • 执行请求时候,服务崩溃,定向到其它服务再次执行,导致区块链层面数据执行2次。

解决在多台服务负载的情况下,保证数据一致性

分布式事务问题

分布式事务问题, 可能是金融系统最难处理的问题之一了

其它

CAP原则, 在分布式系统中, 一致性(Consistency)、可用性(Avaliability)、分区容错性(Partition Tolerance), CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。

  • P 分区容错性, 分布式系统的多个节点之间, 必然可能出现无法通信的情况, 因此在分布式系统中必定只能是CP或者AP
  • 一致性和可用性是相互冲突的, 如果要一致, 在更改一个节点的数据的时候, 必须同步修改其它节点的数据, 这个过程中, 其它节点是无法读取和写入就违背了可用性原则.

因此, 在分布式系统中都不追求强一致性, 只需要保证最终所有节点的数据一致即可.

ACID数据库在写入和更新资料的时候保证事务的正确可靠必须具备的四个特性:原子性(atomicity,或称不可分割性)、一致性(consistency)、隔离性(isolation,又称独立性)、持久性(durability)。

  • Atomicity(原子性):一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。
  • Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。
  • Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括未提交读(Read uncommitted)、提交读(read committed)、可重复读(repeatable read)和串行化(Serializable)。
  • Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。