2014-03-27 45 views
0

我有一个Ruby应用程序,每分钟需要大约10000个请求。 其中一些请求执行写入数据库表。到数据库的最大连接数是200.写入缓存vs写入数据库 - 性能基准?

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

示例代码

#... 
    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 
  • 服务器:独角兽(高并发)

在此先感谢

回答

1

SOLUTION

根据基准写入memcache是​​更有效率的方式。 虽然有必要处理竞赛条件。根据memcachier团队的反馈。

测试保存聊天消息DB enter image description here

同样的测试 - 不保存聊天消息当前DB

响应时间是更好的方式。该应用程序还可以每分钟处理更多请求。

enter image description here

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

有,一般来说,两个内存缓存来解决这个问题的方法:

既然你追加到一个数组,您可以改为使用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