为可扩展的Go应用程序提供Redis客户端的最佳方法

时间:2018-11-12 15:01:50

标签: go redis redigo

我在应用程序中使用Redigo,我想知道我的服务应如何与Redis接口。

维基百科关于线程安全的说法是这样的:

  

线程安全是一种适用于多线程代码的计算机编程概念。线程安全代码仅以确保所有线程正常运行并满足其设计规范的方式操作共享数据结构,而不会发生意外交互。

我的意思是,如果一个数据结构需要被多个客户端访问(在当今的微服务世界中,数百个,即使不是数百万个,也要成千上万个),线程安全就是我们确保状态为无论哪个客户端访问数据以及何时访问数据,都正确地保留在系统中。这意味着解决访问优先级(哪个客户端首先到达那里),确保锁住突变(一次只有一个客户端可以写),同时促进并发(如果没有更改,许多客户端可以读取数据)。

从我收集到的信息来看,一个Redigo客户端可以同时被多个“ goroutines”(或线程)使用。这使我相信,像我在Java中熟悉的单例实现就足够了。

我看到了示例,例如herehere,其中Redis连接(pool s只是在main方法中创建的,并传递给各种redigo函数。尽管看起来确实遵循单例模式,但这似乎不是完成任务的最可靠方法。 (可以理解,第二篇文章实际上只是一个快速的n'dirty API。)

我会这样:

  1. main函数调用init中,它返回一个redigo pool

  2. 创建将pool接受为参数的处理程序函数(控制器)(一种“脏”依赖注入)。

(我认为)这将确保仅创建一个pool

或者,是否有任何原因导致我每次想访问数据存储区时都无法创建pool(客户端)?如果在交易完成后客户端被杀死,那么每次处理程序收到请求时,纺出新的pool是否有问题?

1 个答案:

答案 0 :(得分:1)

注释中已经提供了正确的答案,尽管我仍然想加5美分。

您的问题混淆了两个概念-并发和resource pool

并发代码可确保使用共享内存在同一个应用程序中安全地执行多个执行流。 在我们的示例中,我们有来自用户和处理程序的多个http请求,这些代码同时执行。数据库连接是该流程的一部分,是执行请求所必需的。

并发代码应能够使用DB连接并在必要时打开/关闭连接。

尽管如此,并发与定义在任何给定时间应打开多少连接以及如何重用/共享这些连接的规则无关:

  • 有人可以为每个请求创建数据库连接,并且该代码为 同时。
  • 有人可以使用一些共享的数据库连接,并且 代码是并发的,只要多个请求不干扰 彼此。内存锁通常可以实现什么。

另一方面,连接池是一种模式,它提供了处理数据库连接的有效方法。 为什么管理连接生存期很重要:

  1. 打开连接很昂贵
  2. 不使用数据库而无法维持的昂贵连接只能保持有限数量的打开连接。

使用连接池,您可以控制:

  1. 总是打开多少连接-预热慢速资源
  2. 打开的连接数上限-防止打开太多的连接
  3. 连接超时-连接重用与释放未使用的资源之间的平衡

维护每个请求的连接或连接池不允许有效的连接重用。每个请求都会因连接打开开销而减慢,通信量激增会导致打开太多连接等。

通常,应用程序在所有请求之间共享一个连接池。

有时,开发人员为不同类型的连接创建多个池。例如,一个用于交易操作的池和一个用于报告的池。