go如何启动一个协程?
package main
import (
"fmt"
"time"
)
// 这是一个普通的函数,我们将用goroutine来并发执行它
func doSomething(id int) {
fmt.Printf("协程 %d 开始执行...\n", id)
time.Sleep(time.Second * 2) // 模拟耗时操作
fmt.Printf("协程 %d 执行结束.\n", id)
}
func main() {
// 启动两个协程
go doSomething(1)
go doSomething(2)
// 注意:main函数的goroutine将继续执行,不会等待doSomething函数完成
fmt.Println("主goroutine在等待协程执行...")
// 可以通过sync.WaitGroup或者其他同步机制确保所有协程执行完毕
// 但是在本例中我们简单地让main函数结束,实际应用中可能需要适当处理
}
两阶段提交, 三阶段提交?
两阶段提交(Two-Phase Commit, 2PC)和三阶段提交(Three-Phase Commit, 3PC)是分布式系统中用于实现跨多个数据库或服务节点的分布式事务的一致性协议。这两种协议主要用于确保在分布式环境下的事务要么全部成功,要么全部失败,从而维持事务的原子性和一致性。
两阶段提交(2PC)
阶段一:准备阶段(Prepare Phase)
- 协调者(Coordinator)向所有参与节点(Participants)发送“准备提交”的请求,每个参与者执行事务操作但不提交,进入“预提交”状态,并记录undo/redo日志以便后续回滚或提交。
- 参与者回复“准备好”(同意继续)或“无法准备”(遇到错误或资源不足等情况)。
阶段二:提交阶段(Commit Phase)
- 协调者根据所有参与者的反馈决定是否提交事务:
- 如果所有参与者都回复“准备好”,则协调者向所有参与者发送“正式提交”命令。
- 如果有任何参与者回复“无法准备”,则协调者向所有参与者发送“回滚”命令。
- 参与者收到“提交”或“回滚”命令后,执行相应的操作并释放资源。
缺点:
- 单点故障问题:协调者节点的故障可能导致整个事务长期阻塞。
- 同步阻塞:在第二阶段,所有参与者都会等待协调者的决策,导致资源长时间锁定。
三阶段提交(3PC)
阶段一:CanCommit Phase
- 协调者询问所有参与者是否可以提交事务。
- 参与者根据自身情况决定是否可以提交,回复“可以”或“不可以”。
阶段二:PreCommit Phase
- 如果所有参与者在第一阶段回复“可以”,协调者发送“预提交”命令给所有参与者,参与者开始锁定资源并做好提交准备。
- 参与者收到“预提交”命令后,进入预备提交状态,但不会立即提交事务,而是等待协调者的最终指令。
阶段三:DoCommit Phase
- 协调者根据第二阶段的反馈决定:
- 如果所有参与者都准备好提交,发送“正式提交”命令。
- 如果有参与者不能提交,发送“中止”命令。
- 参与者根据第三阶段的指令执行提交或回滚操作,并释放资源。
改进之处:
- 引入超时机制:在每个阶段结束后,如果协调者未收到响应,参与者可以选择回滚事务以避免资源长期锁定。
- 延迟提交减少阻塞:相较于2PC,3PC减少了在最终决定阶段的阻塞时间。
仍然存在的问题:
- 虽然减轻了阻塞问题,但并未完全消除,尤其是当协调者在第三阶段发送完指令后发生故障时,仍可能出现不一致的情况。
- 单点故障风险依然存在,尽管相对较小。
最后编辑: kuteng 文档更新时间: 2024-04-02 09:53 作者:kuteng