You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Cassandra gocql重试策略生效?自定义重试未触发排查

问题排查与解决方案

核心原因

gocql的RetryPolicy仅针对驱动层面的可重试错误(如连接超时、节点不可用、一致性级别未满足等),而你遇到的“未找到”错误(对应gocql.ErrNotFound)属于业务层面的查询结果为空,不在驱动默认的可重试错误列表里,所以完全不会触发你自定义的重试策略逻辑。

解决方案:手动实现业务重试逻辑

既然需要针对“未找到”这种业务场景重试,就得在代码里手动循环执行查询,直到满足条件或达到重试上限。修改后的代码示例如下:

package main

import (
  "context"
  "fmt"
  "log"
  "time"

  "github.com/gocql/gocql"
)

func main() {
  cluster := gocql.NewCluster("192.168.8.4")
  cluster.Keyspace = "store"
  cluster.ProtoVersion = 4
  session, err := cluster.CreateSession()
  if err != nil {
    log.Fatalln(err)
  }
  defer session.Close()

  ctx := context.Background()
  var count int
  maxRetries := 10
  retryInterval := 3 * time.Second
  var lastErr error

  // 手动循环重试逻辑
  for attempt := 0; attempt <= maxRetries; attempt++ {
    fmt.Printf("执行查询,第%d次尝试\n", attempt+1)
    q := session.Query(`SELECT item_count FROM shopping_cart WHERE userid=?;`, "123").
      Idempotent(true).
      WithContext(ctx)
    
    lastErr = q.Scan(&count)
    if lastErr == nil {
      // 查询成功,退出循环
      break
    }
    if lastErr != gocql.ErrNotFound {
      // 遇到非预期错误,直接终止
      log.Fatalln("查询遇到非预期错误:", lastErr)
    }
    // 是未找到错误,未达重试上限则等待后重试
    if attempt < maxRetries {
      fmt.Printf("未找到数据,%v后重试\n", retryInterval)
      time.Sleep(retryInterval)
    }
  }

  if lastErr != nil {
    log.Fatalln("达到最大重试次数,仍未找到数据:", lastErr)
  }

  fmt.Printf("the count is %d\n\n", count)
}

补充说明

  • 如果你坚持要通过RetryPolicy实现,理论上可以修改驱动源码或通过中间层包装错误,但这会增加复杂度,不推荐。手动重试是最直接且可控的方式。
  • 保持Idempotent(true)标记,确保重试不会带来副作用(读操作本身就是幂等的,这个标记主要是为了符合驱动的重试安全校验)。

内容的提问来源于stack exchange,提问作者chengdol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 01:52:33