我在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
提前致谢
答案 0 :(得分:1)
<强>解强>
根据写入memcache的基准测试更有效率。 虽然有必要处理竞争条件。根据memcachier团队的反馈。
测试将聊天消息保存到数据库
相同测试 - 不将聊天消息保存到当前数据库
响应时间更好。该应用还可以每分钟提供更多请求。
处理竞争条件 *(来自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