内存泄漏 Rails + Sidekiq + Heroku + jsonb
Memory Leak Rails + Sidekiq + Heroku + jsonb
我目前正在获取特定货币对过去两年的大量加密货币每小时价格。我已经将 Sidekiq 同时用于多个硬币。
问题是,当我使用 jsonb 存储信息时,我怀疑它导致了很大的内存泄漏。但我可能错了,我的 Active Record 查询没有优化。
结果是我的 Heroku Worker 不断超过配额并关闭。
def get_2_years_of_btc_data(coin_id)
begin
time_batches = [1451606400,1458810000,1466013600,1473217200,1480420800,1487624400,1494828000,1502031600,1509235200,1516438800,1523642400]
time_batches.each do |time|
sync_hourly_btc_data(coin_id,time)
end
rescue => e
#ScrapeLog.create(error: e.message, process: "Cryptocompare - Sync Coin Prices", resource: "coin", resource_id: coin_id)
end
end
def sync_hourly_btc_data(coin_id,floored_timestamp)
coin = Coin.find(coin_id)
snap = coin.snap
response = HTTParty.get("https://min-api.cryptocompare.com/data/histohour?fsym=#{coin.ticker}&aggregate=1&tsym=BTC&limit=2000&toTs=#{floored_timestamp}")
json = JSON.parse(response.body)
data = json["Data"]
if snap.btc_counter_cache < 1
snap.to_btc = data
else
new_data = data.select {|data| data["time"] > snap.btc_to_ts}
snap.to_btc = snap.to_btc + new_data
end
snap.btc_from_ts = snap.to_btc.first["time"]
snap.btc_to_ts = snap.to_btc.last["time"]
snap.coin.real_price_btc = snap.to_btc.last["close"]
snap.btc_counter_cache = snap.to_btc.size
snap.save
end
Snaps是存储每个硬币价格信息的table,to_btc是jsonb存储所有数据的列。
我需要帮助来了解这是一个常见的 jsonb 问题,当它的大小增加或我的 Active Record 查询效率低下时。
谢谢!
这里的问题似乎不是 jsonb。我假设所提供的代码是实际的工作人员,所以我在这里的第一遍是将工作人员 per 时间批次排入队列。您目前执行此操作的方式似乎必须将所有 API 响应保存在内存中。
因此,如果您在每个时间批次中排队 job/worker,您可以单独处理每个响应 - 考虑到工作人员之间的一些退避(排队到 运行 2 分钟左右),您应该没事。
我想是数据那么大,你做的select遍历也相当昂贵
我目前正在获取特定货币对过去两年的大量加密货币每小时价格。我已经将 Sidekiq 同时用于多个硬币。
问题是,当我使用 jsonb 存储信息时,我怀疑它导致了很大的内存泄漏。但我可能错了,我的 Active Record 查询没有优化。
结果是我的 Heroku Worker 不断超过配额并关闭。
def get_2_years_of_btc_data(coin_id)
begin
time_batches = [1451606400,1458810000,1466013600,1473217200,1480420800,1487624400,1494828000,1502031600,1509235200,1516438800,1523642400]
time_batches.each do |time|
sync_hourly_btc_data(coin_id,time)
end
rescue => e
#ScrapeLog.create(error: e.message, process: "Cryptocompare - Sync Coin Prices", resource: "coin", resource_id: coin_id)
end
end
def sync_hourly_btc_data(coin_id,floored_timestamp)
coin = Coin.find(coin_id)
snap = coin.snap
response = HTTParty.get("https://min-api.cryptocompare.com/data/histohour?fsym=#{coin.ticker}&aggregate=1&tsym=BTC&limit=2000&toTs=#{floored_timestamp}")
json = JSON.parse(response.body)
data = json["Data"]
if snap.btc_counter_cache < 1
snap.to_btc = data
else
new_data = data.select {|data| data["time"] > snap.btc_to_ts}
snap.to_btc = snap.to_btc + new_data
end
snap.btc_from_ts = snap.to_btc.first["time"]
snap.btc_to_ts = snap.to_btc.last["time"]
snap.coin.real_price_btc = snap.to_btc.last["close"]
snap.btc_counter_cache = snap.to_btc.size
snap.save
end
Snaps是存储每个硬币价格信息的table,to_btc是jsonb存储所有数据的列。
我需要帮助来了解这是一个常见的 jsonb 问题,当它的大小增加或我的 Active Record 查询效率低下时。
谢谢!
这里的问题似乎不是 jsonb。我假设所提供的代码是实际的工作人员,所以我在这里的第一遍是将工作人员 per 时间批次排入队列。您目前执行此操作的方式似乎必须将所有 API 响应保存在内存中。
因此,如果您在每个时间批次中排队 job/worker,您可以单独处理每个响应 - 考虑到工作人员之间的一些退避(排队到 运行 2 分钟左右),您应该没事。
我想是数据那么大,你做的select遍历也相当昂贵