写入缓存与写入数据库 - 性能基准?

时间:2014-03-27 15:20:31

标签: ruby-on-rails postgresql memcached

我在rails应用程序上有一个ruby,每分钟大约需要10000个请求。 其中一些请求执行对数据库表的写入。与数据库的最大连接数为200.

我想知道哪些更有效率。写入缓存中的数组并在一次操作中将数据保存在后台,或者将每个请求直接保存到数据库中? 如果我将数据写入缓存中的数组,是否存在任何竞争条件或性能问题? 有没有更好的方法来优化性能并避免数据库瓶颈?

示例代码

 #...
  def self.add_data_message_to_queue(event_id, chat_item)
    bucket_name = 'BUCKET_GET_CHAT_' + event_id.to_s
    chat_queue = Rails.cache.fetch(bucket_name)
    if chat_queue.blank?
      chat_queue = []
    end
    chat_queue.push(chat_item)
    Rails.cache.write(bucket_name, chat_queue, expires_in:Integer(30).days)
  end
  • 服务器:Unicorn(高并发)

提前致谢

1 个答案:

答案 0 :(得分:1)

<强>解

根据写入memcache的基准测试更有效率。 虽然有必要处理竞争条件。根据memcachier团队的反馈。

测试将聊天消息保存到数据库 enter image description here

相同测试 - 不将聊天消息保存到当前数据库

响应时间更好。该应用还可以每分钟提供更多请求。

enter image description here

处理竞争条件 *(来自memcachier团队的反馈)

一般来说,有两种方法可以在memcache中解决这个问题:

由于您要附加到数组,因此您可以使用memcache的APPEND和PREPEND操作。 Rails.cache不支持它们,但底层库Dalli支持这些命令。他们的语义是他们将字符串附加/前置到现有值。当您获取该值时,您将获得所有“附加”连接在一起的字符串,因此您必须例如将每个元素用分号或类似的东西分隔,以将其分解为数组。

更通用的解决方案(适用于任何数据竞争条件)是使用memcache中的版本控制支持。具体来说,memcache中的每个值都分配了一个版本,该版本在任何get请求中返回。在memcache中设置操作可以采用可选的CAS(用于比较和交换)字段,这样只有当版本与存储的当前值匹配时,操作才会成功。同样,我相信Rails.cache不支持这个,但Dalli通过cas方法支持:

cache.add("bucket_get_chat", [])
while(!cache.cas("bucket_get_chat") {|val| val.push(chat_item)}); end