PHP ve NoSQL (MongoDB)
NoSQL Nedir?
NoSQL, ilişkisel olmayan bir veritabanıdır. SQL dili kullanmadan Map-Reduce kavramı ile sorgulama yapılır. Map ve Reduce, aslında fonksiyonel programlamada sıkça kullanılan iki fonksiyondur. Excel buna güzel bir örnektir. Gün geçmiyorki tarih tekerrür etmesin. NoSQL kelimesini birkaç blogta okuduğum vakit Yazılım Mimarı olan 40-45 yaşlarında bir büyüğüme bundan söz ettim. O da, aslında bunun yıllar önce kullanılan Berkley_DB’den başka birşey olmadığını söyledi. Berkley_DB aynı anda çalışan binlerce iş parçacığının(thread) 256 terabyte büyüklüğüde bir veritabanına erişebilmesini mümkün kılar. SQLite’ta BerkleyDB’ye benzer bir yapıya sahiptir. Ama biz SQLite’ı küçük işlerde kullanırız!. Biraz kafa karıştırıcı olduğunu biliyorum. Burada ilginç bir döngü var? Internet mozaik bir yapıdadır. Ve dağınıktır. Bu dağınık yapıyı Google’ın yaptığı gibi indekslemek (tabiri caizse tüm interneti indirmek isterseniz), dünyanın en büyük ve en iyi ilişkilsel veritabanını kanalize olmuş Oracle bile yetersiz kalacaktır.
Peki neden?
- İlişkisel veritabanları, yazma hakkı olan bir sunucu üzerinde koşar. Ana sunucuya birşey olması durumunda slave makinelerden biri master’a çevirilir ve yola devam edilir. Burada ki veritabanına gelen yazma isteklerini düşünebiliyor musunuz?
- Veritabanı büyüdüğünde yedekleme gibi işlemler (bakım) sorun olmaya başlar.
- Replikasyona dair sorunlar yaşayabilirsiniz.
- Google’ın 1 milyon makinesi olduğu varsayılıyor! Bu kadar makinelerin yarısının aynı anda tek bir makineye yazma isteği bulunduğunu düşünürsek durum daha net anlaşılabilir.
Google, startup döneminde, bir mühendislik şirketi gibi davrandı ve ihtiyaçlarını iyi analiz etti. 10.000$‘lık sunucular almak yerine 500$‘lık ucuz makineler satın aldı. Ve bu makinelerin kısa ömürlü ve her an patlayacağını bilerek kodlarını yazdı. Ve BigTable denilen (Hadoop bunun açık kaynak halidir) Map ve Reduce fonksiyonları ile sorgulamayı sağlayan bir mimari kurdu. Bu mimarinin en önemli özelliği; makinelerden biri göçse bile, sistemin çalışmaya devam etmesidir. Her kaydın 3-5 ayrı sunucuda kopyası bulunmaktadır. Bu şekilde web için en uygun devasa bir Mosaic oluşturdular. Peki NoSQL konusuna giriş yaptık. Fakat bu seferde karşımıza birden fazla NoSQL türü çıkacak;
- Key/Value database (Redis, MemcachedDB vb..)
- Document Oriented database. (MongoDB, CouchDB)
- Object database (db4o)
- Graph databse (neo4j)
- Tabular (bigtable, hadoop)
Biz bu türlerden, belge yönelimli veritabanları konusu üzerinede duracağız. Belge yönelimli veritabanları, nesne yönelimli ve ilişkisel veritabanlarının alt katmanıdır. Yukarıda saydığım veritabanlarının birbirinden farkını ve merak ettiğiniz diğer konuları Vikipedi‘den okuyabilirsiniz. MongoDB’yi neden tercih ettiğime dair bilgilerine ise; benchmark testlerinden ve kıyaslama tablosundan edinebilirsiniz.
MongoDB’yi Denemek İçin;
Eğer yukarıdaki bilgiler sizi tatmin etmedi ve MongoDB’yi biraz kurcalamak istiyorsanız ve zamanım yok makineye kurmadan denemek istiyorum diyorsanız; online olarak şuradan deneyebilmeniz mümkün.
MongoDB sunucusunun çalıştırmak için;
mongod --dbpath=/data/mongo
MongoDB’nin Ubuntu’ya Kurulumu
MongoDB’nin Ubuntuya nasıl kurulduğunu anlatacak olsamda diğer işletim sistemleri ve linux dağıtımlarına nasıl kurulacağını şuradan öğrenebilirsiniz. APTITUDE ile kurmak için; aşağıdaki dağıtımınız için uygun olan paket kaynak adresini seçerek /etc/apt/sources.list dosyasına kopyalamanız yeterlidir.
# for Ubuntu Lucid (10.4) (built using a prerelease installation)
deb http://downloads.mongodb.org/distros/ubuntu 10.4 10gen
# for Ubuntu Karmic (9.10)
deb http://downloads.mongodb.org/distros/ubuntu 9.10 10gen
# for Ubuntu Jaunty (9.4)
deb http://downloads.mongodb.org/distros/ubuntu 9.4 10gen
ve sonrasında da aşağıdaki komutları çalıştırmanız yeterlidir.
sudo aptitude update
sudo aptitude install mongodb-stable
# ya da
sudo aptitude install mongodb-unstable
# ya da
sudo aptitude install mongodb-snapshot
# install dependicies for Ubuntu 9.04 ve 9.10
sudo apt-get -y install tcsh git-core scons g++
sudo apt-get -y install libpcre++-dev
libboost-dev libreadline-dev
xulrunner-1.9.1-dev
# get source
git clone git://github.com/mongodb/mongo.git
# build
scons
# install
sudo scons --prefix=/opt/mongo install
Görüldüğü üzere kurulum son derece basit. Derlenerek kurulum işleminde yapılması gereken başlangıç betiği hazırlamak.
#!/usr/bin/env ruby -w
# mongo ;; 2010 (cc) Jan Riethmayer
# This work is licensend under a Creative Commons Attribution 3.0 license.
require 'optparse'
options = {}
optparse = OptionParser.new do|opts|
opts.banner = <<-BANNER
Usage: sudo ./mongo [options]
BANNER
options[:dbpath] = "/data/mongodb/"
opts.on( '-d', '--dbpath', 'Select DB path. Defaults to /data/mongodb/' ) do |path|
options[:dbpath] = path
end
options[:port] = "27017"
opts.on( '-p', '--port PORT', 'Listening to port 27017 by default' ) do |port|
options[:port] = port
end
options[:fork] = false
opts.on( '-f', '--fork', 'Run as daemon' ) do
options[:fork] = true
end
options[:logpath] = "/var/log/mongodb.log"
opts.on( '-l', '--logfile FILE', 'Defaults to /var/log/mongodb.log' ) do |file|
options[:logpath] = file
end
opts.on( '-h', '--help', 'Display this screen' ) do
puts opts
exit
end
end
# Parse the command-line. Remember there are two forms
# of the parse method. The 'parse' method simply parses
# ARGV, while the 'parse!' method parses ARGV and removes
# any options found there, as well as any parameters for
# the options.
optparse.parse!
class Go
attr_accessor :opts
def initialize(opts)
@opts = opts
end
def start
puts "Starting on port #{@opts[:port]} with dbpath #{@opts[:dbpath]}"
puts "Running as Daemon" if @opts[:fork]
puts "Writing to logpath /var/log/mongodb.log"
path = "--dbpath #{@opts[:dbpath]}"
port = "--port #{@opts[:port]}"
log = "--logpath #{@opts[:logpath]} --logappend"
fork = "#{@opts[:fork] ? '--fork' : ''}"
params = [path, port, log, fork].join(" ")
result = %x{ ./mongodb/bin/mongod #{ params } }
puts result
end
def stop
process = %x{ ps -o pid,command ax | grep mongod }
found = false
matcher = process.scan(/(\d+).+?bin.+?mongod.+?--fork/) do |pid|
found = true
puts "Killing process #{pid}"
%x{ kill -2 #{pid} }
end
puts "No mongod process found" unless found
end
end
go = Go.new(options)
case ARGV[0]
when /start/ : go.start
when /stop/ : go.stop
else
raise ArgumentError.new("mongo (start|stop) or mongo -h for help.")
end
Yukarıdaki dosyayı /etc/init.d/mongo şeklinde kaydetmek gerekiyor.
PHP Kurulumu
sudo pecl install mongo
PHP için monog eklentisinin hatasız bir şekilde derlenebilmesi için bilgisayarınızda phpize yüklü olmalıdır. Derleme işleminden sonra, php.ini dosyanıza;
extension=mongo.so
ekledikten sonra kurulum işlemi tamamlanmış olur. Artık PHP mongo ile konuşabilecek durumda. PHP’nin sınıfları ile ilgi detaylı bilgiye php.net/mongo adresinden ulaşabilirsiniz. PHPMyAdmin gibi bir yönetim arabirimi arıyorsanız, PHPMoAdmin tam size göre.
PHP Frameworkleri
Birçok popüler PHP framework’ünün MongoDB için ActiveRecord patternine uygun yazılmış eklentisi mevcut. Gelin bunlara bir göz atalım;
Zend Framework
- Zend_Nosql_Mongo Zend firması tarafından geliştirilen sınıf.
- Shanty Mongo ise diğer bir sınıf.
CakePHPMongoDB Datasource sınıfı.
KohanaMango ise Kohana için ActiveRecord paternini kullanan bir sınıf.
Symfony Symfony için Jason Mooberry tarafından yazılan makalenin, 1. bölümü ve 2. bölümünden bilgi edinebilirsiniz.
Kütüphaneler
- ActiveMongo güzel bir kütüphane. Bu kütüphaneye başlangıç yapmak için ise şu makaleye bakabilirsiniz.
- Morph Kütüphanesi
PHP ile İlgili Diğer Makaleler
- http://technosophos.com/content/mongodb-5-things-every-php-developer-should-know-about-mongodb
- http://www.businessinsider.com/how-we-use-mongodb-2009-11
- http://www.lafermeduweb.net/billet/nosql-mongodb-et-php-premiere-approche-781.html
- http://blog.boxedice.com/2009/07/25/choosing-a-non-relational-database-why-we-migrated-from-mysql-to-mongodb
- http://www.phpclasses.org/blog/post/118-Developing-scalable-PHP-applications-using-MongoDB.html
MongoDB gerçekten çok iyi belgelenmiş ve birçok web çatısı tarafından desteklenen harika bir araç. Bu konuda ki paylaşımlarınızı bekliyorum. :)