From 4436ef7553b19daf6c2566a3dcb608b741a3b28c Mon Sep 17 00:00:00 2001 From: Paul Bellamy Date: Sat, 16 Apr 2011 23:24:12 +0100 Subject: [PATCH 1/2] Added sorted-set variant to allow for inserting historical data --- sorted-set-example.rb | 33 +++++++++++++++++++++++++++++++++ sorted-set.rb | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 sorted-set-example.rb create mode 100644 sorted-set.rb diff --git a/sorted-set-example.rb b/sorted-set-example.rb new file mode 100644 index 0000000..8abcea6 --- /dev/null +++ b/sorted-set-example.rb @@ -0,0 +1,33 @@ +require 'rubygems' +require 'redis' +require './sorted-set' + +# To show the lib implementation here we use a timestep of just one second. +# Then we sample every 0.1 seconds, producing on average 10 samples per key. +# This way we should how multi-key range queries are working. +ts = RedisTimeSeries.new("test",1,Redis.new) + +now = Time.now.to_f +puts "Adding data points: " +(0..300).each{|i| + print "#{i} " + STDOUT.flush + time = (now+(i/10.0)) + ts.add({:time => time, :data => i.to_s}, time) +} +puts "" + +# Get the second in the middle of our sampling. +begin_time = now+1 +end_time = now+2 +puts "\nGet range from #{begin_time} to #{end_time}" + +ts.fetch_range(begin_time,end_time).each{|record| + puts "Record time #{record[:time]}, data #{record[:data]}" +} + +# Show API to get a single timestep +puts "\nGet a single timestep near #{begin_time}" +ts.fetch_timestep(begin_time).each{|record| + puts "Record time #{record[:time]}, data #{record[:data]}" +} diff --git a/sorted-set.rb b/sorted-set.rb new file mode 100644 index 0000000..f251ba4 --- /dev/null +++ b/sorted-set.rb @@ -0,0 +1,42 @@ +require 'base64' + +class RedisTimeSeries + def initialize(prefix,timestep,redis) + @prefix = prefix + @timestep = timestep + @redis = redis + end + + def normalize_time(t) + t = t.to_i + t - (t % @timestep) + end + + def getkey(t) + "ts:#{@prefix}:#{normalize_time t}" + end + + def add(data,timestamp=nil,marshal=true) + timestamp ||= Time.now.to_f + data = marshal ? Marshal.dump(data) : data + @redis.zadd(getkey(timestamp), timestamp, data) + end + + def fetch_range(begin_time,end_time,marshal=true) + begin_time = begin_time.to_f + end_time = end_time.to_f + result = (0..((end_time - begin_time) / @timestep)).collect do |i| + key = getkey(begin_time + (i*@timestep)) + + r = @redis.zrangebyscore(key, begin_time.to_f,end_time.to_f) + marshal ? r.collect{|elem| Marshal.load(elem) } : r + end + result.flatten + end + + def fetch_timestep(time, marshal=true) + t = time.to_f + r = @redis.zrangebyscore(getkey(time), t, t) + marshal ? r.collect{|elem| Marshal.load(elem) } : r + end +end From 9a0964d688ea2cac29b6c3cc4eb2c2164700c48f Mon Sep 17 00:00:00 2001 From: Paul Bellamy Date: Sat, 16 Apr 2011 23:28:55 +0100 Subject: [PATCH 2/2] Renaming sorted-set file --- sorted-set.rb => redis-timeseries-sorted-set.rb | 0 sorted-set-example.rb | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename sorted-set.rb => redis-timeseries-sorted-set.rb (100%) diff --git a/sorted-set.rb b/redis-timeseries-sorted-set.rb similarity index 100% rename from sorted-set.rb rename to redis-timeseries-sorted-set.rb diff --git a/sorted-set-example.rb b/sorted-set-example.rb index 8abcea6..537d6d9 100644 --- a/sorted-set-example.rb +++ b/sorted-set-example.rb @@ -1,6 +1,6 @@ require 'rubygems' require 'redis' -require './sorted-set' +require './redis-timeseries-sorted-set' # To show the lib implementation here we use a timestep of just one second. # Then we sample every 0.1 seconds, producing on average 10 samples per key.