SlideShare a Scribd company logo
1 of 46
Lean & Mean Tokyo Cabinet Recipes Ilya Grigorik @igrigorik
postrank.com/topic/ruby The slides… Twitter My blog
MikioHirabayashi Yukihiro Matsumoto
MikioHirabayashi Yukihiro Matsumoto ???
Hashtable Berkeley DB, DBM, QDB, TDB… B-Tree Table Key-Value with duplicates & ordering 3. Fixed-length  An in memory array.. No hashing. 4. Table Engine Schemaless, indexes & queries Choose your engine
gem install rufus-tokyo require 'rubygems'require 'rufus/tokyo'db = Rufus::Tokyo::Cabinet.new('data.tch')db['nada'] = 'surf'p db['nada'] # => 'surf'p db['lost'] # => nildb.close TC: Hashtable
require 'rubygems'require 'rufus/tokyo'db = Rufus::Tokyo::Cabinet.new('data.tch')db['nada'] = 'surf'p db['nada'] # => 'surf'p db['lost'] # => nildb.close ~ Ruby Hash TC: Hashtable
require 'rubygems'require 'rufus/tokyo't = Rufus::Tokyo::Table.new('table.tct')t['pk0'] = { 'name' => 'alfred', 'age' => '22' }t['pk1'] = { 'name' => 'bob', 'age' => '18', 'sex' => 'male' }t['pk2'] = { 'name' => 'charly', 'age' => '45' }t['pk4'] = { 'name' => 'ephrem', 'age' => '32' }p t.query { |q|q.add_condition 'age', :numge, '32'q.order_by 'age'}# => [ {"name"=>"ephrem", :pk=>"pk4", age"=>"32"},#      {"name"=>"charly", :pk=>"pk2", "age"=>"45"} ]t.close Table Engine TC: Table Engine
require 'rubygems'require 'rufus/tokyo't = Rufus::Tokyo::Table.new('table.tct')t['pk0'] = { 'name' => 'alfred', 'age' => '22' }t['pk1'] = { 'name' => 'bob', 'age' => '18', 'sex' => 'male' }t['pk2'] = { 'name' => 'charly', 'age' => '45' }t['pk4'] = { 'name' => 'ephrem', 'age' => '32' }p t.query { |q|q.add_condition'age', :numge, '32'q.order_by'age'}# => [ {"name"=>"ephrem", :pk=>"pk4", age"=>"32"},#      {"name"=>"charly", :pk=>"pk2", "age"=>"45"} ]t.close age > 32 order by age TC: Table Engine
p t.size# => 0t.transactiondo  t['pk0'] = { 'name' => 'alfred', 'age' => '22' }  t['pk1'] = { 'name' => 'bob', 'age' => '18' }t.abortendp t.size# => 0 Uh oh… TC: Table Engine Transactions
Network Embedded
require "rubygems"require "rest_client"# Interacting with TokyoTyrant via RESTful HTTP!db = RestClient::Resource.new("http://localhost:1978")db["key"].put "value 1"  # insert via HTTPdb["key"].put "value 2"  # update via HTTPputs db["key"].get       # get via HTTP# => "value 2"db["key"].delete         # delete via HTTPputs db["key"].get rescue RestClient::ResourceNotFound RESTful Tokyo Tyrant
require "rubygems"require "rest_client"# Interacting with TokyoTyrant via HTTP!db = RestClient::Resource.new("http://localhost:1978")db["key"].put "value 1"# insert via HTTPdb["key"].put "value 2"# update via HTTPputs db["key"].get       # get via HTTP# => "value 2"db["key"].delete         # delete via HTTPputs db["key"].get rescueRestClient::ResourceNotFound RESTful Tokyo Tyrant Awesome.
“Recently, I sophisticated Hanami and the Sumida River in a houseboat, I was sad that day and not even a minute yet mikio bloom …” … so I added Lua scripting to Tyrant. http://alpha.mixi.co.jp/blog/?p=236
“Powerful, fast, lightweight, embeddable scripting language” ,[object Object]
  Everything is an associatiave array
  Dynamically typed
  Interpreted bytecode
  Garbage collectionGZIP(Source + Docs + Examples) = 212 Kb What is Lua? It’s like Ruby.. except it’s not. Fast + Lightweight = Great for embedded apps
+ CREATE FUNCTION json_members RETURNS STRING SONAME 'lib_mysqludf_json.so';  SELECT json_object(customer_id, first_name) FROM customer; +---------------------------------------------------+ | customer                                                   | +---------------------------------------------------+ | {customer_id:1,first_name:"MARY"}   | +---------------------------------------------------+ Extending the Database? MySQL User Defined Functions JSON Response http://www.mysqludf.org/lib_mysqludf_json/index.php
= C/C++  + + = Lua TC+Lua? Why? To make our lives easier, and more fun! Easy to learn & easy to extend!
Lua extension within Tokyo Cabinet _put(key, value) _putkeep(key, value) _putcat(key, value) _rnum()_vanish() _mapreduce(mapper, reducer, keys) _out(key) _get(key) _vsiz(key) _addint(key, value) TC + Lua Extensions  Request / Response data-flow http://tokyocabinet.sourceforge.net/tyrantdoc/#luaext
-- -- echo.lua-- function echo(key, value)return key .. ":" .. valueend [ilya@igvita] >ttserver-ext echo.lua test.tch  [ilya@igvita] >tcrmgrextlocalhostechofoo bar  foo:bar require 'rubygems'require 'rufus/tokyo/tyrant' # sudo gem install rufus-tokyot = Rufus::Tokyo::Tyrant.new('127.0.0.1', 1978)puts t.ext(:echo, 'hello', 'world')t.close Lua + TC Echo Server
-- -- echo.lua-- function echo(key, value)return key .. ":" .. valueend [ilya@igvita] >ttserver-ext echo.lua test.tch  [ilya@igvita] >tcrmgrextlocalhostechofoo bar  foo:bar require 'rubygems'require 'rufus/tokyo/tyrant' # sudo gem install rufus-tokyot = Rufus::Tokyo::Tyrant.new('127.0.0.1', 1978)puts t.ext(:echo, 'hello', 'world')t.close Lua + TC Echo Server
-- -- echo.lua-- function echo(key, value)return key .. ":" .. valueend [ilya@igvita] >ttserver-ext echo.lua test.tch  [ilya@igvita] >tcrmgrextlocalhostechofoo bar  foo:bar require 'rubygems'require 'rufus/tokyo/tyrant'# sudo gem install rufus-tokyot = Rufus::Tokyo::Tyrant.new('127.0.0.1', 1978)puts t.ext(:echo, 'hello', 'world')t.close Lua + TC Echo Server
-- -- incr.lua-- function incr (key, i)i = tonumber(i)ifnotithenreturnnilend  local old = tonumber(_get(key))  if old theni = old + i  end  if not _put(key, i) then    return nil  end  return iend Verify input Implementing INCR in Lua+TC
-- -- incr.lua-- function incr (key, i)i = tonumber(i)ifnotithenreturnnilend  local old = tonumber(_get(key))if old theni = old + iend  if not _put(key, i) then    return nil  end  return iend Get old value & increment it Implementing INCR in Lua+TC
-- -- incr.lua-- function incr (key, i)i = tonumber(i)ifnotithenreturnnilend  local old = tonumber(_get(key))if old theni = old + iendifnot _put(key, i) thenreturnnilendreturniend Save new value Implementing INCR in Lua+TC
[ilya@igvita] >ttserver-ext incr.lua test.tch  [ilya@igvita] >tcrmgrextlocalhostincrkeyname 1                        1 [ilya@igvita] >tcrmgrextlocalhostincrkeyname 5                        6 require 'rubygems'require 'rufus/tokyo/tyrant' # sudo gem install rufus-tokyot = Rufus::Tokyo::Tyrant.new('127.0.0.1', 1978)5.times do  puts t.ext(:incr, 'my-counter', 2).to_iendt.close Implementing INCR in Lua+TC
[ilya@igvita] >ttserver-ext incr.lua test.tch  [ilya@igvita] >tcrmgrextlocalhostincrkeyname 1                        1 [ilya@igvita] >tcrmgrextlocalhostincrkeyname 5                        6 require 'rubygems'require 'rufus/tokyo/tyrant'# sudo gem install rufus-tokyot = Rufus::Tokyo::Tyrant.new('127.0.0.1', 1978)5.times do  puts t.ext(:incr, 'my-counter', 2).to_iendt.close Implementing INCR in Lua+TC
Lua + TC = Database Kung-fu TTL, Sets & Caching
“Redis as a data structures server, it is not just another key-value DB”
functionset_append(key, value)  local stream = _get(key)ifnot stream then    _put(key, value)else    local set_len = _set_len(stream)    if set_len == 1 then      if stream == value then return nil endelseifset_len > 1 then      for _, element in ipairs(_split(stream, SEP)) do        if element == value then return nil end      end    end    if not _putcat(key, SEP .. value) then      return nil    endendreturn valueend Empty Set Implementing Set operations in TC
functionset_append(key, value)  local stream = _get(key)ifnot stream then    _put(key, value)else    local set_len = _set_len(stream)ifset_len == 1 thenif stream == value thenreturnnilendelseifset_len > 1 thenfor _, element inipairs(_split(stream, SEP)) doif element == value thenreturnnilendendendifnot _putcat(key, SEP .. value) thenreturnnilendendreturn valueend Append key if unique Implementing Set operations in TC
=                ? + [ilya@igvita] >ttserver-ext set.lua test.tch  [ilya@igvita] >tcrmgrextlocalhostset_append key 1 [ilya@igvita] >tcrmgrextlocalhostset_appendkey 2 [ilya@igvita] >tcrmgrextlocalhostset_append key 1 [ilya@igvita] >tcrmgrextlocalhostset_getkey                        1                        2 set_length set_get set_delete set_append Implementing Set operations in TC
“memcachedis a general-purpose distributed memory caching system that is used by many top sites on the internet”      Key                Value                Time             key1 value1 10 key2 value2 20 Time = 15 key2 value2 30 Implementing TTL’s in TC
DELETE where x > Time.now function expire()   local args = {}   local cdate = string.format("%d", _time())table.insert(args, "addcondxNUMLE" .. cdate)table.insert(args, "out")   local res = _misc("search", args)ifnot res then      _log("expiration was failed")end   print("rnum=" .. _rnum() .. " size=" .. _size())end Expiring Records with Lua
=                ? + [ilya@igvita] >ttserver-ext expire.lua -extpc expire 5 "casket.tct#idx=x:dec"  Invoke “expire” command every 5 seconds Table database, with index on expiry column (x) Implementing Set operations in TC
[ilya@igvita] >ttserver -ext session-trail.lua test.tch [ilya@igvita] >tcrmgrextlocalhostadd 1 123 [ilya@igvita] >tcrmgrextlocalhostadd 1 256 [ilya@igvita] >tcrmgrextlocalhostadd 1 987 [ilya@igvita] >tcrmgrextlocalhostadd 2 987 [ilya@igvita] >tcrmgrextlocalhostlist 1 987	1247008220                        256	1247008216                        123	1247008123  Session-trail with Lua Timestamped  session trail
Lua + TC = Map Reduce! Just for kicks.
_out(key) _get(key) _vsiz(key) _addint(key, value) _mapreduce(mapper, reducer, keys) Executing MR jobs within Tokyo Cabinet

More Related Content

What's hot

The Ring programming language version 1.8 book - Part 45 of 202
The Ring programming language version 1.8 book - Part 45 of 202The Ring programming language version 1.8 book - Part 45 of 202
The Ring programming language version 1.8 book - Part 45 of 202Mahmoud Samir Fayed
 
Euro python2011 High Performance Python
Euro python2011 High Performance PythonEuro python2011 High Performance Python
Euro python2011 High Performance PythonIan Ozsvald
 
JFokus 50 new things with java 8
JFokus 50 new things with java 8JFokus 50 new things with java 8
JFokus 50 new things with java 8José Paumard
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2José Paumard
 
Implementing pattern-matching in JavaScript (short version)
Implementing pattern-matching in JavaScript (short version)Implementing pattern-matching in JavaScript (short version)
Implementing pattern-matching in JavaScript (short version)François-Guillaume Ribreau
 
Use PEG to Write a Programming Language Parser
Use PEG to Write a Programming Language ParserUse PEG to Write a Programming Language Parser
Use PEG to Write a Programming Language ParserYodalee
 
Java SE 8 for Java EE developers
Java SE 8 for Java EE developersJava SE 8 for Java EE developers
Java SE 8 for Java EE developersJosé Paumard
 
Bringing modern PHP development to IBM i (ZendCon 2016)
Bringing modern PHP development to IBM i (ZendCon 2016)Bringing modern PHP development to IBM i (ZendCon 2016)
Bringing modern PHP development to IBM i (ZendCon 2016)James Titcumb
 
50 new things we can do with Java 8
50 new things we can do with Java 850 new things we can do with Java 8
50 new things we can do with Java 8José Paumard
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Masahiro Nagano
 
On UnQLite
On UnQLiteOn UnQLite
On UnQLitecharsbar
 
Python高级编程(二)
Python高级编程(二)Python高级编程(二)
Python高级编程(二)Qiangning Hong
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl TechniquesDave Cross
 
Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.Workhorse Computing
 
Python在豆瓣的应用
Python在豆瓣的应用Python在豆瓣的应用
Python在豆瓣的应用Qiangning Hong
 
PL/Perl - New Features in PostgreSQL 9.0 201012
PL/Perl - New Features in PostgreSQL 9.0 201012PL/Perl - New Features in PostgreSQL 9.0 201012
PL/Perl - New Features in PostgreSQL 9.0 201012Tim Bunce
 
Realtime Analytics Using MongoDB, Python, Gevent, and ZeroMQ
Realtime Analytics Using MongoDB, Python, Gevent, and ZeroMQRealtime Analytics Using MongoDB, Python, Gevent, and ZeroMQ
Realtime Analytics Using MongoDB, Python, Gevent, and ZeroMQRick Copeland
 

What's hot (20)

The Ring programming language version 1.8 book - Part 45 of 202
The Ring programming language version 1.8 book - Part 45 of 202The Ring programming language version 1.8 book - Part 45 of 202
The Ring programming language version 1.8 book - Part 45 of 202
 
Euro python2011 High Performance Python
Euro python2011 High Performance PythonEuro python2011 High Performance Python
Euro python2011 High Performance Python
 
JFokus 50 new things with java 8
JFokus 50 new things with java 8JFokus 50 new things with java 8
JFokus 50 new things with java 8
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2
 
Test::Base
Test::BaseTest::Base
Test::Base
 
Unit Testing Lots of Perl
Unit Testing Lots of PerlUnit Testing Lots of Perl
Unit Testing Lots of Perl
 
Implementing pattern-matching in JavaScript (short version)
Implementing pattern-matching in JavaScript (short version)Implementing pattern-matching in JavaScript (short version)
Implementing pattern-matching in JavaScript (short version)
 
Use PEG to Write a Programming Language Parser
Use PEG to Write a Programming Language ParserUse PEG to Write a Programming Language Parser
Use PEG to Write a Programming Language Parser
 
Java SE 8 for Java EE developers
Java SE 8 for Java EE developersJava SE 8 for Java EE developers
Java SE 8 for Java EE developers
 
Effective Benchmarks
Effective BenchmarksEffective Benchmarks
Effective Benchmarks
 
Bringing modern PHP development to IBM i (ZendCon 2016)
Bringing modern PHP development to IBM i (ZendCon 2016)Bringing modern PHP development to IBM i (ZendCon 2016)
Bringing modern PHP development to IBM i (ZendCon 2016)
 
50 new things we can do with Java 8
50 new things we can do with Java 850 new things we can do with Java 8
50 new things we can do with Java 8
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015
 
On UnQLite
On UnQLiteOn UnQLite
On UnQLite
 
Python高级编程(二)
Python高级编程(二)Python高级编程(二)
Python高级编程(二)
 
Advanced Perl Techniques
Advanced Perl TechniquesAdvanced Perl Techniques
Advanced Perl Techniques
 
Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.Object Trampoline: Why having not the object you want is what you need.
Object Trampoline: Why having not the object you want is what you need.
 
Python在豆瓣的应用
Python在豆瓣的应用Python在豆瓣的应用
Python在豆瓣的应用
 
PL/Perl - New Features in PostgreSQL 9.0 201012
PL/Perl - New Features in PostgreSQL 9.0 201012PL/Perl - New Features in PostgreSQL 9.0 201012
PL/Perl - New Features in PostgreSQL 9.0 201012
 
Realtime Analytics Using MongoDB, Python, Gevent, and ZeroMQ
Realtime Analytics Using MongoDB, Python, Gevent, and ZeroMQRealtime Analytics Using MongoDB, Python, Gevent, and ZeroMQ
Realtime Analytics Using MongoDB, Python, Gevent, and ZeroMQ
 

Viewers also liked

Tokyo Cabinet
Tokyo CabinetTokyo Cabinet
Tokyo Cabinetehuard
 
Tokyo Cabinet & Tokyo Tyrant
Tokyo Cabinet & Tokyo TyrantTokyo Cabinet & Tokyo Tyrant
Tokyo Cabinet & Tokyo Tyrant輝 子安
 
Introduction to Tokyo Products
Introduction to Tokyo ProductsIntroduction to Tokyo Products
Introduction to Tokyo ProductsMikio Hirabayashi
 

Viewers also liked (6)

tokyotalk
tokyotalktokyotalk
tokyotalk
 
Tokyo Cabinet
Tokyo CabinetTokyo Cabinet
Tokyo Cabinet
 
Tokyocabinet
TokyocabinetTokyocabinet
Tokyocabinet
 
Tokyo Cabinet & Tokyo Tyrant
Tokyo Cabinet & Tokyo TyrantTokyo Cabinet & Tokyo Tyrant
Tokyo Cabinet & Tokyo Tyrant
 
Tokyo Cabinet
Tokyo CabinetTokyo Cabinet
Tokyo Cabinet
 
Introduction to Tokyo Products
Introduction to Tokyo ProductsIntroduction to Tokyo Products
Introduction to Tokyo Products
 

Similar to Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09

Characterset
CharactersetCharacterset
CharactersetHari K T
 
Python And GIS - Beyond Modelbuilder And Pythonwin
Python And GIS - Beyond Modelbuilder And PythonwinPython And GIS - Beyond Modelbuilder And Pythonwin
Python And GIS - Beyond Modelbuilder And PythonwinChad Cooper
 
Key Value Storage Systems ... and Beyond ... with Python
Key Value Storage Systems ... and Beyond ... with PythonKey Value Storage Systems ... and Beyond ... with Python
Key Value Storage Systems ... and Beyond ... with PythonIan Lewis
 
Introduction To Moco
Introduction To MocoIntroduction To Moco
Introduction To MocoNaoya Ito
 
Maker All - Executive Presentation
Maker All - Executive PresentationMaker All - Executive Presentation
Maker All - Executive PresentationDiogoFalcao
 
SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)Robert Swisher
 
Cplusplus
CplusplusCplusplus
Cplusplusdancey
 
How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012Connor McDonald
 
STL ALGORITHMS
STL ALGORITHMSSTL ALGORITHMS
STL ALGORITHMSfawzmasood
 
Python - Getting to the Essence - Points.com - Dave Park
Python - Getting to the Essence - Points.com - Dave ParkPython - Getting to the Essence - Points.com - Dave Park
Python - Getting to the Essence - Points.com - Dave Parkpointstechgeeks
 
Micro-ORM Introduction - Don't overcomplicate
Micro-ORM Introduction - Don't overcomplicateMicro-ORM Introduction - Don't overcomplicate
Micro-ORM Introduction - Don't overcomplicateKiev ALT.NET
 
What's new in Rails 2?
What's new in Rails 2?What's new in Rails 2?
What's new in Rails 2?brynary
 
Short Intro to PHP and MySQL
Short Intro to PHP and MySQLShort Intro to PHP and MySQL
Short Intro to PHP and MySQLJussi Pohjolainen
 
Advance C++notes
Advance C++notesAdvance C++notes
Advance C++notesRajiv Gupta
 

Similar to Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09 (20)

Characterset
CharactersetCharacterset
Characterset
 
Python And GIS - Beyond Modelbuilder And Pythonwin
Python And GIS - Beyond Modelbuilder And PythonwinPython And GIS - Beyond Modelbuilder And Pythonwin
Python And GIS - Beyond Modelbuilder And Pythonwin
 
Real
RealReal
Real
 
C to perl binding
C to perl bindingC to perl binding
C to perl binding
 
Key Value Storage Systems ... and Beyond ... with Python
Key Value Storage Systems ... and Beyond ... with PythonKey Value Storage Systems ... and Beyond ... with Python
Key Value Storage Systems ... and Beyond ... with Python
 
Introduction To Moco
Introduction To MocoIntroduction To Moco
Introduction To Moco
 
Maker All - Executive Presentation
Maker All - Executive PresentationMaker All - Executive Presentation
Maker All - Executive Presentation
 
SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)
 
Cplusplus
CplusplusCplusplus
Cplusplus
 
Master tuning
Master   tuningMaster   tuning
Master tuning
 
C++ programming
C++ programmingC++ programming
C++ programming
 
How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012How to tune a query - ODTUG 2012
How to tune a query - ODTUG 2012
 
How we build Vox
How we build VoxHow we build Vox
How we build Vox
 
STL ALGORITHMS
STL ALGORITHMSSTL ALGORITHMS
STL ALGORITHMS
 
Osol Pgsql
Osol PgsqlOsol Pgsql
Osol Pgsql
 
Python - Getting to the Essence - Points.com - Dave Park
Python - Getting to the Essence - Points.com - Dave ParkPython - Getting to the Essence - Points.com - Dave Park
Python - Getting to the Essence - Points.com - Dave Park
 
Micro-ORM Introduction - Don't overcomplicate
Micro-ORM Introduction - Don't overcomplicateMicro-ORM Introduction - Don't overcomplicate
Micro-ORM Introduction - Don't overcomplicate
 
What's new in Rails 2?
What's new in Rails 2?What's new in Rails 2?
What's new in Rails 2?
 
Short Intro to PHP and MySQL
Short Intro to PHP and MySQLShort Intro to PHP and MySQL
Short Intro to PHP and MySQL
 
Advance C++notes
Advance C++notesAdvance C++notes
Advance C++notes
 

More from Ilya Grigorik

Pagespeed what, why, and how it works
Pagespeed   what, why, and how it worksPagespeed   what, why, and how it works
Pagespeed what, why, and how it worksIlya Grigorik
 
Making the web fast(er) - RailsConf 2012
Making the web fast(er) - RailsConf 2012Making the web fast(er) - RailsConf 2012
Making the web fast(er) - RailsConf 2012Ilya Grigorik
 
0-60 with Goliath: High performance web services
0-60 with Goliath: High performance web services0-60 with Goliath: High performance web services
0-60 with Goliath: High performance web servicesIlya Grigorik
 
0-60 with Goliath: Building High Performance Ruby Web-Services
0-60 with Goliath: Building High Performance Ruby Web-Services0-60 with Goliath: Building High Performance Ruby Web-Services
0-60 with Goliath: Building High Performance Ruby Web-ServicesIlya Grigorik
 
Ruby in the Browser - RubyConf 2011
Ruby in the Browser - RubyConf 2011Ruby in the Browser - RubyConf 2011
Ruby in the Browser - RubyConf 2011Ilya Grigorik
 
Intelligent Ruby + Machine Learning
Intelligent Ruby + Machine LearningIntelligent Ruby + Machine Learning
Intelligent Ruby + Machine LearningIlya Grigorik
 
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9Ilya Grigorik
 
No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010Ilya Grigorik
 
Real-time Ruby for the Real-time Web
Real-time Ruby for the Real-time WebReal-time Ruby for the Real-time Web
Real-time Ruby for the Real-time WebIlya Grigorik
 
Ruby C10K: High Performance Networking - RubyKaigi '09
Ruby C10K: High Performance Networking - RubyKaigi '09Ruby C10K: High Performance Networking - RubyKaigi '09
Ruby C10K: High Performance Networking - RubyKaigi '09Ilya Grigorik
 
Leveraging Social Media - Strategies & Tactics - PostRank
Leveraging Social Media - Strategies & Tactics - PostRankLeveraging Social Media - Strategies & Tactics - PostRank
Leveraging Social Media - Strategies & Tactics - PostRankIlya Grigorik
 
Ruby Proxies for Scale, Performance, and Monitoring
Ruby Proxies for Scale, Performance, and MonitoringRuby Proxies for Scale, Performance, and Monitoring
Ruby Proxies for Scale, Performance, and MonitoringIlya Grigorik
 
Building Mini Google in Ruby
Building Mini Google in RubyBuilding Mini Google in Ruby
Building Mini Google in RubyIlya Grigorik
 
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.comRuby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.comIlya Grigorik
 
Event Driven Architecture - MeshU - Ilya Grigorik
Event Driven Architecture - MeshU - Ilya GrigorikEvent Driven Architecture - MeshU - Ilya Grigorik
Event Driven Architecture - MeshU - Ilya GrigorikIlya Grigorik
 
Taming The RSS Beast
Taming The  RSS  BeastTaming The  RSS  Beast
Taming The RSS BeastIlya Grigorik
 

More from Ilya Grigorik (16)

Pagespeed what, why, and how it works
Pagespeed   what, why, and how it worksPagespeed   what, why, and how it works
Pagespeed what, why, and how it works
 
Making the web fast(er) - RailsConf 2012
Making the web fast(er) - RailsConf 2012Making the web fast(er) - RailsConf 2012
Making the web fast(er) - RailsConf 2012
 
0-60 with Goliath: High performance web services
0-60 with Goliath: High performance web services0-60 with Goliath: High performance web services
0-60 with Goliath: High performance web services
 
0-60 with Goliath: Building High Performance Ruby Web-Services
0-60 with Goliath: Building High Performance Ruby Web-Services0-60 with Goliath: Building High Performance Ruby Web-Services
0-60 with Goliath: Building High Performance Ruby Web-Services
 
Ruby in the Browser - RubyConf 2011
Ruby in the Browser - RubyConf 2011Ruby in the Browser - RubyConf 2011
Ruby in the Browser - RubyConf 2011
 
Intelligent Ruby + Machine Learning
Intelligent Ruby + Machine LearningIntelligent Ruby + Machine Learning
Intelligent Ruby + Machine Learning
 
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9No callbacks, No Threads - Cooperative web servers in Ruby 1.9
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
 
No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010No Callbacks, No Threads - RailsConf 2010
No Callbacks, No Threads - RailsConf 2010
 
Real-time Ruby for the Real-time Web
Real-time Ruby for the Real-time WebReal-time Ruby for the Real-time Web
Real-time Ruby for the Real-time Web
 
Ruby C10K: High Performance Networking - RubyKaigi '09
Ruby C10K: High Performance Networking - RubyKaigi '09Ruby C10K: High Performance Networking - RubyKaigi '09
Ruby C10K: High Performance Networking - RubyKaigi '09
 
Leveraging Social Media - Strategies & Tactics - PostRank
Leveraging Social Media - Strategies & Tactics - PostRankLeveraging Social Media - Strategies & Tactics - PostRank
Leveraging Social Media - Strategies & Tactics - PostRank
 
Ruby Proxies for Scale, Performance, and Monitoring
Ruby Proxies for Scale, Performance, and MonitoringRuby Proxies for Scale, Performance, and Monitoring
Ruby Proxies for Scale, Performance, and Monitoring
 
Building Mini Google in Ruby
Building Mini Google in RubyBuilding Mini Google in Ruby
Building Mini Google in Ruby
 
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.comRuby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
Ruby Proxies for Scale, Performance, and Monitoring - GoGaRuCo - igvita.com
 
Event Driven Architecture - MeshU - Ilya Grigorik
Event Driven Architecture - MeshU - Ilya GrigorikEvent Driven Architecture - MeshU - Ilya Grigorik
Event Driven Architecture - MeshU - Ilya Grigorik
 
Taming The RSS Beast
Taming The  RSS  BeastTaming The  RSS  Beast
Taming The RSS Beast
 

Recently uploaded

Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionDilum Bandara
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 

Recently uploaded (20)

Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
Advanced Computer Architecture – An Introduction
Advanced Computer Architecture – An IntroductionAdvanced Computer Architecture – An Introduction
Advanced Computer Architecture – An Introduction
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 

Lean & Mean Tokyo Cabinet Recipes (with Lua) - FutureRuby '09

  • 1. Lean & Mean Tokyo Cabinet Recipes Ilya Grigorik @igrigorik
  • 5.
  • 6.
  • 7.
  • 8. Hashtable Berkeley DB, DBM, QDB, TDB… B-Tree Table Key-Value with duplicates & ordering 3. Fixed-length An in memory array.. No hashing. 4. Table Engine Schemaless, indexes & queries Choose your engine
  • 9. gem install rufus-tokyo require 'rubygems'require 'rufus/tokyo'db = Rufus::Tokyo::Cabinet.new('data.tch')db['nada'] = 'surf'p db['nada'] # => 'surf'p db['lost'] # => nildb.close TC: Hashtable
  • 10. require 'rubygems'require 'rufus/tokyo'db = Rufus::Tokyo::Cabinet.new('data.tch')db['nada'] = 'surf'p db['nada'] # => 'surf'p db['lost'] # => nildb.close ~ Ruby Hash TC: Hashtable
  • 11. require 'rubygems'require 'rufus/tokyo't = Rufus::Tokyo::Table.new('table.tct')t['pk0'] = { 'name' => 'alfred', 'age' => '22' }t['pk1'] = { 'name' => 'bob', 'age' => '18', 'sex' => 'male' }t['pk2'] = { 'name' => 'charly', 'age' => '45' }t['pk4'] = { 'name' => 'ephrem', 'age' => '32' }p t.query { |q|q.add_condition 'age', :numge, '32'q.order_by 'age'}# => [ {"name"=>"ephrem", :pk=>"pk4", age"=>"32"},# {"name"=>"charly", :pk=>"pk2", "age"=>"45"} ]t.close Table Engine TC: Table Engine
  • 12. require 'rubygems'require 'rufus/tokyo't = Rufus::Tokyo::Table.new('table.tct')t['pk0'] = { 'name' => 'alfred', 'age' => '22' }t['pk1'] = { 'name' => 'bob', 'age' => '18', 'sex' => 'male' }t['pk2'] = { 'name' => 'charly', 'age' => '45' }t['pk4'] = { 'name' => 'ephrem', 'age' => '32' }p t.query { |q|q.add_condition'age', :numge, '32'q.order_by'age'}# => [ {"name"=>"ephrem", :pk=>"pk4", age"=>"32"},# {"name"=>"charly", :pk=>"pk2", "age"=>"45"} ]t.close age > 32 order by age TC: Table Engine
  • 13. p t.size# => 0t.transactiondo t['pk0'] = { 'name' => 'alfred', 'age' => '22' } t['pk1'] = { 'name' => 'bob', 'age' => '18' }t.abortendp t.size# => 0 Uh oh… TC: Table Engine Transactions
  • 15.
  • 16. require "rubygems"require "rest_client"# Interacting with TokyoTyrant via RESTful HTTP!db = RestClient::Resource.new("http://localhost:1978")db["key"].put "value 1" # insert via HTTPdb["key"].put "value 2" # update via HTTPputs db["key"].get # get via HTTP# => "value 2"db["key"].delete # delete via HTTPputs db["key"].get rescue RestClient::ResourceNotFound RESTful Tokyo Tyrant
  • 17. require "rubygems"require "rest_client"# Interacting with TokyoTyrant via HTTP!db = RestClient::Resource.new("http://localhost:1978")db["key"].put "value 1"# insert via HTTPdb["key"].put "value 2"# update via HTTPputs db["key"].get # get via HTTP# => "value 2"db["key"].delete # delete via HTTPputs db["key"].get rescueRestClient::ResourceNotFound RESTful Tokyo Tyrant Awesome.
  • 18. “Recently, I sophisticated Hanami and the Sumida River in a houseboat, I was sad that day and not even a minute yet mikio bloom …” … so I added Lua scripting to Tyrant. http://alpha.mixi.co.jp/blog/?p=236
  • 19.
  • 20. Everything is an associatiave array
  • 22. Interpreted bytecode
  • 23. Garbage collectionGZIP(Source + Docs + Examples) = 212 Kb What is Lua? It’s like Ruby.. except it’s not. Fast + Lightweight = Great for embedded apps
  • 24. + CREATE FUNCTION json_members RETURNS STRING SONAME 'lib_mysqludf_json.so'; SELECT json_object(customer_id, first_name) FROM customer; +---------------------------------------------------+ | customer | +---------------------------------------------------+ | {customer_id:1,first_name:"MARY"} | +---------------------------------------------------+ Extending the Database? MySQL User Defined Functions JSON Response http://www.mysqludf.org/lib_mysqludf_json/index.php
  • 25. = C/C++ + + = Lua TC+Lua? Why? To make our lives easier, and more fun! Easy to learn & easy to extend!
  • 26. Lua extension within Tokyo Cabinet _put(key, value) _putkeep(key, value) _putcat(key, value) _rnum()_vanish() _mapreduce(mapper, reducer, keys) _out(key) _get(key) _vsiz(key) _addint(key, value) TC + Lua Extensions Request / Response data-flow http://tokyocabinet.sourceforge.net/tyrantdoc/#luaext
  • 27. -- -- echo.lua-- function echo(key, value)return key .. ":" .. valueend [ilya@igvita] >ttserver-ext echo.lua test.tch [ilya@igvita] >tcrmgrextlocalhostechofoo bar foo:bar require 'rubygems'require 'rufus/tokyo/tyrant' # sudo gem install rufus-tokyot = Rufus::Tokyo::Tyrant.new('127.0.0.1', 1978)puts t.ext(:echo, 'hello', 'world')t.close Lua + TC Echo Server
  • 28. -- -- echo.lua-- function echo(key, value)return key .. ":" .. valueend [ilya@igvita] >ttserver-ext echo.lua test.tch [ilya@igvita] >tcrmgrextlocalhostechofoo bar foo:bar require 'rubygems'require 'rufus/tokyo/tyrant' # sudo gem install rufus-tokyot = Rufus::Tokyo::Tyrant.new('127.0.0.1', 1978)puts t.ext(:echo, 'hello', 'world')t.close Lua + TC Echo Server
  • 29. -- -- echo.lua-- function echo(key, value)return key .. ":" .. valueend [ilya@igvita] >ttserver-ext echo.lua test.tch [ilya@igvita] >tcrmgrextlocalhostechofoo bar foo:bar require 'rubygems'require 'rufus/tokyo/tyrant'# sudo gem install rufus-tokyot = Rufus::Tokyo::Tyrant.new('127.0.0.1', 1978)puts t.ext(:echo, 'hello', 'world')t.close Lua + TC Echo Server
  • 30. -- -- incr.lua-- function incr (key, i)i = tonumber(i)ifnotithenreturnnilend local old = tonumber(_get(key)) if old theni = old + i end if not _put(key, i) then return nil end return iend Verify input Implementing INCR in Lua+TC
  • 31. -- -- incr.lua-- function incr (key, i)i = tonumber(i)ifnotithenreturnnilend local old = tonumber(_get(key))if old theni = old + iend if not _put(key, i) then return nil end return iend Get old value & increment it Implementing INCR in Lua+TC
  • 32. -- -- incr.lua-- function incr (key, i)i = tonumber(i)ifnotithenreturnnilend local old = tonumber(_get(key))if old theni = old + iendifnot _put(key, i) thenreturnnilendreturniend Save new value Implementing INCR in Lua+TC
  • 33. [ilya@igvita] >ttserver-ext incr.lua test.tch [ilya@igvita] >tcrmgrextlocalhostincrkeyname 1 1 [ilya@igvita] >tcrmgrextlocalhostincrkeyname 5 6 require 'rubygems'require 'rufus/tokyo/tyrant' # sudo gem install rufus-tokyot = Rufus::Tokyo::Tyrant.new('127.0.0.1', 1978)5.times do puts t.ext(:incr, 'my-counter', 2).to_iendt.close Implementing INCR in Lua+TC
  • 34. [ilya@igvita] >ttserver-ext incr.lua test.tch [ilya@igvita] >tcrmgrextlocalhostincrkeyname 1 1 [ilya@igvita] >tcrmgrextlocalhostincrkeyname 5 6 require 'rubygems'require 'rufus/tokyo/tyrant'# sudo gem install rufus-tokyot = Rufus::Tokyo::Tyrant.new('127.0.0.1', 1978)5.times do puts t.ext(:incr, 'my-counter', 2).to_iendt.close Implementing INCR in Lua+TC
  • 35. Lua + TC = Database Kung-fu TTL, Sets & Caching
  • 36. “Redis as a data structures server, it is not just another key-value DB”
  • 37. functionset_append(key, value) local stream = _get(key)ifnot stream then _put(key, value)else local set_len = _set_len(stream) if set_len == 1 then if stream == value then return nil endelseifset_len > 1 then for _, element in ipairs(_split(stream, SEP)) do if element == value then return nil end end end if not _putcat(key, SEP .. value) then return nil endendreturn valueend Empty Set Implementing Set operations in TC
  • 38. functionset_append(key, value) local stream = _get(key)ifnot stream then _put(key, value)else local set_len = _set_len(stream)ifset_len == 1 thenif stream == value thenreturnnilendelseifset_len > 1 thenfor _, element inipairs(_split(stream, SEP)) doif element == value thenreturnnilendendendifnot _putcat(key, SEP .. value) thenreturnnilendendreturn valueend Append key if unique Implementing Set operations in TC
  • 39. = ? + [ilya@igvita] >ttserver-ext set.lua test.tch [ilya@igvita] >tcrmgrextlocalhostset_append key 1 [ilya@igvita] >tcrmgrextlocalhostset_appendkey 2 [ilya@igvita] >tcrmgrextlocalhostset_append key 1 [ilya@igvita] >tcrmgrextlocalhostset_getkey 1 2 set_length set_get set_delete set_append Implementing Set operations in TC
  • 40. “memcachedis a general-purpose distributed memory caching system that is used by many top sites on the internet” Key Value Time key1 value1 10 key2 value2 20 Time = 15 key2 value2 30 Implementing TTL’s in TC
  • 41. DELETE where x > Time.now function expire() local args = {} local cdate = string.format("%d", _time())table.insert(args, "addcondxNUMLE" .. cdate)table.insert(args, "out") local res = _misc("search", args)ifnot res then _log("expiration was failed")end print("rnum=" .. _rnum() .. " size=" .. _size())end Expiring Records with Lua
  • 42. = ? + [ilya@igvita] >ttserver-ext expire.lua -extpc expire 5 "casket.tct#idx=x:dec" Invoke “expire” command every 5 seconds Table database, with index on expiry column (x) Implementing Set operations in TC
  • 43.
  • 44. [ilya@igvita] >ttserver -ext session-trail.lua test.tch [ilya@igvita] >tcrmgrextlocalhostadd 1 123 [ilya@igvita] >tcrmgrextlocalhostadd 1 256 [ilya@igvita] >tcrmgrextlocalhostadd 1 987 [ilya@igvita] >tcrmgrextlocalhostadd 2 987 [ilya@igvita] >tcrmgrextlocalhostlist 1 987 1247008220 256 1247008216 123 1247008123 Session-trail with Lua Timestamped session trail
  • 45. Lua + TC = Map Reduce! Just for kicks.
  • 46. _out(key) _get(key) _vsiz(key) _addint(key, value) _mapreduce(mapper, reducer, keys) Executing MR jobs within Tokyo Cabinet
  • 47. functionwordcount()functionmapper(key, value, mapemit)for word instring.gmatch(string.lower(value), "%w+") domapemit(word, 1)endreturntrueendlocal res = ""functionreducer(key, values) res = res .. key .. "" .. #values .. "" return true end if not _mapreduce(mapper, reducer) then res = nil end return resend Emit: {word: 1} Map-Reduce within Tokyo Cabinet
  • 48. functionwordcount()functionmapper(key, value, mapemit)for word instring.gmatch(string.lower(value), "%w+") domapemit(word, 1)endreturntrueend local res = ""functionreducer(key, values) res = res .. key .. "" .. #values .. ""returntrueendifnot _mapreduce(mapper, reducer) then res = nilendreturn resend Emit: {word: 1} sizeof(values) Map-Reduce within Tokyo Cabinet
  • 49. [ilya@igvita] >ttserver-ext wordcount.lua test.tch [ilya@igvita] >tcrmgrputlocalhost1 “This is a pen.“ [ilya@igvita] >tcrmgrputlocalhost1 “Hello World“ [ilya@igvita] >tcrmgrputlocalhost1 “Life is good“ [ilya@igvita] >tcrmgrextlocalhostwordcount a 1 good 1 is 2 life 1 pen 1 this 1 Execute Map-Reduce Job Map-Reduce within Tokyo Cabinet

Editor's Notes

  1. So what is Tokyo Cabinet? Not surprisingly, as the name implies Tokyo Cabinet is a software project that was started in Japan, and as any Rubyist knows, Japanese developers have made some amazing contributions. Case in point: Ruby and Matz. Started as a research project back in ’93, it made its way to North America in around 2001 and 2002, and the rest is history.For that reason, when I stumbled across Tokyo Cabinet, I decided to do some digging. Turns out, the project is a brainchild of one developer.. and facebook to the rescue to help us put a face to the project. And I don’t know about you, but when I saw that photo.. I had one association pop up..
  2. Yeah? What do you think? In fact, I think the analogy may be well suited because Tokyo Cabinet has all the potential to make it big in the database world.
  3. When we talk about TC, we are actually referring to three distinct products under the umbrella: - cabinet – a set of database management routines - tyrant – a standalone server implementation around cabinet - dystopia – full text search engine built on top of tokyo cabinetAll of the projects are written in very clean, easy to read, and well documented C, and released under LGPL. For the purposes of this talk, we’ll first focus on tokyo cabinet and work through some of the basics and then move on to tyrant, which is where we’ll spend most of the time. I’m not going to talk about Dystopia, but I’d encourage you to check it out and play with it.
  4. QDBM is/was a library of routines for managing a database. - 2000 – 2007Tokyocabinet is a successor to QDBM.
  5. - Thread-safeRow level lockingSupports many different data layouts as we will see shortlyFull ACID supportHas bindings to all the most popular languages, which is pretty important considering this is an embedded database
  6. TC has many different engines, which if you’re ever used MySQL is exactly the same as deciding between MyISAM or InnoDB, or any other engine. Each one has it’s advantages and the right choice really depends on your data and performance requirements. The bread and butter is the hashtable, which is just a key value store like BDB and many other database. It’s fast, really fast.B-Tree table is similar to the hash table, but because of the supported data layout it actually allows storage of duplicate keys, and iteration over that data.Fixed-length is a no frills array. It’s probably the fastest engine there is, just because of it’s simplicity, but you certainly give up a lot of functionality as well.Last but not least, the Table engine is one of the most interesting features of TC. It is essentially a schemaless document store with support for arbitrary indexing and query capabilities. Let’s take a look at a few examples…
  7. We’re using tokyo cabinet via rufus/tokyo gem, which means we’re building an embedded database. There are two good alternatives for interfacing with TC from Ruby. There is a native gem provided by the author, and then there is the rufus/tokyo gem which I’m using here which is built via FFI which means you can this library from Jruby, MRI, Rubinius and so forth. It is definitely a little bit slower, but I like the syntax it provides a lot more than the native gem.
  8. It walks & talks just like a Ruby Hash. Very easy to use.
  9. Create a query, order by ‘age’. In this case we didn’t declare any explicit indexes, but the dataset is small so the query is still very fast. If we were working with a larger dataset we would explicitly declare an index either via ruby or when we created the database. Check the docs for details on how to do this.
  10. Also, as you would expect, there is full transaction support. For this reason alone, it’s not completely unreasonable to think about using TC in place of Ruby hashes in some of your code. It’s dead simple, and fast.
  11. http://www.slideshare.net/rawwell/tokyotalk
  12. - High concurrency (multi-thread uses epoll/kqueue) - 3 Protocol Options: Binary, memcached, and HTTP - Hot backup - Update logging - Replication (master/slave, master/master) - Lua extensions
  13. Interacting via rest_client.. No rufus/tokyo here!
  14. Unfortunately, even though the project is very mature at this point, and is being used in production at mixi, finding discussions or support around the project is a bit of a challenge. Mikio regularly writes on his developer blog at mixi, but even that is in Japanese.. And I’m a big fan of statistical machine translation techniques, but there is definitely a lot of room for improvement… What you see on the slide is a start of one his blog posts of August of last year, in which he goes on to announce… By the way, this is where you should gasp and all jump in joy, because this is huge!
  15. Lua" (pronounced LOO-ah) means "Moon" in Portuguese. As such, it is neither an acronym nor an abbreviation, but a noun. Lua runs on all flavors of Unix and Windows, and also on mobile devices (such as handheld computers and cell phones that use BREW, Symbian, Pocket PC, etc.) and embedded microprocessors (such as ARM and Rabbit) for applications like Lego MindStorms. Lua is a fast language engine with small footprint that you can embed easily into your application. Lua has a simple and well documented API that allows strong integration with code written in other languages.Lua allows many applications to easily add scripting within a sandbox…
  16. So why is Lua + TokyoCabinet so interesting after all? Who’s used MySQL UDFs’? Anyone written one? They’re a pain on both accounts.User-defined functions are compiled as object files and then added to and removed from the server dynamically using the CREATE FUNCTION and DROP FUNCTION statements. You can add functions as native (built-in) MySQL functions. Native functions are compiled into the mysqld server and become available on a permanent basis. Couple of problems: C/C++ plus a very messy internal API. If you get it wrong, you crash the database, so you better get it right. Why use it? Faster then triggers, allows linking against other libraries. For example, there is a very popular memcached library which allows you to interface with memcache right from MySQL. There are number of reasons why you would want to use this, but one great use case is for replicating memcached. That is, use mysql protocol to replay queries and then update your memcached instances in different data centers, etc. This is exactly how Facebook keeps their clusters in sync.
  17. TT is a hassle to extend the protocol and implementation. Lua on the server is able to register any function.The "passing as an argument and then returns the results" so that the interface that is common to all database operations, "the method name string, string key, string value to send, running and passing the key value of the name of the method, the return string will be returned "only if a protocol that eliminates the need to define for each protocol.
  18. - Lua Extension * defines arbitrary database operations * atomic operation by record locking - define DB operations as Lua functions * clients call each giving functionname and record data * the server returns the return value of the function - options about atomicity * no locking / record locking / global lockinghttp://www.scribd.com/doc/12016121/Tokyo-Cabinet-and-Tokyo-Tyrant-Presentation
  19. Enough handwaving, let’s look at the code… A no-op extension which will return the key and value pair without storing anything in the database.The “..” syntax is Lua’sconcat operator for strings.
  20. Next, we start the tokyo tyrant server via a command line utility ‘ttserver’ and pass in the –ext parameter with the name of the extension. That’s all you need to start the server with our new extension.After that, we can use the manager utility and invoke some commands. First we specify ext as the command name, which indicates that we’re going to be calling an extension, then the address of the server, then we specify the command, which is “echo” and finally we pass in our key and value. In return, we get the string from TC!
  21. Alternatively, we could do the same thing from ruby. Except this time, instead of creating a local database, we’re going to specify an IP address and port. From there, we call the ext method again, pass in the name of the command as a symbol and the parameters. Voila.
  22. Ok, so echo is a cute example, but let’s look at something slightly more interesting. We’re going to build an increment command in Lua. Now, TC already has this in it’s API, but we’re going to do this for the same of an example.
  23. Redis is a key-value database. It is similar to memcached but the dataset is not volatile, and values can be strings, exactly like in memcached, but also lists and sets with atomic operations to push/pop elements.In order to be very fast but at the same time persistent the whole dataset is taken in memory and from time to time and/or when a number of changes to the dataset are performed it is written asynchronously on disk. You may lost the last few queries that is acceptable in many applications but it is as fast as an in memory DB (Redis supports non-blocking master-slave replication in order to solve this problem by redundancy).
  24. Do some iteration over keys, and finally append the new value if it’s actually new.
  25. In similar fashion, implement delete get and length functions and we have a minimal set of SET operations in TC. Of course, this is not going to be as fast as a native implementation in Redis, but that’s not the point either. The point is the potential extensibility of the database.
  26. The extpc argument allows us to specify a function and an interval, in this case 5 seconds which will be executed by the tokyo server. Which means that our cleanup script will be executed every 5 seconds, effectively removing the expired records from the database! Additionally, we’re going to add an index on x, in decreasing order to help speed up this operation.Once again, TC+Lua = memcached? Not quiet. Memcached will perform better because it doesn’t care to sweep it’s memory for expired records, it just lets them hang around and evicts them when it runs of out free memory. But, it’s a great example of scripting your database.
  27. Finally, here’s a real use case deployed at mixi and documented by Mikio. They use tyrant as a proxy cache server in front of a tier of their database. They use lua to interface with their cache and fallback to the actual MySQL and Hbase tables on a cache miss or write. This is possible because Lua has bindings for MySQL, which means that the entire cache server layer is built in Lua and runs as Tokyo Tyrant. No need for any extra frills and the different TC engines allow them to customize the cache layout to fit their use case.
  28. Another example documented by Mikio is a session trail tracker. Instead of analyzing the logs in offline fashion, they built a system which recorded user’s visit based on their session cookie. In this case, there are two sessions one with ID 1, and second with ID 2. First user visits resources 123, 256, and 987, which are then easily retrieved via the list operation.The source for this is available in my github repo.
  29. Back in November of ’08Mikio added another native interface for invoking mapreduce jobs on the database. There is no particular reason for this, as this implementation does not really have the distributed features that make Map-Reduce what it is, but it is a great example of a programming paradigm making the rounds…To get started with this functionality, you will once again need Lua and we’ll have to build just two functions to make it all work, a mapper and a reduce function. Let’s take a look at an example…
  30. We’re going to build a wordcount example. That is, we’re going to assume that the values in our database are strings, and we’ll try to get a word frequency count across all the keys. To do that, we’re going to iterate over all the keys, which will be passed to the mapper function repeatedly, and emit a temporary tuple, where each word will have a count of 1.
  31. Next, the reducer function takes over. In the background TC aggregates all the results with the same key and passes them into reduce. At this point, we simple count the number of values for each word, and.. we’re done!
  32. Start the server, add a few strings, and then execute our MR job. Easy as that.
  33. On that note.. Hopefully these examples gave you a taste for how easy it is to extend Tokyo Cabinet, and I would really encourage you to give it a try. All of the examples we went through in the slides are available in my github repo which I created for this talk, as well as a number of other examples.Take a look at the high-low-game, and the inverted-index extensions. Both great examples of what you can do with less than a hundred lines of Lua and TC.