分组操作
分组执行一批相同的或类似的任务则是任务编排中一类情形
ErrGroup
将一个大的任务拆成几个小任务并发执行,可以有效地提高程序的并发度
方法
- WithContext
- 返回一个 Group 实例和 context.WithCancel(ctx) 生成的新 Context
- 子任务返回错误,或者是 Wait 调用返回,这个新 Context 就会被 cancel
- Go
- 传入子任务函数 f ,成功,返回 nil,否则返回 error,并且 cancel 这个新的 Context。
- Wait
- 等所有子任务都完成,才会返回,否则阻塞等待。
- 有多个子任务返回错误,只会返回第一个出现的错误,所有的子任务都执行成功,返回 nil
gollback
用来处理一组子任务的执行的,它解决了 ErrGroup 收集子任务返回结果的痛点
方法
-
All
- 它会等待所有的异步函数(AsyncFunc)都执行完才返回
- 而且返回结果的顺序和传入的函数的顺序保持一致。
-
Race
- 只要一个异步函数执行成功,就立马返回。同时会把其它子任务的 Context cancel掉,这样子任务就可以中断自己的执行。
- 所有子任务都没有成功,就返回最后一个 error 信息。
-
Retry
- 执行一个子任务,如果子任务执行失败,它会尝试一定的次数,如果一直不成功 ,就会返回失败错误 ,如果执行成功,它会立即返回。
- 如果retires 等于 0,它会永远尝试,直到成功
Hunch
Hunch提供的功能和 gollback 类似,不过它提供的方法更多
方法
- All
- 传入一组可执行的函数(子任务),返回子任务的执行结果
- 一旦一个子任务出现错误,它就会返回错误信息
- Take
- 指定 num 个子任务正常执行完没有错误,就会返回这几个子任务的结果。
- 一旦一个子任务出现错误,它就会返回错误信息
- Last
- 返回最后 num 个正常执行没有错误的子任务的结果(和Take相反)。
- 一旦一个子任务出现错误,它就会返回错误信息
- Retry
- 和 gollback 的 Retry 方法的功能一样
- Waterfall
- 所有的子任务都是串行执行的,前一个子任务的执行结果会被当作参数传给下一个子任务,直到所有的任务都完成,返回最后的执行结果。
- 一旦一个子任务出现错误,它就会返回错误信息
schedgroup
指定一组 goroutine在某个时间或者某个时间之后执行
方法
- Delay 和 Schedule
- 指定在某个时间或者之后执行一个函数
- Delay time.Duration 参数
- Schedule 指定明确的某个时间执行
- Wait
- 阻塞,直到之前安排的所有子任务都执行完才返回
- Context被取消,Wait 方法会返回这个 cancel error。
- 调用 Wait ,就不能调用它的 Delay 和 Schedule ,会 panic。
- 只能调用一次,多次调用会 panic。
分布式并发原语etcd
Leader 选举
- 选举
- 查询
- 监控
互斥锁
同一时刻,只允许其中的一个节点持有锁
- Locker
- 类似于 Go 标准库中的 sync.Locker 接口,提供了 Lock/UnLock 的机制,基于 Mutex 实现
- Mutex
- 提供了Lock/UnLock和查询 Mutex 的key 的信息的功能
- 读写锁
- 和标准库的读写锁的功能是一样的
队列
分布式队列
多读多写的队列,可以启动多个写节点和多个读节点
优先级队列
和队列类似,写入元素需要提供 uint16 整数优先级,优先级高优先出队。
栅栏
Barrier:分布式栅栏
持有 Barrier 的节点释放了它,所有等待这个 Barrier 的节点才会继续执行
DoubleBarrier:计数型栅栏
初始化计数型栅栏时,就必须提供参与节点的数量,当这些数量的节点都 Enter 或者 Leave 的时候,这个栅栏就会放开
STM(事务)
- 简化多个key的操作,并且提供事务功能(要么全成功,要么全失败)
- 方法:Get、Put、Receive 和 Delete
内存模型
并发环境中多goroutine 读相同变量的时候,变量的可见性条件
happens-before
goroutine 内部,程序的执行顺序和它们的代码指定的顺序是一样的
go语言中保证的happens-before关系
- init 函数
- init函数一定在当前包的任何初始化代码之前执行
- goroutine
- 启动 goroutine 的 go 语句的执行,一定发生在此 goroutine 内的代码之前执行
- 根据此规则,go 语句传入的参数是一个函数执行的结果,那么,这个函数一定先于 goroutine 内部的代码被执行。(参数结果从传入的时候就固定了)
- Channel
- 对 Channel 的第n个发送操作,一定发生在第n个接收操作之前
- close Channel 的操作,一定发生在从 Channel中读取出零值之前。
- 对无缓冲的Channel的读取操作,一定发生在此Channel的发送操作之前
- Mutex/RWMutex
- 解锁操作一定发生在下次上锁操作之前
- WaitGroup
- Wait 方法等到计数值归零之后才返回
- Once
- once.Do(f) 调用,函数 f 一定会在任何 Do 方法返回之前执行
- atomic
- Store 一定在Load之前执行,但是太过于复杂,现阶段还是不要使用 atomic 来保证顺序性。