【问题标题】:Best way to provide redis client for extensible go applications为可扩展的 Go 应用程序提供 Redis 客户端的最佳方式
【发布时间】:2018-11-12 15:01:50
【问题描述】:

我在一个应用程序中使用 redigo,我想知道我的服务应该如何与 Redis 交互。

维基百科对线程安全有这样的说法:

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

我对此的解释是,如果一个数据结构需要被多个客户端访问(在当今的微服务世界中,有数百、数千甚至数百万),线程安全是我们确保状态正常的方式无论哪个客户端以及何时访问数据,都可以正确保存在系统中。这意味着解决访问优先级(哪个客户端首先到达那里),确保锁定突变(一次只有一个客户端可以写入)同时促进并发性(如果没有更改,许多客户端可以读取数据)。

据我所知,一个 redigo 客户端可以被多个“goroutines”(或线程)同时使用。这让我相信像我熟悉的 Java 中的单例实现就足够了。

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

我会这样做:

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

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

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

或者,我每次想访问数据存储时都不能创建pool(客户端)有什么原因吗?如果客户端在事务完成后被杀死,那么每次处理程序收到请求时启动新的pool 是否有任何问题?

【问题讨论】:

标签: go redis redigo


【解决方案1】:

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

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

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

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

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

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

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

  1. 打开连接很昂贵
  2. 在不使用数据库的情况下保持连接的成本很高,只能保持有限数量的打开连接。

通过连接池你可以控制:

  1. 始终打开多少连接 - 预热慢速资源
  2. 最大打开连接数 - 防止打开太多连接
  3. 连接超时 - 连接重用和释放未使用资源之间的平衡

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

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

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

【讨论】:

    猜你喜欢
    • 2016-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-01
    • 2010-09-27
    • 1970-01-01
    • 2013-08-09
    • 2016-08-14
    相关资源
    最近更新 更多