PHP ve NoSQL (MongoDB)

April 6, 2010

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?

  1. İ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?
  2. Veritabanı büyüdüğünde yedekleme gibi işlemler (bakım) sorun olmaya başlar.
  3. Replikasyona dair sorunlar yaşayabilirsiniz.
  4. 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;

  1. Key/Value database (Redis, MemcachedDB vb..)
  2. Document Oriented database. (MongoDB, CouchDB)
  3. Object database (db4o)
  4. Graph databse (neo4j)
  5. 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

CakePHP MongoDB Datasource sınıfı.

Kohana Mango 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

PHP ile İlgili Diğer Makaleler

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. :)