rredis 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.autotest +23 -0
  2. data/.gemtest +0 -0
  3. data/.rspec +2 -0
  4. data/CHANGELOG.md +3 -0
  5. data/Gemfile +18 -0
  6. data/Gemfile.lock +68 -0
  7. data/History.txt +6 -0
  8. data/Manifest.txt +40 -0
  9. data/README.md +143 -0
  10. data/Rakefile +34 -0
  11. data/benchmark/default.rb +62 -0
  12. data/benchmark/pipeline.rb +57 -0
  13. data/bin/rredis_server +7 -0
  14. data/config.ru +5 -0
  15. data/lib/lua/get.lua +74 -0
  16. data/lib/lua/store.lua +170 -0
  17. data/lib/rredis.rb +61 -0
  18. data/lib/rredis/server.rb +63 -0
  19. data/lib/rredis/web/assets/javascripts/application.js +3 -0
  20. data/lib/rredis/web/assets/javascripts/main.js +97 -0
  21. data/lib/rredis/web/assets/javascripts/vendor/bootstrap.js +1726 -0
  22. data/lib/rredis/web/assets/javascripts/vendor/bootstrap.min.js +6 -0
  23. data/lib/rredis/web/assets/javascripts/vendor/highcharts/highcharts.js +202 -0
  24. data/lib/rredis/web/assets/javascripts/vendor/highcharts/modules/canvas-tools.js +133 -0
  25. data/lib/rredis/web/assets/javascripts/vendor/highcharts/modules/exporting.js +23 -0
  26. data/lib/rredis/web/assets/javascripts/vendor/highcharts/themes/dark-blue.js +263 -0
  27. data/lib/rredis/web/assets/javascripts/vendor/highcharts/themes/dark-green.js +263 -0
  28. data/lib/rredis/web/assets/javascripts/vendor/highcharts/themes/gray.js +262 -0
  29. data/lib/rredis/web/assets/javascripts/vendor/highcharts/themes/grid.js +95 -0
  30. data/lib/rredis/web/assets/javascripts/vendor/highcharts/themes/skies.js +89 -0
  31. data/lib/rredis/web/assets/javascripts/vendor/jquery.js +4 -0
  32. data/lib/rredis/web/assets/stylesheets/application.css +10 -0
  33. data/lib/rredis/web/assets/stylesheets/vendor/bootstrap-responsive.css +686 -0
  34. data/lib/rredis/web/assets/stylesheets/vendor/bootstrap.css +3990 -0
  35. data/lib/rredis/web/images/glyphicons-halflings-white.png +0 -0
  36. data/lib/rredis/web/images/glyphicons-halflings.png +0 -0
  37. data/lib/rredis/web/views/index.slim +7 -0
  38. data/lib/rredis/web/views/layout.slim +26 -0
  39. data/spec/rredis/get_spec.rb +47 -0
  40. data/spec/rredis/store_spec.rb +159 -0
  41. data/spec/spec_helper.rb +21 -0
  42. metadata +124 -0
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+ require 'autotest/fsevent'
5
+ # Autotest.add_hook :initialize do |at|
6
+ # at.extra_files << "../some/external/dependency.rb"
7
+ #
8
+ # at.libs << ":../some/external"
9
+ #
10
+ # at.add_exception 'vendor'
11
+ #
12
+ # at.add_mapping(/dependency.rb/) do |f, _|
13
+ # at.files_matching(/test_.*rb$/)
14
+ # end
15
+ #
16
+ # %w(TestA TestB).each do |klass|
17
+ # at.extra_class_map[klass] = "test/test_misc.rb"
18
+ # end
19
+ # end
20
+
21
+ # Autotest.add_hook :run_command do |at|
22
+ # system "rake build"
23
+ # end
File without changes
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
@@ -0,0 +1,3 @@
1
+ === 0.1.0 / 2012-06-22
2
+
3
+ First release
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source :rubygems
2
+ gem 'redis', '>=3.0.1'
3
+ gem 'slim'
4
+ gem 'sprockets'
5
+ gem 'sass'
6
+ gem 'vegas'
7
+
8
+ group :test, :development do
9
+ gem 'rspec'
10
+ gem 'simplecov', :require => false
11
+ gem 'hoe'
12
+ gem 'hoe-git'
13
+ gem 'hoe-gemspec'
14
+ gem 'hoe-bundler'
15
+ gem 'ZenTest'
16
+ gem 'autotest-fsevent'
17
+ end
18
+
@@ -0,0 +1,68 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ ZenTest (4.8.1)
5
+ autotest-fsevent (0.2.8)
6
+ sys-uname
7
+ diff-lcs (1.1.3)
8
+ ffi (1.0.11)
9
+ ffi (1.0.11-java)
10
+ hike (1.2.1)
11
+ hoe (3.0.6)
12
+ rake (~> 0.8)
13
+ hoe-bundler (1.1.0)
14
+ hoe (>= 2.2.0)
15
+ hoe-gemspec (1.0.0)
16
+ hoe (>= 2.2.0)
17
+ hoe-git (1.5.0)
18
+ hoe (>= 2.2.0)
19
+ multi_json (1.3.6)
20
+ rack (1.4.1)
21
+ rake (0.9.2.2)
22
+ redis (3.0.1)
23
+ rspec (2.10.0)
24
+ rspec-core (~> 2.10.0)
25
+ rspec-expectations (~> 2.10.0)
26
+ rspec-mocks (~> 2.10.0)
27
+ rspec-core (2.10.1)
28
+ rspec-expectations (2.10.0)
29
+ diff-lcs (~> 1.1.3)
30
+ rspec-mocks (2.10.1)
31
+ sass (3.1.19)
32
+ simplecov (0.6.4)
33
+ multi_json (~> 1.0)
34
+ simplecov-html (~> 0.5.3)
35
+ simplecov-html (0.5.3)
36
+ slim (1.2.2)
37
+ temple (~> 0.4.0)
38
+ tilt (~> 1.3.3)
39
+ sprockets (2.4.3)
40
+ hike (~> 1.2)
41
+ multi_json (~> 1.0)
42
+ rack (~> 1.0)
43
+ tilt (~> 1.1, != 1.3.0)
44
+ sys-uname (0.9.0)
45
+ ffi (>= 1.0.0)
46
+ temple (0.4.0)
47
+ tilt (1.3.3)
48
+ vegas (0.1.11)
49
+ rack (>= 1.0.0)
50
+
51
+ PLATFORMS
52
+ java
53
+ ruby
54
+
55
+ DEPENDENCIES
56
+ ZenTest
57
+ autotest-fsevent
58
+ hoe
59
+ hoe-bundler
60
+ hoe-gemspec
61
+ hoe-git
62
+ redis (>= 3.0.1)
63
+ rspec
64
+ sass
65
+ simplecov
66
+ slim
67
+ sprockets
68
+ vegas
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2012-03-28
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
@@ -0,0 +1,40 @@
1
+ .autotest
2
+ .rspec
3
+ CHANGELOG.md
4
+ Gemfile
5
+ Gemfile.lock
6
+ History.txt
7
+ Manifest.txt
8
+ README.md
9
+ Rakefile
10
+ benchmark/default.rb
11
+ benchmark/pipeline.rb
12
+ bin/rredis_server
13
+ config.ru
14
+ lib/lua/get.lua
15
+ lib/lua/store.lua
16
+ lib/rredis.rb
17
+ lib/rredis/server.rb
18
+ lib/rredis/web/assets/javascripts/application.js
19
+ lib/rredis/web/assets/javascripts/main.js
20
+ lib/rredis/web/assets/javascripts/vendor/bootstrap.js
21
+ lib/rredis/web/assets/javascripts/vendor/bootstrap.min.js
22
+ lib/rredis/web/assets/javascripts/vendor/highcharts/highcharts.js
23
+ lib/rredis/web/assets/javascripts/vendor/highcharts/modules/canvas-tools.js
24
+ lib/rredis/web/assets/javascripts/vendor/highcharts/modules/exporting.js
25
+ lib/rredis/web/assets/javascripts/vendor/highcharts/themes/dark-blue.js
26
+ lib/rredis/web/assets/javascripts/vendor/highcharts/themes/dark-green.js
27
+ lib/rredis/web/assets/javascripts/vendor/highcharts/themes/gray.js
28
+ lib/rredis/web/assets/javascripts/vendor/highcharts/themes/grid.js
29
+ lib/rredis/web/assets/javascripts/vendor/highcharts/themes/skies.js
30
+ lib/rredis/web/assets/javascripts/vendor/jquery.js
31
+ lib/rredis/web/assets/stylesheets/application.css
32
+ lib/rredis/web/assets/stylesheets/vendor/bootstrap-responsive.css
33
+ lib/rredis/web/assets/stylesheets/vendor/bootstrap.css
34
+ lib/rredis/web/images/glyphicons-halflings-white.png
35
+ lib/rredis/web/images/glyphicons-halflings.png
36
+ lib/rredis/web/views/index.slim
37
+ lib/rredis/web/views/layout.slim
38
+ spec/rredis/get_spec.rb
39
+ spec/rredis/store_spec.rb
40
+ spec/spec_helper.rb
@@ -0,0 +1,143 @@
1
+ ## RReDis
2
+
3
+ https://github.com/dsander/RReDis
4
+
5
+ RReDis is a round robin database backed by redis. It uses the brand new lua scripting feature of redis 2.6.
6
+
7
+
8
+ ## Getting started
9
+
10
+ Install the gem
11
+
12
+ gem install rredis
13
+
14
+
15
+ Store some metrics
16
+
17
+ require 'rredis'
18
+ rrd = RReDis.new
19
+
20
+ # We start two hours in the past
21
+ start = (Time.now-(3600*2)).to_i
22
+
23
+ # We pretend to update the data every 10 seconds for two hours
24
+ (2*3600/10).times do |step|
25
+ rrd.store "example", start+step*10, rand(100)
26
+ end
27
+
28
+ Fetch data from RReDis
29
+
30
+ require 'rredis'
31
+ rrd = RReDis.new
32
+
33
+ # Get the data from 5 minutes ago until now
34
+ puts rrd.get('example', Time.now-300, Time.now).inspect
35
+ # Get the data from one hour ago until 55 minutes ago
36
+ puts rrd.get('example', Time.now-3600, Time.now-3300, 'min').inspect
37
+ # Get the data from two hours ago until 90 minutes ago
38
+ puts rrd.get('example', Time.now-7200, Time.now-5400, 'max').inspect
39
+ The get function takes three or four arguments:
40
+
41
+ * The metric to query
42
+ * Starting time stamp for the timespan to return
43
+ * Ending time stamp for the timespan to return
44
+ * Optional aggregation method
45
+
46
+
47
+ The array returned contains two arrays, the first one with unix timestamps of the measurements, the second one the (aggregated) values.
48
+
49
+ ## Configuration
50
+
51
+ Per default RReDis is configured to store one measurement every 10 seconds for one day (called native resolution from here on), and then aggregate the measurements for the following timespans:
52
+
53
+ * 1 week at 1 minute resolution
54
+ * 1 month at 15 minute resolution
55
+ * 1 year at 1 hour resolution
56
+
57
+ RReDis also stores the average, minima and maxima of aggregated measurements.
58
+
59
+ # Configuration format
60
+
61
+ RReDis default configuration:
62
+
63
+ {:steps=>10, :rows=>17280,
64
+ :aggregations=>["average", "min", "max"],
65
+ :rra => [ {:steps=>60, :rows=>10080, :xff=>0.5},
66
+ {:steps=>900, :rows=>2976, :xff=>0.5},
67
+ {:steps=>3600, :rows=>8760, :xff=>0.5}]}
68
+
69
+ `:steps` interval in seconds in which to store measurements
70
+
71
+ `:rows` amount of measurements to store, the timespan in seconds of the native resolution equals to `:steps`*`:rows`
72
+
73
+ `:aggregations` array of aggregations to use for this measurement, currently available: `average`, `min`, `max`, `sum`
74
+
75
+ `:rra` array of archives to store historical data
76
+
77
+
78
+ For every `:rra`:
79
+
80
+ `:steps` interval in seconds in which to aggregate the measurements of the next higher resolution
81
+
82
+ `:rows` amount of aggregations to store, the timespan in seconds of the archive equals to `:steps`*`:rows`
83
+
84
+ `:xff` the xfiles factor - determines if aggregated measurements are stored. 1.0 would require 10 of 10 measurements from the next higher resolution (either form a rra or the native resolution), 0.1 would require 1 of 10 measurements
85
+
86
+ # Modify the configuration
87
+ You can either explicitly configure a metric via the `config` method:
88
+
89
+ rrd = RReDis.new
90
+ rrd.config("metic", {:steps => 10, :rows => 3})
91
+
92
+
93
+ Or change the default configuration which will be applied to every measurement without an explicit configuration:
94
+
95
+ rrd = RReDis.new
96
+ rrd.default_config = {:steps => 10, :rows => 3}
97
+
98
+
99
+ ## Performance
100
+
101
+ Even though redis supports a lot of data types, it was clearly not made to act as a round robin database, but still with lua scripting the performance is really nice.
102
+
103
+ With the default configuration RReDis is able to handle around 2.5k updates per second (ubuntu vm with two cores of an i5 750 in virtual box running on windows), which is still amazingly fast considering the complexity of the store.lua script.
104
+
105
+ Check out the default.rb script in the benchmark directory. Here are the results of my machine:
106
+
107
+ 0.000395ms per op, 2529.6144076826317 op/s
108
+ 415.557405432s for for 1051200 inserts
109
+ 8639 stored measurements/aggregations
110
+ 156 bytes used per stored measurement
111
+ 6882960 measurements storable per gb of ram
112
+ 794 metrics storable per gb of ram
113
+ 5273285 redis commands performed
114
+ 5 redis commands performed per stored measurement
115
+
116
+ Using pipelining, we are able to determine the limits of redis itself. On my box redis can handle about 10k updates per second. A "advanced" key-value store able to run a lua script 10 thousand times a second doing about 50 thousand internal operations per second is just plain amazing.
117
+ Hats off! @antirez
118
+
119
+
120
+ ## LICENSE:
121
+
122
+ (The MIT License)
123
+
124
+ Copyright (c) 2012 Dominik Sander
125
+
126
+ Permission is hereby granted, free of charge, to any person obtaining
127
+ a copy of this software and associated documentation files (the
128
+ 'Software'), to deal in the Software without restriction, including
129
+ without limitation the rights to use, copy, modify, merge, publish,
130
+ distribute, sublicense, and/or sell copies of the Software, and to
131
+ permit persons to whom the Software is furnished to do so, subject to
132
+ the following conditions:
133
+
134
+ The above copyright notice and this permission notice shall be
135
+ included in all copies or substantial portions of the Software.
136
+
137
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
138
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
139
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
140
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
141
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
142
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
143
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,34 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ gem 'hoe', '>= 2.1.0'
5
+ require 'hoe'
6
+ require "rspec/core/rake_task"
7
+
8
+ # Hoe.plugin :compiler
9
+ # Hoe.plugin :gem_prelude_sucks
10
+ # Hoe.plugin :inline
11
+ # Hoe.plugin :racc
12
+ # Hoe.plugin :rubyforge
13
+ Hoe.plugin :git
14
+ Hoe.plugin :gemspec
15
+ Hoe.plugin :bundler
16
+ Hoe.plugin :gemcutter
17
+ Hoe.plugins.delete :rubyforge
18
+
19
+ Hoe.spec 'rredis' do
20
+ developer('Dominik Sander', 'git@dsander.de')
21
+ self.description ="RReDis - a round robin database backed by redis"
22
+ self.summary = "RReDis - dead simple monitoring and graphing round robin database using redis"
23
+
24
+ self.readme_file = 'README.md'
25
+ self.history_file = 'CHANGELOG.md'
26
+ self.extra_deps << ["redis"]
27
+ end
28
+
29
+ task :prerelease => [:clobber, :check_manifest, :test]
30
+
31
+
32
+ task :default => :spec
33
+ task :test => :spec
34
+
@@ -0,0 +1,62 @@
1
+ require 'rredis'
2
+ require 'benchmark'
3
+
4
+ r = Redis.new
5
+ r.flushall
6
+ r.config 'resetstat'
7
+
8
+ rrd = RReDis.new
9
+ memory = r.info["used_memory"].to_i
10
+ commands = r.info["total_commands_processed"].to_i
11
+
12
+ # Define who much data we want to store
13
+ days = 365
14
+ steps = 30
15
+
16
+ # Calculate the amount of measurements we need to store
17
+ day = 3600*24
18
+ start = Time.now-(day*days)
19
+ n = day*days/steps
20
+
21
+ # We regenerate the data to just measure the inserts
22
+ data = []
23
+ n.times do |i|
24
+ data << [(start+(i*steps)).to_f, rand(100_0)]
25
+ end
26
+
27
+ # Do the actual work
28
+ res = Benchmark.realtime do
29
+ #rrd.pipelined do
30
+ n.times do |i|
31
+ d = data.pop
32
+ rrd.store "bench", d[0], d[1]
33
+ end
34
+ #end
35
+ end
36
+
37
+ puts "#{res/n}ms per op, #{1/(res/n)} op/s"
38
+
39
+ # Calculate the amount of measurements we actually stored
40
+ stored_meassuremnts = 0
41
+ r.keys("rrd_bench*").each do |k|
42
+ next if k.include? 'config'
43
+ if !k.include? 'min' and !k.include? 'max'
44
+ stored_meassuremnts += r.zcard(k)
45
+ end
46
+ end
47
+
48
+ used_memory = r.info["used_memory"].to_i - memory
49
+ commands_processed = r.info["total_commands_processed"].to_i - commands
50
+
51
+ bytes_per_measurement = used_memory/stored_meassuremnts
52
+ stored_measuremnts_per_gb = (1*1024*1024*1024).to_f/bytes_per_measurement
53
+ stored_metrics_per_gb = (1*1024*1024*1024).to_f/used_memory
54
+ commands_per_measurement = commands_processed/n
55
+
56
+ puts "#{res}s for for #{n} inserts"
57
+ puts "#{stored_meassuremnts} stored measurements/aggregations"
58
+ puts "#{bytes_per_measurement} bytes used per stored measurement"
59
+ puts "#{stored_measuremnts_per_gb.to_i} measurements storable per gb of ram"
60
+ puts "#{stored_metrics_per_gb.to_i} metrics storable per gb of ram"
61
+ puts "#{commands_processed} redis commands performed"
62
+ puts "#{commands_per_measurement} redis commands performed per stored measurement"
@@ -0,0 +1,57 @@
1
+ require 'rredis'
2
+ require 'benchmark'
3
+
4
+ r = Redis.new
5
+ r.flushall
6
+ r.config 'resetstat'
7
+
8
+ rrd = RReDis.new
9
+ memory = r.info["used_memory"].to_i
10
+ commands = r.info["total_commands_processed"].to_i
11
+
12
+ # Define who much data we want to store
13
+ days = 32
14
+ steps = 30
15
+
16
+ # Calculate the amount of measurements we need to store
17
+ day = 3600*24
18
+ start = Time.now-(day*days)
19
+ n = day*days/steps
20
+
21
+ # We regenerate the data to just measure the inserts
22
+ data = []
23
+ n.times do |i|
24
+ data << [(start+(i*steps)).to_f, rand(100_0)]
25
+ end
26
+
27
+ # Do the actual work
28
+ res = Benchmark.realtime do
29
+ rrd.pipelined do
30
+ n.times do |i|
31
+ d = data.pop
32
+ rrd.store "bench", d[0], d[1]
33
+ end
34
+ end
35
+ end
36
+
37
+ puts "#{res/n}ms per op, #{1/(res/n)} op/s"
38
+
39
+ # Calculate the amount of measurements we actually stored
40
+ stored_meassuremnts = 0
41
+ r.keys("rrd_bench*").each do |k|
42
+ next if k.include? 'config'
43
+ if !k.include? 'min' and !k.include? 'max'
44
+ stored_meassuremnts += r.zcard(k)
45
+ end
46
+ end
47
+
48
+ used_memory = r.info["used_memory"].to_i - memory
49
+ commands_processed = r.info["total_commands_processed"].to_i - commands
50
+
51
+ bytes_per_measurement = used_memory/stored_meassuremnts
52
+ stored_measuremnts_per_gb = (1*1024*1024*1024).to_f/bytes_per_measurement
53
+ stored_metrics_per_gb = (1*1024*1024*1024).to_f/used_memory
54
+ commands_per_measurement = commands_processed/n
55
+
56
+ puts "#{res}s for for #{n} inserts"
57
+ puts "#{commands_processed/res} redis commands per second"