惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
Stack Overflow Blog
Stack Overflow Blog
人人都是产品经理
人人都是产品经理
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
Vercel News
Vercel News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Y
Y Combinator Blog
The Cloudflare Blog
Last Week in AI
Last Week in AI
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
V
Visual Studio Blog
博客园 - 三生石上(FineUI控件)
小众软件
小众软件
Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
博客园 - 司徒正美
B
Blog RSS Feed
Microsoft Azure Blog
Microsoft Azure Blog
罗磊的独立博客
Hugging Face - Blog
Hugging Face - Blog
L
LangChain Blog

Posts on WKLKEN THINKING

apisix 中的 lrucache apisix 中的服务发现机制 apisix 中的负载均衡 apisix etcd机制 聊聊框架 关于 k8s 的 zero downtime deployment 一些建议 apisix 遇到的一些问题 关于在除夕前一天换了一个洗衣机的故事 Django DRF 性能优化 DRF 的一些实践 Part1: Serializer DRF继承关系图 Better Code: 关于接口的灵活性 新的仓库: wklken/naming 缓存使用的一些经验 Better Code: 抽象: 可扩展性与可维护性的抉择 Better Code: 异常时, 该提示用户哪些信息? Better Code: 更好的异常日志打印 Go: some libs Go: logrus性能提升 Go: gin validation 远程办公的一点总结 Go: 开发过程中的一些bug 项目管理实践: 风险驱动开发 Go: 一种error wrap调用链处理方式 漫谈技术选型 Go: 基于 apitest 做handler层单元测试 Go: go-sql-driver interpolateparams参数优化 [分享]深度工作 你需要更多的思考时间 Django项目重构小结
Go: go-redis/cache升级的坑
2021-03-05 · via Posts on WKLKEN THINKING

这是在做 Golang 项目中的一些实践

在做一个项目, 使用了 go-redis/redisgo-redis/cache

某个节点, 做了所有依赖包的升级.

在做缓存依赖包的升级时, 必须十分注意, 新版本的第三方包做了哪些变更, 阅读CHANGE LOG和相关的源码;

主要风险:

  • breaking changes
  • 对象/方法/参数等协议变更
  • 存储格式(是否向前兼容)

即, 一旦做了升级, 原先正常的代码, 可能会有问题

所以需要确认:

  1. 新老版本存储格式是否一致?
  2. 代码中涉及的地方是否使用同样的操作?

1. v7升级v8

issue: Can’t upgrade from v7 to v8 directly?

package main

import (
	"context"
	"fmt"

	cv7 "github.com/go-redis/cache/v7"
	cv8 "github.com/go-redis/cache/v8"
	rdsv7 "github.com/go-redis/redis/v7"
	rdsv8 "github.com/go-redis/redis/v8"
	msgpackv4 "github.com/vmihailenco/msgpack/v4"
)

func main() {
	// TODO: 测试放入redis用另一个取
	d := map[string]interface{}{
		"hello": 1,
		"world": "ok",
	}

	// 使用两个版本的cli进行测试, v7/v8
	// 1. 使用v7, marshal 放入db
	// 2. use v8, 获取

	v7 := &cv7.Codec{
		Redis:     rdsv7.NewClient(&rdsv7.Options{}),
		Marshal:   msgpackv4.Marshal,
		Unmarshal: msgpackv4.Unmarshal,
	}

	err := v7.Set(&cv7.Item{
		Key:    "aaa",
		Object: d,
	})
	fmt.Println("set err:", err)

	v8 := cv8.New(&cv8.Options{
		Redis: rdsv8.NewClient(&rdsv8.Options{}),
	})

	var result map[string]interface{}
	err = v8.Get(context.TODO(), "aaa", &result)
	fmt.Println("get err:", err)
	fmt.Println(result)
}

执行结果:

set err: <nil>
get err: unknown compression method: 6b
map[]

原因, go-redis/cache v8引入的压缩 v8/cache.go, 没有做向前兼容的逻辑

解决方案: 在基础类中, 更换掉key的namespace, 增加版本号; 例如 project:hello 变成 project:v8:hello

2. 升级v8后的msgpack 与 pipeline的处理

由于 go-redis/cache 主要用于单个对象的 set/get

某些业务场景下, 我们使用pipeline进行批量操作

此时, pipeline拿回回来的是 raw string, 原先v7由于set算法用的msgpack.Marshal, 自定义pipeline处理结果直接用msgpack.Unmarshal没有问题.

但是, 升级到v8后, 由于compession逻辑的存在, 此时使用原生的msgpack.Unmarshal将会报错(无法识别被压缩的字符串)

解决: 需要切换为 go-redis/cache 对象的Unmarshal