Golang redigo 使用笔记 (二):并发处理和连接池

一、并发问题

redigo 官方的文档描述中,Receive()方法是不支持多并发的,原文为:

Do()方法是间接调用了 Receive()方法,所以 Do()方法也是不支持多并发的。我们可以用一段代码来验证这一点:

这里是一个函数,完成了一个简单的 INCRBY 命令,实现 nKey + i 功能,和正常情况不同的是在 Send()Flush()后不会立刻使用 Receive()来获取结果,而是让线程休眠一段时间再来获取。

主函数中开启两个 gorutine 运行这段代码:

运行结果:

可以看到,线程 5 先运行,然后线程 1 运行,由于线程 1 休眠时间短,所以它会先读取输入缓冲区的返回数据,按照预期,线程 1 读到的结果应该是 1,因为它只是执行了 incr nKey 1 。而实际上,它读到的却是线程 5 的结果。

从这里我们可以很明显看出这一过程是线程不安全的,即它是不支持多并发的。那么如果要实现并发应该怎么做呢,官方也提出了解决方法,使用线程安全的连接池来解决这个问题:

二、连接池

redigo 中的线程池是一个对象:

一个连接池创建的示例为:

当连接池创建完毕之后,如果需要使用连接时调用 pool.Get()方法即可获得一个可用的连接,此时再执行 Do()等方法时就不会被其他并发干扰,要注意的是每获取到一个可用的连接并且在使用完之后,一定要通过 conn.Close()来主动释放连接,以方便下一个应用调用,不然该连接将会一直被占用。

同时官方提供了一个 NewPool()来创建连接池,但是这个方法是不推荐的:

三、示例代码

一个完整的示例代码:

发表评论