前言
以论坛项目为例,其中一个常见的统计更新需求是发布主题或回帖时会相应累加更新数据库相关统计表中目标日期对应的主题数或发帖数。考虑到这种性质的统计数据其实并不需要纯实时更新且增加不必要的数据库写压力,我们可以在 Golang 层面从数据库初始化存储至内存变量并在相应处理业务中更新相关的统计数据变量,再定时更新至数据库即可。
但这里有一个典型的问题是竞态条件(race condition),即数据一旦被多个线程共享操作,那么就很可能会产生争用和冲突的情况,这往往会破坏共享数据的一致性。如果不对这种并发操作共享数据加以控制,则最后得到的累加统计数据很可能是被低估而失真的。
在解决这个问题的角度上,本文不打算阐述诸如数据库锁、第三方内存缓存、消息队列等外部工具的配合使用方案,毕竟 Go 语言是以独特的并发编程模型傲视群雄的语言,我们应该完全可以在此层面解决之。因此本文将列出利用 Go 语言中的几个内置工具来解决的方案。
Golang http 连接中的协程
首先说到并发编程,不得不提到 Golang 中的协程。首先协程可看作用户态线程,在 Golang 中即 goroutine。Golang 中启用协程比较方便,使用 go 关键字即可。例如:
我们现在来看一下 Golang 中 http 服务涉及的 Server struct,这个结构体中有个 Serve 方法,此方法的部分说明如下: