go语言中的一个优雅的冥等补偿算法 backoff - 业务逻辑重试示例
package main
import (
"context"
"fmt"
"math"
"math/rand"
"time"
)
// 定义一个简单的接口,用于模拟可能失败的业务逻辑操作
type BusinessLogic interface {
TryOperation(ctx context.Context) error
}
// 实现BusinessLogic接口的具体结构体
type SampleBusinessLogic struct{}
// TryOperation尝试执行业务逻辑操作,可能会失败
func (bl SampleBusinessLogic) TryOperation(ctx context.Context) error {
// 模拟随机的失败概率
if rand.Intn(100) < 20 { // 20%的概率失败
return fmt.Errorf("operation failed")
}
fmt.Println("Operation succeeded")
return nil
}
// 使用回退算法执行业务逻辑操作
func ExecuteWithBackoff(ctx context.Context, bl BusinessLogic, maxRetries int) error {
var backoff = NewExponentialBackoff(50*time.Millisecond, 2, maxRetries)
var err error
for i := 0; i <= maxRetries; i++ {
err = bl.TryOperation(ctx)
if err == nil {
return nil // 成功执行,返回
}
if i < maxRetries {
time.Sleep(backoff.Next()) // 在重试之前等待一段时间
}
}
return err // 达到最大重试次数后返回错误
}
// 定义一个指数回退算法的结构体
type ExponentialBackoff struct {
initialDelay time.Duration
factor float64
maxRetries int
attempts int
}
// NewExponentialBackoff创建一个新的ExponentialBackoff实例
func NewExponentialBackoff(initialDelay time.Duration, factor float64, maxRetries int) *ExponentialBackoff {
return &ExponentialBackoff{
initialDelay: initialDelay,
factor: factor,
maxRetries: maxRetries,
}
}
// Next计算下一次尝试的延迟时间
func (b *ExponentialBackoff) Next() time.Duration {
if b.attempts >= b.maxRetries {
return 0
}
delay := b.initialDelay * time.Duration(math.Pow(b.factor, float64(b.attempts)))
b.attempts++
return delay
}
func main() {
ctx := context.Background()
bl := SampleBusinessLogic{}
maxRetries := 5
err := ExecuteWithBackoff(ctx, bl, maxRetries)
if err != nil {
fmt.Printf("Operation failed after %d attempts\n", maxRetries)
}
}
这段代码首先定义了一个BusinessLogic
接口,用于模拟可能失败的业务逻辑操作。然后实现了一个具体的结构体SampleBusinessLogic
来实现这个接口。接着定义了一个ExponentialBackoff
结构体来表示回退算法,并实现了Next
方法来计算下一次重试的延迟时间。ExecuteWithBackoff
函数使用这个算法来执行业务逻辑操作,如果在指定的最大重试次数内都失败了,则返回错误。在main
函数中,我们创建了上下文、业务逻辑操作和最大重试次数,并调用ExecuteWithBackoff
来执行示例。
评论已关闭