原子计数器 - Redis vs Postgres或其他数据库?

11
I希望您能在云上实现一个原子计数器,以从并发连接生成连续整数。这背后的业务是跟踪服务器。

优先要求:

  1. (必须) 耐用 - 确保一旦客户获得一个数字,其他客户永远不会获得相同的数字。不要重复。
  2. (必须) 可扩展 - 当前负载为每秒10K,在200-1000并发客户端连接中未来将达到每秒1M。可扩展性特性增加了100。
  3. (必须) 平均误差在+-15毫秒内(postgres/mysql/redis很好,但像DynamoDB这样的http延迟是不可能的)这只是为了筛选出较慢的解决方案
  4. (可选) 以增量方式增加 这是一种扩展性方法,其中客户端按块(例如100)递增并在应用程序内存中管理递增。
  5. (可选) 公平价格< 150美元,每秒5k,预计在更低的定价增长。
  6. (可选) HA(高可用性) - 我可以处理0.01%的故障,但耐久性很重要,我需要没有重复的号码。

我的备选方案是:

  1. postgres序列的顺序为CREATE SEQUENCE serial CACHE 100; SELECT nextval(sequence) - 140$/m MultiAZ AWS RDS db.m3.medium不像redis那样快,但我认为平均速度< 7ms。 "缓存"是一个强大的功能,应该提高性能。
  2. Redis INCR与Redis Sentinel/RDS MultiAZ - cache.m3.medium MultiAZ - 120$/m - 耐久性有问题。

Redis具有INCRBY,而Postgres仅具有序列的“缓存”功能,需要往返到数据库。

您有任何意见吗?关于这两个选择或其他选择?


这需要放在数据库中吗?你不能使用大多数编程平台中存在的同步原语来构建自己的“计数器服务”吗? - Dai
3
也许您应该使用GUIDs? - Dai
2
我认为单个Redis或Postgres实例无法处理每秒1M的请求。您需要一些分布式方法来生成唯一的ID。看看Twitter的Snowflake,它可能会有所帮助。 - for_stack
1
您没有明确说明需要存储任何数据。如果只需维护计数器,那么真的不应该在数据库中进行计数。正如Dai所说,一个(实际上并不是很复杂的)服务确实是最好的选择(除了在协议栈中实现)。不仅数据库了解锁定/事务处理,它们依赖于底层系统进行锁定。您的服务也可以使用这种方式。至于价格:很好,这只是一个美好的愿望。对于1M/s,您可以轻松地增加一两个0(但成本压力可能会导致其他概念,例如客户端获得100(0)的范围)。 - Solarflare
forslack - 谢谢你分享关于Snowflake的信息,它肯定是未来流量增长的一个很好的选择。 - naviram
显示剩余2条评论
1个回答

16

我认为你高估了Redis故障的风险,因为它无法刷新到磁盘,并低估了任何关系数据库管理系统(RDBMS)出现同样问题的风险。在两种情况下,通过将写操作同步到磁盘可以减轻风险。

在Redis中,这意味着切换到AOF(只追加文件)模式,如您已经提供的持久化链接中所述。

不需要进行任何过期键的技巧。 incrincrby的原子行为足以确保唯一性和耐久性,特别是与AOF持久化结合使用时。

Redis对于此用例来说几乎完美。它足够快且可扩展。 Redis已经存在一段时间了。没有任何合法的耐久性问题会不关心PostgreSQL或MySQL。

正如@Solarflare所指出的,让应用程序一次获取多个ID块更具成本效益和可扩展性。这可以在Redis中使用incrby来实现。


Carl,这正是我个人所需要的输入,我将接受这个答案,并提到for_clack和Solaflare对此的贡献。 - naviram
Redis似乎也是一个很好的选择,因为它在这种情况和其他情况下都具有可扩展性特点。 - naviram
1
我还要感谢 for_slack 提到像 Twitter Snowflake 这样的分布式唯一 ID 解决方案,以及 Solflare 指出当扩展规模时,我的 100(0) 范围建议实际上是分布式解决方案的一种具有成本效益的替代方案。 - naviram
对 Redis 中如何进行范围操作进行了小的更新,以作澄清。 - Carl Zulauf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接