给 TiCDC 接上一个 unbound 的 channel

最近在改造 TiCDC 的 Sink 组件时需要为 MQ 类型的 Sink 接上一个 unbound 的 channel。 在搜索过程中发现了一个项目叫做 chann,它是一个接口统一并且支持范型的 channel。 虽然这个库看上去实现很简单,但是我在实际使用过程中并不是很顺利。下面我就介绍一下我在使用该库时遇到的问题和进行的思考。 此博客在 GitHub 上公开发布。 如果您有任何问题或疑问,请在此处打开一个 issue。 简介 该库由 golang 社区非常活跃的 changkun 编写,托管在他组建的 golang-design 组织下。 它提供了统一的接口来创建不同类型的 channel,并且支持范型: ch := chann.New[int]() // 无界限, 无容量限制 ch := chann.New[func()](chann.Cap(0)) // 没有缓存, 容量为 0 ch := chann.New[string](chann.Cap(100)) // 有缓存,容量为 100 它的发送和接收操作和原生 channel 一致: ch.In() <- 42 println(<-ch.Out()) // 42 它的关闭接口为: ch.Close() 从接口来看,它几乎能无缝的接入到我当前的项目当中,这也是我选择它的原因。 源码阅读 在开始分析我遇到的问题之前,我们需要先深入阅读一下源码。它的源码不是很长,并且我主要是用的是无界限的 chann,所以下面就着重看一下无界限的 chann 的源码。 type Chann[T any] struct { in, out chan T close chan struct{} cfg *config q []T } Chann 是一个范型结构体,它里面维护了 in 和 out channel,这就是我们能使用原生 channel 语法操作 chann 的入口和出口。...

July 10, 2022 · 5 min · Rustin liu

从 pingcap tidb 学习使用静态检查工具提升代码质量

大家好,我是 Rustin 。今天想跟大家简单介绍一下如何使用一些 golang 的静态代码检查工具来提升代码质量! 此博客在 GitHub 上公开发布. 如果您有任何问题或疑问,请在此处打开一个 issue。 简介 从去年接触到 TiDB 就开始尝试在社区帮忙修复一些简单的 Bug。最近,我在阅读代码的过程中发现 TiDB 的代码库中有大量的没有必要的类型转换,我就用 GoLand 分析检查出大部分的无效的类型转化, 然后提了一个 PR (CEO 半夜 review 代码,哈哈哈)修复。在这个 PR 中 zz-jason 大神 评论希望能够通过静态检查工具来检测无效的类型转换。 我经过一些研究,决定使用 unconvert 来检测无效的类型转换,然后在这个 PR 解决了这个问题。 最近我终于有机会在公司写 Go了,所以我也想在公司的项目上配置和使用一些静态检查工具来提升代码质量。 在经过一下午的努力之后终于把 TiDB 的大部分检查工具移植到了公司项目上,并且在 github 上创建了一个模板项目 go-boilerplate 。下面我就简单介绍一下这个模板的构建过程和使用的方式。 init 项目,添加代码 我最近使用的 Go 版本 1.13.8,所以就使用 go mod 来初始化和管理项目。 go mod init github.com/Rustin170506/go-boilerplate 然后我添加了 main 文件和一个用作例子的 foo 文件,目录结构如下所示: . ├── foo.go ├── foo_test.go ├── go.mod ├── go....

April 25, 2020 · 4 min · Rustin liu

Raft 领导人选举实现

大家好,我是 Rustin。最近在做 6.824 的实验 lab2,今天想写一篇文章记录一下前段时间做的 Raft 领导人选举机制的实现。 此博客在 GitHub 上公开发布. 如果您有任何问题或疑问,请在此处打开一个 issue。 简介 6.824 是 MIT 的分布式系统公开课,今年还有官方的视频资料放出。 目前也有国内的同学正在进行翻译工作,可以参考一下。 课程质量非常高,国内也有一些整理好的相关资料可以参考。 下面我就简单描述一下 Raft 领导人选举机制实现过程和一些踩过的坑,我会尽可能的聚焦在实现实验的细节上,因为我可能对 Raft 目前的理解也比较浅显。所以如果您对这篇文章感兴趣,请您先阅读论文和观看课程视频并尝试实现。 领导人选举规则分析 在 Raft 中分别有三种角色分别是:Leader, Follower 和 Candidate。在整个系统正常运行过程中,只会有一个 Leader 节点,其他的都是 Follower 节点。只有在需要重新选举的阶段,节点会尝试将自己转换为 Candidate,然后向所有的节点发出投票 RPC 消息展开选举。 我觉得而一个比较好的切入思路就是搞明白何时需要进行 Leader 的选举?我们阅读论文会发现主要有两种情况需要进行选举,一种就是当 Raft 集群启动之后开始第一次选举,另外一种就是 Leader 出现故障,无法使用心跳机制维持自己的统治, 导致选举超时机制触发,节点开始尝试新的一轮的选举(需要注意的是,选举有可能在一个 Term 中没有结果,那么就在下个 Term 中继续选举直到选出 Leader)。 搞清楚何时进行选举,我们再来看看选举的 RPC 请求和回复的数据结构: Request 参数 解释 term 候选人的任期号 candidateId 请求选票的候选人的 Id lastLogIndex 候选人的最后日志条目的索引值 lastLogTerm 候选人最后日志条目的任期号 Reply 返回值 解释 term 当前任期号,以便于候选人去更新自己的任期号 voteGranted 候选人赢得了此张选票时为真 从数据结构中我们可以看到能够影响到选举的主要有两个部分,一个是 Term,另外一个就是候选人的最后一条日志条目。那我们就尝试从这两点方面去消化和理解选举的规则:...

April 12, 2020 · 5 min · Rustin liu