Hadoop Workshop Etkinliği

sparkİstanbul Spark Tanışmaları Grubu (İSTG) tarafından Spark ın tanıtımı ve kullanımı konulu 25 Temmuz 2015 Cumartesi günü İstanbul’da yapılan çalışma etkinliği sonrası, planlanan diğer bir diğer etkinlik olan Hadoop ile Merhaba Dünya konulu workshop, 8 Ağustos 2015 Cumartesi günü Maslak taki İTÜ Teknokent’te gerçekleştirildi. Arı 3 Çekirdek Seminer Salonu’nda gerçekleştirilen etkinliğe değişik şirket ve sektörden 25 kişi katıldı. İTÜ Çekirdek Yönetimi’nin önceki etkinlikte olduğu gibi, seminer salonlarını Workshop için kullanıma sunmaları etkinliğin güzel bir ortamda gerçekleşmesine önemli katkı sağladı.

Etkinliği düzenleyen İSTG grubunun kurucularından olan Şafak Serdar Kapçı’nın, Hadoop’u tanıtan kısa sunumundan sonra yaklaşık üç saat süren uygulama kısmına geçildi. Bu kısım, Hadoop kurulumu için daha önceden Şafak Bey tarafından hazırlanan CentOS İşletim Sistemli sanal makinanın, her bir katılımcı tarafından kendi makinasında ayağa kaldırılması, geliştirme için gerekli olan Java ve IDE ortamı olan Eclipse in yüklenmesi ve Hadoop un son sürümü Hadoop.2.7.1 kurulumu ve gerekli konfigürasyonların yapılması ile tamamlandı. Bu adımda Hadoop un üç farklı çalışma şeklinden,

  1. Basit (Standalone mode)
  2. Sanki dağıtık (Pseudodistributed mode)
  3. Tam dağıtık (Fully distributed mode)

içinden, ikincisi olan sanki dağıtık mode a göre konfigürasyonlar yapıldı. Bu modda, hadoop un temel bileşenleri tek makinada sanki bir cluster varmışçasına çalıştırıldığı için, tek bir makine üzerinde olsa da gerçeğe mümkün olduğunca yakın bir Hadoop kurulumu yapılmış oldu.

Sonrasında Java projeleri olarak hazırlanmış örnek projelerin github üzerinden alınması ve Eclipse ortamında çalıştırılması şeklinde katılımcıların her birinin kendi makinası üzerinde kurduğu Hadoop ile uygulama denemeleri yaptığı aşamaya geçildi.

Detaylar

Uygulama örneklerinde kullanılmak üzere seçilen veri setleri şunlar oldu.

TCMB.txt veri seti : TC Merkez Bankası GBP ve USD döviz kurları 1950 den günümüze efektif alış ve satış kurları verileri.

NCDC.txt veri seti : National Climatic Data Center (NCDC) ın 1901 den bu yana dünyanın birçok bölgelerinde günlük olarak kayıt edilmiş sıcaklık değerleri verileri.

CDR.txt veri seti : Arama verilerinin bulunduğu örnek veri seti.

 

Şafak Bey in hazırladığı projeler şu şekilde kurgulanmıştı.

  1. TCMB => TCMB.txt veri setinden yıl ve İngiliz Sterlini Alış (gbpA) değerlerini Map eden bir Mapper class ı, her yıl için gün bazında map edilen bu değerlerden her yıl için maksimum değerleri üreten bir reducer class ı. Sonuçta <key, value> şeklinde yıl ve o yılki maksimum gbpA değerleri üretilmektedir.
  2. NCDC => NCDC.txt veri setinden yıl ve sıcaklık değerlerini Map eden bir Mapper class ı, her yıl için gün bazında map edilen bu değerlerden her yıl için maksimum sıcaklık değerlerini üreten bir reducer class ı. Sonuçta <key, value> şeklinde yıl ve o yılki maksimum sıcaklık değerleri üretilmektedir.
  3. CallData => CDR.txt veri setinden konuşma süresi değerlerini Map eden bir Mapper class ı, map edilen bu değerlerden ortalama konuşma süresini üreten bir reducer class ı. Sonuçta <key, value> şeklinde duration ve ortalama konuşma değeri üretilmektedir.

 

Bu adımların detaylarına github daki HadoopWorkShop dan ulaşabilirsiniz.

 

Şafak Serdar Kapçı, Hadoop’u tanıtan kısa bir sunum yaptı.
Şafak Serdar Kapçı, Hadoop’u tanıtan kısa bir sunum yaptı.

 

Çalışma boyunca Şafak Bey katılımcılar ile tek tek ilgilendi.
Çalışma boyunca Şafak Bey katılımcılar ile tek tek ilgilendi.

 

Uygulamalar için Eclipse olarak bilinen ve Java dünyasında yaygın olarak kullanılan Etkileşimli Geliştirme Ortamı – IDE (Integrated Development Environment) tercih edildi. Şafak Bey’in hazırladığı kodlar kullanılarak pratikte bir Hadoop uygulamasının veri işlemede nasıl kullanıldığı uygulamalı olarak gösterildi.

IDE olarak Eclipse ortamı kullanıldı.
IDE olarak Eclipse ortamı kullanıldı.

 

Kaynak Yöneticisi WEB kullanıcı ekranı
Kaynak Yöneticisi WEB kullanıcı ekranı

 

NameNode Web kullanıcı ekranı
NameNode Web kullanıcı ekranı

 

Bitiriş

Workshop boyunca Şafak Bey in sorulara tek tek cevap veriyor olması, dağıtık veri işleme gibi zor bir konunun Hadoop ile nasıl yapılabildiğinin anlaşılması açısından katılımcılar için iyi bir fırsat sunmuş oldu. Bu başarılı etkinlikte emeği geçenleri kutluyoruz.

Spark ile Tanışma Etkinliği

sparkİstanbul Spark Tanışmaları Grubu (İSTG) tarafından Spark ın tanıtımı ve kullanımı konulu çalışma toplantısı, 25 Temmuz 2015 Cumartesi günü İstanbul Maslak taki, İTÜ Teknokent’te gerçekleştirildi. Arı 3 Çekirdek Seminer Salonu’nda gerçekleştirilen etkinliğe değişik şirket ve sektörden 23 kişi katıldı. İTÜ Çekirdek Yönetimi’nin seminer salonlarını Workshop için kullanıma sunmaları etkinliğin güzel bir ortamda gerçekleşmesine önemli katkı sağladı.

Etkinliği düzenleyen İSTG grubunun kurucusu olan Şafak Serdar Kapçı’nın, Spark’ı tanıtan kısa sunumundan sonra yaklaşık üç saat süren uygulama kısmına geçildi. Bu kısım, Spark kurulumu için sanal makinanın hazırlanması, gerekli bazı ön yüklemelerin yapılması ve sonunda da Spark’ın kurulumu ile tamamlandı. Sonrasında iki ayrı örnek veri seti üzerinde uygulamalı olarak Spark ın yetenekleri gösterildi. Bu adımların detaylarına github daki SparkWorkShop dan ulaşabilirsiniz.

Şafak Serdar Kapçı’nın, Spark’ı tanıtan kısa sunumu
Şafak Serdar Kapçı’nın, Spark’ı tanıtan kısa sunumu
Çalışmalar boyunca Şafak Bey in tek tek katılımcılar ile ilgilenmesi ve sorularını cevaplaması
Çalışmalar boyunca Şafak Bey in tek tek katılımcılar ile ilgilenmesi ve sorularını cevaplaması

Uygulamalar için REPL olarak bilinen ve popüler etkileşimli hesaplama ortamı olarak yakın zamanda Jupyter Projesi ismi ile Python a bağlı olmayan bir kimliğe bürünen IPython Notebook ortamında Şafak Bey in hazırladığı kodların üzerinden geçildi. Spark için hazırlanmış Python API paketi olan PySpark kullanılarak temel verinin SparkContext e yüklenmesi ve bu veri üzerinde transformasyon ve aksiyon kategorisindeki işlemlerin nasıl yapılacağı ile ilgili örnek verilerek devam edildi.

spark03
Spark için hazırlanmış Python API paketi olan PySpark kullanımı

Arkasından SparkSQL e bir giriş olarak, PySpark paketinin bir alt paketi olan pyspark.sql kullanılarak da benzer işlemlerin aynı veri setleri üzerinde nasıl yapıldığı konusunda bazı örneklerle oturum tamamlandı.

SparkSQL e bir giriş olarak, PySpark paketinin bir alt paketi olan pyspark.sql ın kullanımı
SparkSQL e bir giriş olarak, PySpark paketinin bir alt paketi olan pyspark.sql ın kullanımı

Çalışmalar boyunca Şafak Bey in tek tek katılımcılar ile ilgilenmesi ve sorularını cevaplaması ile genel olarak katılımcıların bir çoğunun Spark a giriş ve ısınma açısından hızlı bir başlangıç yaptıkları söylenebilir. Bu etkinlikte emeği geçen burada bahsedemediğimiz kişileri yorumlar kısmına eklerseniz seviniriz. Hadoop konusunda bir bloğa da sahip olan Şafak Bey i bu başarılı organizasyon nedeni ile tebrik ediyoruz.

MongoDB Replica Set Kullanımı

MongoDB, şüphesiz son 5 yılın en iyi NoSQL veritabanı çözümlerinden bir tanesi. Foursquare gibi büyük firmalar tarafında kullanıldığı öğrenilince, insanlar kendi sistemlerinde ciddi veri saklama çözümleri için bir heyecanla MongoDB kullanmaya çalışıyor. Evet MongoDB bir çok alanda veri saklama işinde çok yararlı olabilir, ama inanın yanlış kullanıldığı takdirde sizin bir numaralı kabusunuz da olabilir…. MongoDB Replica Set kullanımı ile ilgili internette çok fazla döküman var ama tam olarak çalıştırabileceğiniz şekilde Replica Set kurulumunu anlatan bir kaynak yok. Bu yazıda sizlere adım adım nasıl kurulacağını anlatacağım.

Yüksek hit alan sistemlerde veri saklama işini yaparken verilerin en az bir kopyasının olması(redundancy) ve yüksek erişilebilir(high availability) olması olmazsa olmazlardandır. Biz bunu MongoDB de Replica Set ile yapacağız.

Replica Set Nedir?

Aynı veri setini barındıran ve yöneten bir grup mongod servisleridir. Replica Set in öncelikli amacı datanın redundant ve high available olmasını sağlamaktır. Verilerin kopyası birden fazla sunucuda tutulduğu için, herhangi bir sunucuda donanımsal sıkıntı yaşadığınız zaman, ayni veri baska sunucudan okunabilir. Daha sonra sıkıntı giderildiğinde başka sunucudan aynı veri sorun yaşanan sunucuya otomatik olarak senkronize edilir. Ya da başka bir senaryo düşünürsek, aynı veri birden fazla sunucuda var demiştik. Okuma işlemi yaparken hep aynı sunucudan okumak yerine okuma yükü verinin kopyasının olduğu sunuculara dağıtılır. Dolayısıyla veri okuma ya da yazma hızı artırılmış olur.

Replica Set Yöntemleri

MongoDB Replica Set oluşturmak için gerekli üye sayısı tek sayı olmalıdır. Mesela aşağıdaki 3 üyeli bir Replica Set. Gördüğünüz üzere bir tane Primary üye iki tane Secondary üye var. Diyelim ki sizin bir uygulamanız var ve bu uygulama MongoDB ye bağlanıp belirli işlemler yapıyor. Siz herhangi bir yazma işlemi yaptığınızda Primary üye bu isteği alıp kendi log sistemi olan oplog a yazar. Buraya ayzmasının sebei, daha sonra Secondary üyeler tarafından okunup Secondary üyelerin kendi veritabanlarina yazması için gerekli olmasıdır.

01
Replica Set 1 (http://www.mongodb.org)

Şimdi de başa bir yönteme göz atalım. Bu senaryomuzda ise kalıcı bir Primary üye olmayacak, yeri geldiğinde Secondary üyeler Primary olabilecek. Peki neden böyle bir duruma ihtiyaç duyulsun? Diyelim ki Primary üyenin bulunduğu makine kapandı, bu durumda yazma isteklerini karşılayacak bir üye de olmayacak. Yani sistemde data kaybı olacaktır. Ama siz mimarinizi değiştirip, Primary kapandığında ya da Primary üye 10 saniyeden fazla bir süre diğer üyelerle iletişim kuramadığında, geri kalan üyeler kendi aralarında karar verip Primary üye seçerlerse sistem normal işleyişine devam edebilecektir. Bu mimariyi iki şekilde yapabilir siniz:

02
Replica Set 2 (http://www.mongodb.org)

Burada yeni bir üye tipi var: Arbiter. Bu üye hiçbir şekilde veri işlemi yapmaz sadece Primary üye seçimi yapılırken seçmen sayısının tek sayının katı olması için vardır. Yani sadece seçim işleminde rol oynar. Daha önce de demiştik, Replica Set üye sayısı tek sayı olmalıdır. Peki neden 2 tane Secondary ve tek Primary yok? Aslında onu da yapabilirsiniz ama eğer 2 tane Secondary kullanmaya gerek yok ise, Arbiter kullanmak sizin veritabanı maliyetinizi düşürecektir.

03
Üye seçimi (http://www.mongodb.org)

Bu şekilde de Primary üye bir şekilde kapanırsa eğer, geri kalanlar kendi aralarında Primary seçeceklerdir.

Son olarak, Replica Set’ten veri okuma işlemi genelde Primary üye üzerinden yapılır ama siz okuma stratejinizi değiştirip sadece Secondary üyeden okuma işlemi yap diyebilirsiniz. Bu konuyla ilgili detaylı bilgiyi buradan bulabilirsiniz.

Kurulum İçin Gereksinimler

Kurulum sırasında birden fazla sunucuya (ya da sanal makine de olabilir) ihtiyacımız olacak. Aslında aynı makine üzerinde birden fazla mongod servisini ayrı portlarda da çalıştırabiliriz, ama gerçek yaşamdaki kullanıma yakın olsun diye farklı sunucularda kurarak anlatmayı tercih ediyorum. Ama birden fazla suncuyu nerde bulacağız diyebilirsiniz. Hiç sorun değil, lokal makinenize docker kurup birden fazla linux container ayağa kaldırıp bunlara kurulum yapacağız. Docker kurulumu ile ilgili detaylara burada değinmeyeceğiim, isteyen şuradan nasıl kurulduğuna bakabilir. Kurulum esnasında kullandığım docker komutlarından kısaca bahsediyor olacağım.

Replica Set kurulumundan önce size tek bir mongod servisinin nasıl kurulduğunu göstereceğim. Bu Replica Set kurulumu yaparken işinize yarayacak.

MongoDB kurulumu

Docker kurduktuna sonra ubuntu kullanacağız ama öncelikle indirmemiz gerekiyor. docker pull ubuntu komutunu çalıştırarak indirme işlemi tamamlayın. Daha sonra docker images komutunu çalıştırınca listede ubuntu imajını görmeniz lazım. Şimdi ubuntu imajını kullanarak bir tane container ayağa kaldırıp içine MongoDB kurulumu yapabiliriz ama en az 3 tane container olacak ve herbirine tek tek MongoDB kurmak pek mantıklı olmayabilir. O yüzden gelin bunu otomasyona bağlayalım. Yani öyle birşey yapacağız ki,

  1. ubuntuyu kullansın
  2. MongoDB paketini indirsin ve belirli klasöre kopyalasın
  3. daha önceden hazırladığımız mongo.conf dosyasını container içine kopyalasın

Bu adımları bir Dockerfile içine yazıp bu direktifler doğrultusunda kendi imajımızı yaratabiliriz. Şimdi Dockerfile adında bir dosya yaratın ve içine aşağıdaki içeriği koyun.

FROM ubuntu:latest
RUN apt-get update -y && apt-get install -y wget unzip build-essential
RUN cd /opt \
        && wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.4.tgz \
        && tar -xvzf mongodb-linux-x86_64-3.0.4.tgz \
        && mv mongodb-linux-x86_64-3.0.4 mongodb
RUN mkdir -p /data/mongo
RUN mkdir -p /var/log/mongodb

ADD mongodb.conf /opt/mongodb/mongodb.conf
RUN chmod 644 /opt/mongodb/mongodb.conf
RUN chmod 644 /data/mongo

Basitçe, yaratacağımız imajın özelliklerini direktif halinde belirttik, şimdi bunu derleyip imaj oluşturalım. Derlemek için ise aşağıdaki komutu kullanabilirsiniz.

docker build -t mongodb:1.0 .

Bu komut sayesinde, bulunduğunuz dizindeki Dockerfile kullanılarak mongodb adında ve 1.0 versiyonunda bir imaj oluşturduk. Artık bu imajı kullanarak istediğimiz kadar container yaratabiliriz. Sanki bilgisayarınızdaki işletim sistemi ve dosyaların imajını almışsınız ve her an istediğiniz makineye kuruluabilir şeklinde düşünebilirsiniz. Container çalıştırmak için aşağıdaki komutu kullanabilirsiniz.

docker run -d --name mongodb-1 -v /dockerdata:/dockerdata mongodb:1.0 tail -f /dev/null

Bu komut ile container arka planda(-d) çalışır durumda. Adını –name opsiyonuyla verdik ve çalıştırılırken kullanılacak imaj mongodb:1.0 . -v seçeneği volume anlamına geliyor ve bu da lokaldeki bir klasörü container içindeki klasör ile eşleştirmek için kullanılıyor. Mesela ileriki bölümlerde bir anahtar üreteceğiz ve bu anahtar lokaldeki /dockerdata/ klasöründe olacak ve container içinden /dockerdata/mongokey.pem aslında lokal klasörden ulaşılmış olacak. En sondaki fonksiyon zorunlu değil ama eğer docker container içinde hiçbirşey çalışmayacak şeilde ayağa kalkarsa açar açmaz kapanacaktır. O yüzden /dev/null dosyasını tail komutuyla okudum ve bu sayede container ayakta durmuş olacaktır. Container çalışıyor ama bu container e nasıl bağlanacağız? Bağlanmadan önce docker ps diyerek o anki çalışan docker container listesine bakabiliriz. Burada container biligilerini göreceksiniz. Container’a bağlanmak için NAME alanını kullanacağız. Biz container’ı ayağa kaldırırken adını mongodb-1 vermiştik. Bağlanmak için aşağıdaki komutu kullanalım.

docker exec -i -t mongodb-1 bash

Bu komuttan sonra container a bağlanıp komut satırına düşmüş olacaksınız. Artık elinizde icinde MongoDB kurulu olan Ubuntu işletim sistemi var. MongoDB’yi başlatmak icin aşağıdaki komutu kullanabilirsiniz:

/opt/mongodb/bin/mongod --config /opt/mongodb/mongodb.conf

MongoDB’yi başlatmanın birçok yöntemi var. İsterseniz parametreleri direkt olarak komut satırından verebilirsiniz, dilerseniz bir config dosyasına koyup –config opsiyonuyla config dosyasını geçebilirsiniz. Şimdi gelelim config dosyasının içerğindeki ifadelerin ne anlama geldiğine;

dbpath: MongoDB’nin verileri yazacağı klasörün path’i

logpath: MongoDB calışırken logları yazacağı log dosyası

fork: MongoDB’nin daemon modda çalışabilmesi için gereken parametredir. Normalde MongoDB arkaplanda çalışmaz, fork: true derseniz arkaplanda çalıştırmanıza imkan sağlar.

pidfilepath: MongoDB’yi çalıştırdığınızda process id’sini yazacağı dosyadır. Aslında process id’sini ps -ef | awk ‘/mongodb/{print $2}’ | head -1 komutuyla da alabilirsiniz.

logappend: Aslında bu opsiyon analitik için çok önemli. Bu seçenek true olarak ayarlanırsa, mongod restart edildiğinde var olan logların üzerine yazmaz ve kaldığı yerden devam eder. Ama bu seçenek yoksa, restart işleminde eski loglar uçar (Eğer rotate etmediyseniz tabi) ve yeni bir log dosyası yaratıp ona yazmaya devam eder.

smallfiles: Bu seçenek true olursa, MongoDB nin oluşturduğu default veri dosya boyutları küçük olur. Bu konu performans açısından önemli ve burada çok da detaya inmek istemiyorum. Detaylı bilgi için şuraya bakabilirsiniz.

Artık MongoDB çalışır durumda, ama tahmin edeceğiniz gibi hiç bir güvenlik seviyesi yok. İsteyen bağlanıp veri yazabilir. O yüzden yönetim için hesap ekeleyelim. MongoDB servisi çalışırken aşağıdaki komutu çalıştırırsanız:

/opt/mongodb/bin/mongo

MongoDB ye bağlanacaksınız. Replica Set işlemleri, aslında bir yönetici hesabının yapması gereken işlemlerdir. O yüzden sisteme root kullanıcısı ekleyelim. İlk önce admin veritabanına use admin diyerek geçelim ve aşağıdaki komut yardımıyla root kullanıcısı ekleyelim.

db.createUser(
  {
    user: "root",
    pwd: "123456",
    roles: [ { role: "root", db: "admin" } ]
  }
)

Daha sonra şu komut yardımıyla kullanıcıya giriş yaptırabilirsiniz:

db.auth("root", "123456")

Artık kullanıcımız var, MongoDB’yi güvenlikli haliyle restart edebiliriz. Ama önce config dosyasına auth=true eklemeniz lazım. Ekledikten sonra MongoDB’yi restart edelim. Tekrardan admin database ine aşağıdaki komut ile bağlanalım.

/opt/mongodb/bin/mongo localhost:27017/admin

Bağlandıktan sonra db.getUsers() derseniz, yetkili olmadığınızı söyleyen bir mesaj belirecektir. Giriş yapalım:

db.auth("root", "123456"); 

Artık istediğimiz işlemi yapabiliriz.

Buraya kadar yaptığımız güvenlik tabakası olan bir MongoDB servisi kurmaktı. Şimdi replica set nasıl ayarlanır ona bakacağız.

Mantık çerçevesinden olaya baktığımız zaman, Replica Set üyelerinin birbirleriyle haberleşmesi şifreli olması lazım. Yani herhangi bir üye gelişi güzel Replica Set’e bağlanamamalı. Bunun için bir anahtar üreteceğiz ve bütün üyeler bu anahtarı kullanacak. Anahtarı aşağıdaki komut ile üretebiliriz.

openssl rand -base64 741 > mongokey.pem chmod 600 mongokey.pem 

mongokey.pem dosyası, Replica Set üyeleri tarafından okunabilecek bir yerde olması lazım. Bu dosyayı herbir üyenin bulunduğu container’a kopyalayabilirsiniz, ya da dockerdata ortak klasöründen okuyabilirsiniz. Bu anahtarı belirtmek için de config dosyasına bir kayıt daha koymamız lazım.

keyFile=/dockerdata/mongokey.pem

mongokey.pem dosyasını /dockerdata/ klasörüne kopyalayıp MongoDB üyelerini yeniden başlatabiliriz. Tabi yeni configi 3 üyenin config dosyasına ekelmeyi unutmayalım. Diğer üyeler aslında henüz ortada değil onları da aşağıdaki komutlarla başlatalım.

docker run -d --name mongodb-2 -v /dockerdata:/dockerdata mongodb:1.0 tail -f /dev/null
docker run -d --name mongodb-3 -v /dockerdata:/dockerdata mongodb:1.0 tail -f /dev/null

Artık 3 üyemiz var ve docker ps dediğinizde aşağıdaki gibi bir çıktı göreceksiniz.

04

Şimdi ilk container’a bağlanıp Replica Set ayarlarını yapalım.

docker exec -i -t mongodb-1 bash

ile bağlandıktan sonra

/opt/mongodb/bin/mongo localhost:27017/admin -u root -p ‘123456’

ile admin veritabanına bağlanalım ve Replica Set ayarlamaya hazırız.

Replica Set i akliftestirmek icin MongoDB konsolundayken aşağıdaki komutu kullanalım.

rs.initiate()

Bu komut aktifleştirmeyi yapıp kendisini de ilk üye olarak ekler. rs.conf() komutunu çalıştırırsanız aşağıdaki gibi bir çıktı görürsünüz.

05

Buradaki JSON objesinde members altında üyelerin bilgileri yer alır. İlk üyenin host değeri rasgele bir sayı olarak ayarlanmış. Aslında bizim mimaride üyelerin birbirleriyle bu adlarla ulaşması ilk aşamada host tanımlaması yapmadan imkansızdır. O yüzden buradaki host değerini IP ile değiştireceğiz. Peki IP yi nerden bulacağız? Burada docker inspect komutu imdadımıza yetişiyor. docker inspect <container_id> komutunu çalıştırınca ilgili container’a ait bir sürü bilgi gösterilecektir. NetworkSettings.IPAddress de ilgili container’ın IP adresi yer alır. <container_id> yi de docker ps diyerek ilgili container’ın id sini bulabilirsiniz. Aşağıdaki ekrana göre ilk mongo containerin id si 0f110ae7a9f3 tür.

06

docker inspect 0f110ae7a9f3 komutunu çalıştırdığımda IP adresini 172.17.0.29 olduğunu gördüm. Diğer container IP lerine bakmanıza gerek yok çünkü Docker ard arda açılan container ların IP lerini ardışık olarak atar. Yani diğer üyelerin IP adresleri bende 172.17.0.30 ve 172.17.0.32 dir. Şimdi gelelim ilk üyenin host değerini IP ile değiştirmeye. Basit olarak var olan Replica Set konfigürasyonunu bir değişkene atıp host değerini güncelleyeceğiz. Sonra da rs.reconfig() ile eski konfigürasyon ile değiştireceğiz.

cfg=rs.conf()
cfg.members[0].host=”172.17.0.29:27017”
rs.reconfig(cfg)

Diğer üyeleri de eklemek için aşağıdaki komutları kullanabilirsiniz.

rs.add(“172.17.0.30:27017”)
rs.add(“172.17.0.31:27017”)

Tekrar rs.conf() komutuyla diğer üyelerin de eklendiğini görebilirsiniz. rs.conf() dediğinizde her bir üyeye ait bilgileri göreceksiniz. Burda benim bahsetmek istediğim özellik priority. Priority, master seçilirken öncelikli olarak kullanılan alandır. Mesela ilk container 1.0 diğerleri 0 priority değerine sahip olursa, ilk container her zaman seçilen master olacaktır. Örnek aşağıdadır:

cfg=rs.conf()
cfg.members[0].priority = 1
cfg.members[1].priority = 0
cfg.members[2].priority = 0
rs.reconfig(cfg)

Priority hakkında daha fazla bilgiye buradan ulaşabilirsiniz

Son olarak anlatmak istediğim konu Replica Set’in durumuyla ilgili bilgi veren rs.status() komutu. Bu komutu çalıştırdığınızda aşağıdaki gibi bir çıktı alacaksınız.

07

Burada PRIMARY üyenin ne zaman seçildiğini electionTime ile, SECONDARY üyelerin nereye senkronize olduklarını syncingTo ile, SECONDARY üyenin PRIMARY üyeye ne zaman kontrol mesajı gönderdiğini lastHeartbeat, ne zaman yanıt aldığını lastHeartbeatRecv alanından anlayabilirsiniz.

Bu makalede temel olarak MongoDB Replica Set nasıl kurulduğundan bahsetmeye çalıştım. Buradaki anlatım en temel düzeyde olmasına rağmen epeyce uzun oldu. Bir sonraki makalede sizlere Replica Set mimarisinde günlük hayatta nasıl sorunlarla karşılaşılıyor ve bunların çözümleri nelerdir onlardan bahsedeceğim.

NoSQL’in Kısa Tarihi

1 NoSQL’in kısa tarihi

1.1 Eski Güzel Günlerin Bitişi

Eskilerin geçmişi “ah o eski güzel günler” diye andığını ve yeniler için ise “o eski güzel günlerin” henüz gelmediğini bilerek yaşadığımızda, her yeni oluşumun kendine has güzellikleri ile geldiğini de bilmeliyiz. Bilgi teknolojileri dünyasının eski güzel günlerinde, eldeki problemin çözümü için gerekli olanlar az sayıda seçenek arasından seçilirdi. Genel maksatlı bir programlama dili, bir veri tabanı çözümü, bir donanım seçilir ve gerisi şelale tipi proje planının uygulanmasından ibaret olurdu.

Özellikle 2000 li yılların başından itibaren yaşanan gelişmeler ile “eski güzel günleri” bir daha gelmemek üzere geride bıraktık. Hayatın ve bilginin hızlı akışı ile eski alışkanlıklar bir bir değişiyor. Bu oturmuş bir düzende kaçınılmaz olarak “eskiler” ve “yeniler” arasında bir mücadele yaşanmasına da yol açıyor. Eskiler derken, her şeyi kastediyoruz, insanlar, teknolojiler, yöntemler, alışkanlıklar.

Tek bir yazıya sığmayacak kadar geniş olan bu konuda, bu yazımızda amacımız birçok kaynaktan zaten gelişmeleri takip eden siz okurlara farklı bir açıdan genel değişiminin ne olduğunu göstermek olacaktır. Bu yazı fikri, internetten izlediğim bir Renk değiştirme kart numarası videosunu seyrederken uyandı. Bu videoda numarayı yapan kişi, destenin içinden karşısındaki kişinin seçtiği rastgele bir kartın arka rengini el çabukluğu ile değiştiriyor. Numara bittikten sonra ise bu numarayı nasıl yaptığını daha geniş açıdan çekim yapmış bir kameranın yardımı ile görüyoruz. O da ne? Meğerse değişen sadece kartın rengi değilmiş, ekranda görülen her şeyin rengi değişmiş oysaki. Bu video bize dikkatimizi verdiğimiz şeyden büyük bir resim olduğunu ve bu resmi anlamanın gerçek değişimi anlamak olduğunu gösteriyor. Bu nedenle önce büyük resimde nelerin olduğuna bakarak başlayacağız.

Değişim Öncesi

1.2.1 Büyük Resim

2009 yılına kadar, verilerin saklanması ve erişilmesi probleminin çözümü için geliştirilmiş başka veritabanı sistemleri var olsa da, İlişkisel Veri Tabanı Yönetim Sistemleri (RDBMS) bilgi teknolojileri dünyasında ezici bir üstünlük kurmuştu. Bu nedenle ‘veri tabanı’ dendiğinde ilişkisel kelimesi kullanmaya gerek duyulmazdı.

1960 lı yıllara geri gittiğimizde, verilerin saklanması ve bu saklanan verilere hızlı ulaşım problemi için birkaç çözüm önerilmişti. Bunlardan hepimizin bildiği ilişkisel veri tabanları, kümelerin üzerinde tanımlanan ilişkilere dayanmaktadır. Bu yapı üzerine kurgulanan Yapısal Sorgu Dili (SQL), esasen iki kümenin kesişimi, birleşimi, farkı, kartezyen çarpımı gibi kavramların komutlara dönüştürülmüş halidir. Hal böyle olunca, saklanan verinin belli bir yapıda olması, bu yapının da tablolara dayanması çok şaşırtıcı gelmiyor. Esasen bunun arka planında, iş dünyasında dijitalleşme olmadan çok önceleri yaygınlaşan tablo formatlı muhasebe tabloları ve bunun devamı olan ve günümüzde de yaygın olarak kullanılan MS Excel gibi SpreadSheet uygulamalar vardır.

Bu temel yapının üzerine, veriye erişimin hızlanması için indekslemeler, güvenlik için erişim yetkileri, yerden tasarruf için sıkıştırma algoritmaları, zaman içinde çıkan bu problemlerin dışındaki önemli bazı problemlerin çözümü için Atomiklik, Tutarlılık, İzolasyon, Sağlamlık (ACID) kelimeleri ile özetlenen özellikler geldi.

İlk Alternatifler

İlişkisel veri tabanlarına alternatif arayışlarının geçmişi 1970 lerin sonlarına gider. Alternatifler derken üç ayrı grubun var olduğunu baştan söylemekte fayda var.

1.2.2.1 Birinci grup

1.2.2.1.1 NoSQL veri tabanları

Veri modelinin ilişkisel olduğu fakat sorgu dilinin SQL olmadığı gruptur. Bu grubun iyi bir örneği olan Ingres veritabanı 1970 ile 1985 arasında gelişti ve 1980 lerin başında ORACLE ile rekabet ediyordu. Sorgu dili SQL değil Quel di. Her ne kadar rekabete dayanamadıysa da, küllerinden Sybase, MS SQL Server gibi veri tabanları doğdu. Hatta Postgres projesi ile (Post Ingres) PostgreSQL e evrilmiştir.

NoSQL kelimesini ilk olarak kullanan, 1998 yılında geliştirdiği açık kaynak kodlu ilişkisel veri tabanına sorgulama dili olarak SQL kullanmadığı için NoSQL DB ismini veren Carlo Strozzi dir. Kendisi bu nedenle, şu anda ilişkisel olmayan veri modeline dayanan veri tabanları için yaygın olarak kullanılan NoSQL kelimesi yerine NoREL (No Relational) kelimesinin daha uygun olacağını belirtmiştir. Yani ilk kullanıldığında NoSQL gerçekten ‘SQL i olmayan’ anlamında kullanılmıştır.

Strozzi

1.2.2.2 İkinci grup

İlişkisel veri modeline dayanan ama kayıtların satır bazında değil sütün bazında tutulduğu veritabanlarıdır.

1.2.2.2.1 Kolon bazlı ilişkisel veri tabanları

1996 yılında Sybase IQ, ilk kolon bazlı analitik platform oldu.

1.2.2.3 Üçüncü grup

Veri modelinin de farklı olduğu veri tabanlarıdır.

1.2.2.3.1 Nesne ilişkili veri tabanları

Nesne tabanlı yazılım dillerinin yaygınlaşmaya başlaması ile birlikte nesne ilişkili veri tabanları (object relational databases) öne çıksa da yaygınlaşması mümkün olmamıştır. En büyük avantajları veritabanı ile uygulamanın geliştirildiği programlama dilinin aynı veri modelini kullanıyor olmaları idi.

1980 sonrasında nesne tabanlı veri tabanları konusunda ciddi çalışmalar ticari ürünlere dönüştü. GemStone (Smalltalk), Objectivity/DB gibi nesne veri tabanları örnek verilebilir. 1981 de ‘UNIX üzerindeki bilgi’ Informix (INFORMation on unIX) adı verilen nesne ilişkili bulit-in desteği olan Informix DB kullanılmaya başlandı.

1.2.2.3.2 Anahtar-değer (Key-Value) veri tabanları

Verilerin bir anahtar değere ve buna karşılık gelen herhangi bir tipteki veriyle birlikte tutulmasıdır. Örnek olarak telefon rehberindeki telefon numaraları ve karşı gelen ad soyad bilgilerini verebiliriz. Tabii anahtar değerin tekil olması zorunluluğu vardır. Bunun bildiğim en erken örneği 1970 li yılların başında MUMPS (Massachusetts General Hospital Utility Multi-Programming System) ın şemasız M veri tabanıdır.

1.2.2.3.3 Graf veri tabanları

Graf teorisine dayanan ve verinin düğümler ve bu düğümleri birbirine bağlayan bağlantı çizgileri ile ifade edildiği bir veri tabanı yapısıdır. Bu bağlantılar doğrudan gösterge (pointer) denen bellek adresi ile verildiği için indeksleme ihtiyacı olmadan hızlı erişim olanağı verir. Graf teorisinin temel uğraşları olan iki düğüm arasındaki en kısa yolun bulunması, alt grupların belirlenmesi gibi sorulara graf veritabanları ile hızlı şekilde cevap bulunabilir. Uzun yıllar ilişkisel veritabanlarının gölgesinde kalmış olsalar da son zamanlarda yeniden popülerlik kazanmaya başlamıştır.

1.2.2.3.4 Alana özel veri tabanları

Bu kategoride, belli bir iş alanına özel ihtiyaçları karşılamak için özel olarak dizayn edilmiş veritabanlarını toplayabiliriz. Bunlara örnek, 1980 li yılların başından itibaren Electronic design automation (EDA or ECAD) entegre devre veya baskılı devre kartları gibi elektronik sistem tasarımı yapan şirketlerin kullandıkları yazılımları desteklemek için geliştirilmiş EDA database elektronik dizayn veritabanı. 1986 yılında kurulan Amerikan Synopsys şirketi bu alanda önde gelen firmadır.

1.3 Değişimin başlaması

Anlatılan bu büyük resmin değişiminde, Web in 90 lı yıllarda gelişip yaygınlaşmasının katkısını en ön sırada görebiliriz.

1.3.1 CAP Teoremi

Bu bakımdan CAP teoremi olarak anılan ve

“Dağıtık bir sistem inşa ederken, olmasını isteyeceğiniz üç özellikten; tutarlılık (consistency), cevap verebilme (availability) ve ağdaki parçalanmalara tolerans (tolerance of network partitions) dan sadece ikisine sahip olabilirsiniz.”

şeklinde özetlenebilen teoremin ilk olarak Eric Brewer tarafından 1998 yılında ortaya atılması şaşırtıcı değildir. Temel bileşenler;

CAP Teoremi dağıtık sistemler konusunda çalışan araştırmacıların ve uygulayıcıların zaman zaman eleştirdikleri, üzerinde tartışmaların yapıldığı bir konudur. Bu bakımdan, Eric Brewer’in 12 yıl sonra konu hakkında yayınladığı yazısı meraklısının ilgisini çekebilir. Konu hakkındaki örnek bir tartışma için Daniel Abadi’nin yazısına ve gelen yorumlara bakabilirsiniz. Esasen bu üç özellikten; Tutarlılık ve Cevap verebilme, ağda parçalanma olduğu zaman birbirleri ile rekabet eden iki özelliktir. Bu teoreme pratik bir uygulama örneğini Brewer şu şekilde veriyor. ATM lerde para çekme, para yatırma ve bakiye sorgulama sistemini ele alalım.

Tutarlılık her zaman istenen bir özellik midir? Yani C A yı yener mi? Teorik olarak evet, fakat pratikte hayır. Yüksek hizmete açık olma (availability) yüksek gelir ve müşteri memnuniyeti anlamına gelmektedir. Ana kural bakiyenin sıfır veya üstünde olmasıdır. Bunu ihlal edecek operasyon para çekme olacağı için buna özel önem verilmelidir. Diğerleri her zaman çalıştırılabilir. ATM dizaynı yapanlar ağda kopma olduğu zamanlarda para çekmeye engel olmalıdırlar. Bu ise çok kısıtlayıcı bir etki olarak hizmete açık olmayı (availability) düşürür. Bunun yerine tek başına çalışma modunda belirlenen bir miktar kadar para çekilebilmesine izin vermek çözüm olabilir.

1.3.2 Hadoop un doğuşu

Web in hızlı bir gelişim sürecine girdiği 2000 li yılların başlarından itibaren oyunun kuralları yavaş yavaş değişmeye başladı. Bu yavaş değişim 2009 yılında ki büyük patlamaya kadar daha çok webde doğan Google, Yahoo!, Amazon gibi şirketlerin, kendi problemlerine çözüm çabaları olarak bilindi ve sınırlı bir alanda etkili oldu. Birçok bilgi teknolojileri çalışanı dahi gelişmelerden habersizdi. Değişimin fitilini ateşleyen Google un yaptığı çalışmaları makale olarak yayınlaması, bilgi birikimini kısmen de olsa dünya ile paylaşması oldu. 2003 yılında The Google File System, 2004 yılında MapReduce, 2006 yılında Bigtable makaleleri yazılım dünyasında heyecan uyandırdı. Açık kaynak kodlu, dağıtık, kümeleme yapısı üzerinde veri işleme yapabilen mimari üzerine kurulmuş bir çözüm için şartlar hazırlanmıştı.

2002 yılında açık kaynak kodlu bir Web arama motoru yapmak için kolları sıvamış olan Mike Cafarella ve Doug Cutting topladıkları text veriyi işleme konusunda uygun bir çözüm üretmeye çalışırken Google un makalelerini okudular. Nutch ismi verilen ve amacı web i tarayıp topladığı veriyi indeksleyerek etkin bir arama motoru yapmak olan ana projede ihtiyaç olan, dağıtık bir veri işleme altyapısı olarak, Cutting in Hadoop ismini verdiği benzer bir yazılımı geliştirmeye başladılar. Bu noktada Yahoo!, Cutting i işe alarak oyuna dahil oldu. Altı ay içinde Yahoo! nun kullandığı teknolojilerden birisi oldu, iki sene sonra ise vazgeçilmezi haline geldi.

Hadoop ile güçlendirilen veri analizi, reklam alanında kişilerin ilgileri ve reklamın hedef kitleye ulaşması konusunda yapılan analizlerde kullanıldı. Yapılan analizlerden birisi kişilerin browser homepage ini değiştirmesine neden olan hikayeyi ortaya çıkarmaktı. Yahoo on milyonlarca dolar harcadığı tahmin edilen Hadoop u açık kaynak olarak tutmaya devam etti. Bu değişimin ateşinin çok uzaklardan görülebilmesini sağladı. 2008 yılında Microsoft, kendi arama sistemini geliştirmek için doğal dil işleme yöntemlerini kullanarak arama sorgusu problemini çözme konusunda çalışan ve Hadoop a destek veren start-up firmalarından Powerset‘i satın alarak oyuna girdi. Satın alma sonrasında bu desteğin devam etmesi konusunda yeşil ışık yakarak Hadoop un geliştirilmesine destek verenlere katıldı. Facebook elindeki milyarlarca fotoğrafı işlemek için Hadoop teknolojisini kullanmaya başladı.

Dough Cutting ve Hadoop :)
Dough Cutting ve Hadoop :)

1.3.3 Değişimin katalizörleri

1.3.3.1 Çevik yöntemler

Bu yöntemler şemasız çalışmayı destekleyen yöntemlerdir. BT projelerinin iş ihtiyaçlarından kaynaklı hızlı değişim ve gelişim taleplerine cevap verebilmesi nedeni ile çevik (agile) yöntem ve benzerlerinin popülerliği artmıştır.

1.3.3.2 Polyglot programlama

Gittikçe artan bir şekilde, genel uygulama dilini belirlemek ve o dilde uzman geliştiricileri projeye dahil etmek kendi başına yeterli olmadığı, çıkan alt problemleri çözmek için farklı programlama dillerini kullanmanın olağanlaştığı bir döneme girildi. Tek bir programlama dilinin yetmediği bir dönemin başladığını ilk haber verenlerden birisi olan Neal Ford, 5 Aralık 2006’da bloğunda Polyglot Programming‘i tanımlarken şöyle demişti:

“tek bir genel maksatlı dil ile uygulama yazma devri kapanmıştır, alana özel dilleri eklemeye başlayacağız.”

Bu iddia temel olarak bir lisanı öğrenen insanların diğer lisanları öğrenirken temel kavramları zaten bildikleri için çok hızlı bir şekilde öğrenebileceklerine dair yapılan araştırmalara dayanmaktadır. İnsanların konuştukları dillerde olduğu gibi, programlama dillerinde de geçerli bir çıkarım olduğu düşüncesi temelinde şekillenmektedir.

1.3.3.3 Polyglot dayanıklılık

Scott Leberknight, 15 ekim 2008 de yazdığı yazıda programlama dillerindeki polyglot kavramını veritabanı dünyasına uyarlıyor. Dayanıklılık (persistance) kelimesi, zor koşullar altında ayakta durma, kendine verilen görevleri yerine getirme için kullanılmaktadır. Polyglot Persistance, veri tabanlarından beklenen persistance özelliğinin tek bir veri modeline dayalı olarak istenen şekilde sağlanmasının, mevcut problemlere istenen performans özelliklerini kazandırmak için yeterli olmadığı fikrini savunuyor. Farklı veri modellerine dayanan birden fazla veri tabanlı çözümlerin yaygınlaşacağını iddia ediyor. Bunun anlamı aşağı yukarı benzer yapıya sahip, benzer performans özellikleri olan alternatifler içinden bir Veri Tabanı Yönetim Sistemi (DBMS) seçme devrinin kapanmasıdır. Eski güzel günlerin baskın ilişkisel veri modeli artık hiç düşünülmeden seçilen bir veri modeli olmaktan çıkmaya başlamıştır.

1.3.3.4 Entegrasyon

24 Kasım 2008’de yazdığı bir yazıda Martin Fowler; 1980 li yıllardaki nesne ilişkili veri tabanlarının yaygınlaşmamasının en önemli sebebinin, ilişkisel veri tabanlarının bir entegrasyon aracı olarak ve SQL in bir protokolmüş gibi değişik uygulamaların birbiri ile olan veri alış verişinde kullanılıyor olmasından kaynaklandığını söylemektedir. Alternatif yolların özellikle Webservice lerin çıkması ile, çoğunlukla XML formatlı text dokümanlar kullanılarak uygulamaların birbirleri ile sql olmadan konuşmaları sağlanarak, farklı veri tabanları kullanmanın önündeki en önemli engelin aşıldığını öne sürmektedir. Her uygulamanın kendi veri modeline en uygun olana karar vermede hiç olmadığı kadar özgür olduğunun değişimin en önemli sebebi olduğunu dile getirmiştir. 16 Kasım 2011 tarihli yazısında da konuyu daha geniş kitlelere duyurmuştur.

1.4 NOSQL 2009

Last.fm isimli, kişilere dinledikleri müziğe göre önerilerde bulunan (music discovery & recommendation system) bir firmanın Londra’daki ofisinde çalışan Johan Oskarrson, yukarıda özetini verdiğimiz gelişmeler sonrası popüler olan Hadoop konusunda son gelişmelerin konuşulup tartışılacağı Hadoop Submit e katılmak için Haziran 2009’da San Francisco ya gitmeye karar veriyor. Konu ile ilgili birçok kişinin orada olacağı düşüncesi ile katılımın ücretsiz olduğu açık kaynak kodlu, dağıtık, ilişkisel olmayan veri tabanları konulu bir etkinlik NOSQL meetup düzenlemek istiyor ve bloğunda bunu şöyle duyuruyor:

‘To make the most of the flight money I’m putting together a free meetup about “open source, distributed, non relational databases” or NOSQL for short.’

Oskarrson, kısa NOSQL kelimesini büyük ihtimalle tweeter da kullanmak ve akılda kalıcı olması nedeni ile üzerinde çok düşünmeden seçmişti. İlgi çok yoğundu, mevcut 100 kişilik katılımcı kapasitesi beş saatte doldurulunca, yoğun talep üzerine ek 50 kişilik kontenjan da açılmıştı.

O toplantıda kapalı kaynak kodlu Google un BigTable ı, Amazon un Dynamo su ve Yahoo! PNUTS’ından ilham alınarak yapılan, açık kaynak kodlu NRDBMS ler (NonRelational Database Management Systems) konuşuldu. Bu toplantı ilk olarak NoSQL kelimesinin ilişkisel olmayan (non relational) olarak kullanılmaya başlanması olarak alınabilir. Toplantıdaki içeriklere ulaşmak için tıklayın.

NoSQL veritabanlari

1.4.1.1 İsim arayışları

NoSQL isminin mevcut harekete, uygun olmadığı yolundaki eleştiriler alternatif önerileri ile birlikte geldi. Adam Keys tarafından Ağustos 2009’da Post-relational kelimesi önerildi. nosql-database.org‘un arşivlerine başlıklarda geçen NoSQL ve NOSQL kelimelerinin kullanımı olarak baktığımızda, NOSQLin 2 Kasım 2009 da Debasish Ghosh nun ‘NOSQL Movement’ yazısında ‘Call it NoSQL (~SQL) or NOSQL (Not Only SQL), the movement has a mission.’ ile geçtiğini görüyoruz. Yine aynı arşivde en son 15 Aralık 2009 da NOSQL i Nati Shalom un bloğundan alınan yazının başlığında ‘The Common Principles Behind the NOSQL Alternatives’ ve yazıda aşağıdaki resim görülüyor.

Not only sql

Sonrasında Not Only SQL açıklaması kullanılmaya devam ediliyor fakat NoSQL şeklinde yazılma kabul görüyor. Bu sitenin ana sayfasında da belirtildiği üzere:

‘The original intention has been modern web-scale databases. The movement began early 2009 and is growing rapidly. Often more characteristics apply such as: schema-free, easy replication support, simple API, eventually consistent / BASE (not ACID), a huge amount of data and more. So the misleading term “nosql” (the community now translates it mostly with “not only sql“) should be seen as an alias to something like the definition above.’

Sonuç olarak yanlış anlaşmalara yol açsa da NoSQL in bir alias olarak kullanılması genel kabul görüyor.

Ekim 2009 da Atlanta da NoSQL Doğu konferansında kullanım olağanlaştı.
Ekim 2009 da Atlanta da NoSQL Doğu konferansında kullanım olağanlaştı.

1.5 Günümüz

Açık kaynak kodlu, dağıtık, kümeleme yapısı üzerinde veri işleme yapabilen mimari üzerine kurulmuş çözümlerin sayısının arttığı, RDBMS ve NoSQL sistemlerin birbirlerine benzemeye başladığı bir dönemi yaşıyoruz. NoSQL ve Hadoop çözümlerinde SQL e benzeyen dillerin daha çok kullanılıyor olması, NoSQL veri tabanlarında kaçınılan join operasyonunun kolay ve etkin bir şekilde yapılabilmesini sağlayan ürünlerin ön plana çıktığı, SSD diskler gibi disk teknolojilerindeki gelişimlerin veritabanlarının mimarisine etki ettiği bir zaman dilimindeyiz. RDBMS lerde olan birbirine çok benzeme, en azından yakın zamanlarda NoSQL veritabanları için geçerli olmayacak gibi görünüyor. Bir projede farklı veritabanları kullanmanın sıradan olduğu bir döneme giriyoruz. Stream verinin işlenmesinin yaygınlaşması sonucu dağıtık işleme yapma özelliğinin batch ile birlikte stream özelliği kazandığını da görüyoruz. Bu ise diske yazmadan RAM yani bellekde verilerin işlenmesine dayanan in-memory veritabanlarının daha çok kullanıldığı bir uygulama mimarisine götürüyor bizleri. Veritabanına özel saklama motoru (Storage engine) kullanmak yerine probleme uygun saklama motoru kullanmaya izin veren veri tabanlarının öne çıktığını görüyoruz. Hatta yıllardır kullanılan saklama motorları yenileri ile değiştirilmeye veya alternatif olarak sunulmaya başlandı. Örnek olarak CouchDB nin yeni saklama motoru ForestDB Ekim 2014’de duyurulmuştu. MongoDB ninki okuma yoğun çözümler için MMAP, yazma yoğun çözümler için yeni storage engine WiredTiger, veya 3rd party diğer motorlar kullanılabilmektedir.

1.6 Sonuç

Yeni BT dünyasında, iş kullanıcılarının verilere erişim ve analiz konusundaki aylar alan ve ciddi maliyetler getiren isteklerinin karşılanması için NoSQL seçenekler yeni alternatifler sunuyor. Bu alternatiflerin değerlendirilmesi için eski alışkanlıkların değiştirilmesi gerekiyor. Yeni tip yazılımcı, veri analisti, veri bilimci kısaca veriden değer üretenleri daha çok konuda bilgi sahibi olmaları gerekecek dinamik bir gelecek bekliyor. Bu yazının bu anlamda faydalı olacağını umuyorum.

R Programlama Dili

R_logo.svgBu yazımızda, veriyi anlamlandırmak için kullanılan analitik yöntemler için geliştirilmiş istatistiksel paket ve programlama dilleri içinde son yıllarda öne çıkan bir seçenek olan ve iki milyon kullanıcısı olduğu söylenen R programlama dili nin sağladığı avantajlara kısaca bakacağız. Özellikle büyük veri işlemede de etkin bir şekilde kullanımının örnekleri açıklandıkça bu dilin daha da popüler olacağı şüphesiz. Son olarak, R dili üzerine büyük veri ambarları ve Hadoop kapsamında kurumsal çözümler üreten Revolution Analytics firmasının Nisan 2015 başında Microsoft firması tarafından satın alınması bu trendin devam edeceğinin en büyük kanıtı.

Dünyada popüler ve yaygın olarak kullanılan programlama dilleri için bazı peryotlarda çeşitli indeksler ve sıralamalar yayınlanıyor. Bunların içinde benim takip ettiğim indeks, on yıldır aylık olarak yayınlanan TIOBE index. Nisan 2015 sıralamasında R dili 19 uncu sırada ve analitik dünyasının devi SAS firmasının SAS programlama dilinin 2 basamak üstünde. Bu denli yoğun rekabetin olduğu bir alanda nasıl oluyor da açık kaynak kodlu ücretsiz bir yazılım böyle bir başarı kazanabiliyor? Yıllarca SAS programlama dilini kullanmış bir veri madencisi olarak bu konudaki değerlendirmelerimi, ayrı bir yazıya bırakarak R programlama dilinin temel özelliklerine değinerek yazımıza başlayalım.

İstatistiksel çıkarım yapmak için kullanılan teknik ve algoritmaların hazır olarak kullanımı için geliştirilen kütüphaneleri de içeren, buna makine öğrenmesi algoritmalarının da eklendiği R dilinin fonksiyon tabanlı ve nesne bazlı bir dil olması ve rakiplerine görece daha yeni bir dil olması en büyük artılarından. Temel matematiksel işlemlerin yapılması dışında, karmaşık matris işlemlerinin bir satırlık kod ile yapılıyor olması, açık döngü yapıları yerine alternatif olan gizli döngülere izin veren etkin yapısı, dile yeni başlayanlar için sıkıntı yaratsa da ilerleyenler için büyük imkanlar sunuyor.

Ayrıca, açık kaynak kodlu ve ücretsiz ulaşılabilmesi, çok geniş kitleler tarafından kullanılan ve birçok veri işleme ve veri madenciliği yazılımının çözümüne dahil ettiği ortak çözüm dili olma yolunda emin adımlarla ilerlemesini sağlamaktadır.

R programlama dilinin nesne tabanlı bir dil olduğunu söylemiştik. Bu nedenle kullanılan her şey bir nesnedir.

01

Komutların genel yapısı,

çıktı <- komut(<girdi(ler)>)

şeklindedir. Her sonuç bir nesne olarak tutulur ve başka bir fonksiyona parametre olarak gönderilebilir. Örneğin c ile gösterdiğimiz sayıların ortalamasını almak için

Ortalama <- mean( c )

demek yeterlidir. Matematiksel işlemler ve istatistiksel hesaplamaları kolayca yapmak üzerine kurgulanmış bir dil olarak, matris ve vektör hesaplamaları çok kolaylaştırılmıştır. Matris oluşturma, matris çarpımı ve transpozunu alma işlemleri oldukça kolaydır.

02

Eldeki verinin işlenmesi ve analizi için de gayet uygun bir dildir ve veri bilimcilerinin Python dili ile birlikte kullandıkları zaman, veri işlemede her problemin üstesinden gelebilecek bir ikili olurlar.

Grafiksel analiz ve işlemler R programlamanın güçlü yanlarından birisidir. Temel faydaları;

  • Yaptıklarımız manuel işlemler olmadığı için kolay tekrar edilebilir geliştirilebilir, aktarılabilir, otomatikleştirilebilir.
  • Bir analizi birçok değer için tekrar etmek çok kolaylaşır.
  • Veriyi işleme kolaylaşır.
  • Programlama ile benzer problemlere hızlı çözüm mümkün olur.

Bu amaçla gelişmiş bir komut seti sunulmaktadır. Bunlardan bazılarını kısaca görerek devam edelim. R dilinin kütüphanelerle zenginleştirilmiş yapısı içinde base R olarak isimlendireceğimiz ana paketin içinde bulunan plot komutu ile aşağıdaki grafikleri kolayca elde edebiliriz.

03

04

Başka bir örnek, ortalaması 0, standart sapması 1 olan bir normal dağılımı 500 deneme için şu şekilde bulup, grafiğini çizebiliriz.

05

Bu çok basit grafik örnekleri verdikten sonra, istatistiksel hesaplamaların nasıl yapıldığı konusuna da girerek, bu tür bir işte geçirilen adımları da içerecek şekilde daha somut bir örnek ile devam edelim.

İhtiyacımız olan veriyi Dünya Bankası web adresinden Ülkelerin Nüfus Sayısı Değişim Oranları Verisi olarak alıyoruz. Kaynağından CSV formatında aldığımız verinin, R dilinde bir nesne olarak yüklenmesini çok kolay bir şekilde yapıyoruz. Bunun için benim de kullandığım ve gayet memnun olduğum IDE RStudio yu kullanırsanız, menüler ile de bu işlemi gerçekleştirebilirsiniz.

06

Veriye kısaca bakacak olursak, ülkelerin 1960 yılından itibaren yapılan nüfus sayımları sonuçlarına göre, senelik nüfus sayısı değişim oranlarını yüzde olarak bize veriyor. Şimdi R dilini kullanarak bu verileri kısaca analiz edelim. Öncelikle gereksiz olan kolonlardan kurtulalım.

07

Veriyi incelediğimizde bir zaman serisi verisi olduğunu görüyoruz. Zaman serileri, düzenli veya düzensiz aralıklarla değişkenin ölçülen değeri ile ölçüm zamanının sıralama ilişkisinin dikkate alınarak veri olarak saklanması ile oluşan matematiksel yapılardır. Elimizdeki veride ölçülen değişken nüfus değişim oranı, zaman dilimi yıldır. Zaman serileri; enerji, havacılık, parakende, telekom, finans, askeriye, bilimsel deney vb birçok alanda karşımıza çıkan ve Şeylerin İnterneti (Internet of Things – IOT) olarak isimlendirilen yeni büyük verinin temelidir. Veri üreten ve bu veriyi internet yolu ile aktaran akıllı cihazların yaygınlaşması ile yakın zamanda iş dünyasının karar alma mekanizmalarının kökten değişeceği görülmektedir. Öyle ki son birkaç yıldır zaman serileri için geliştirilen TSDB gibi özel veritabanlarına şahit oluyoruz.

Nüfus değişimi verilerimize dönecek olursak, 1960 yılı bütün ülkelerin verilerinden yola çıkarak, şöyle bir grafiğe çok kolay erişebiliyoruz.

08

Bu grafikten 1960 yılında ortalama nüfus artış hızının ikiyi biraz geçtiğini, ekstrem değerleri yuvarlak işaretlerle görüyoruz ve maksimumda %10 a yakın bir artışın olduğu ülke olduğu negatif olan yani nüfusu azalan bir ülke de olduğunu görüyoruz. Bu çizimlerin nasıl yorumlanacağı ile ilgili detay merak edenler tıklayın.

Üç ülke için 1960-2013 yıllarındaki bütün verileri değerlendirerek bakacak olursak;

09

10

Summary komutu ile aldığımız temel istatistiklere bakarak hemen görebiliyoruz ki nüfus artış ortalaması tüm dünya için 1960 dan bu yana düşüş trendinde.

11

Bunu grafik olarak da görebiliyoruz. Bütün dünyada 1960-2013 arasındaki nüfus değişim oranlarının yıl bazındaki temel istatistiklerini tek grafikte görmek mümkündür.

12

13
Dünyanın nüfus değişim oranlarındaki değişimin 1980 yılı mallonrasında, azalma trendinde olduğunu görüyoruz.

İncelediğimiz verinin zaman serisi olduğunu tespit etmiştik. Bu veriyi hazır fonksiyonları kullanarak kolayca işleyebilmek için R dilindeki ts sınıfını kullanabiliriz. Bunun için yılları gösteren kolonların satır olarak bulunması gerekiyor. Bu noktada veriyi uygun hale getirmek için bir ön işlem gereksinimi doğuyor. Bu bize R dilinin bu konudaki yeteneklerini göstermek için fırsat sunuyor. Bu amaçla R nin temel veri tiplerinden data.frame i, transpoze eden fonksiyonu kullanabiliriz ama bunu yaparken ilk kolondaki ülke isimlerini ayırmak, işlemin püf noktasıdır.

14

Bu şekilde veriyi aşağıdaki formata getirmiş olduk.

15

R dilinin tanımlı sınıflarından ts class ına geçirebiliriz. Verimizde zaman boyutunda her yıl bir gözlem/ölçüm olduğu için, başlangıcı ve frekansı verirken bunu dikkate alıyoruz.

16

Bu şekilde birden fazla ülke için 1960-2013 arasındaki çoklu bir zaman serisini elde etmiş oluyoruz.

17

Zaman serilerinin bir alt bölümünü almak istersek şu şekilde yapabiliriz.

18

Burada 1985-2013 aralığındaki zaman dilimi Türkiye verisi için basit bir lineer model (lm) yapabiliriz.

20

19

Temel grafik paketi ile çizimler görsel olarak zayıftır. Fakat yeteneklidir.

21 22

Bu noktada temel R içinde olmayıp ek paket olarak geliştirilmiş olan görsel yönden güçlü grafikler veren ve ek özellikler katan ggplot2 kütüphanesi’nden de bahsetmekte fayda var. Örnek olarak yukarıdaki grafik ggplot2 ile şu şekilde görselleştirilebilir.

23 24

Burada ggplot2 nin geliştirilmesi gereken bir noktadan bahsetmekte fayda var, zaman serilerini desteklemiyor. Bu nedenle veriyi dönüştürmek zorunda kalıyoruz. Bunun için aşağıdaki tablo üzerinde bazı değişiklikler yapmak gerekiyor. Her gözlem zamanı bir kolon ile gösterildiği formattan, her gözlemin yatayda olduğu bir formata geçmek gerekiyor. Bu işleme teknik olarak de-pivoting denmektedir. Bu işlem ile her bir satırda; ülke kodu, yıl ve gözlem değeri ayrı ayrı yer alacaktır. Elimizdeki veri şu şekilde,

25

De-pivoting işleminin R dilinde melt komutu ile ne kadar kolay yapılabildiğini görelim. Bunun için reshape paketine ihtiyaç duyuyoruz.

26 27

Bu formattaki veriden ilgilendiğimiz ülkelerle ilgili veriyi filtreleyip ggplot2 nin gelişmiş grafikleri ile görelim.

28 29

Sonuç

Büyük veriyi işlerken veriyi depolamak kadar önemli olan depolanan veriden sonuç çıkarma işlemi için etkili ve üründen bağımsız bir analitik dile ihtiyaç bulunmakta. Bu dil için en çok öne çıkan R dilinin analitik karar alma süreçlerinde ve veri analizinde gittikçe daha çok kullanılacağını görüyoruz. Bu nedenle bu konularda çalışan veya çalışmak isteyen veri bilimcisi ve analistlerin R dilini iyi bir şekilde öğrenmelerinde büyük fayda vardır.

Hadoop Nereden Başlamalıyım?

devveriDevveri.com takipçileri arasında Hadoop teknolojileri ile ilgilenen, kendini bu konuda geliştirmek isteyenlerden birçok email alıyorum. En çok sorulan soru “Nereden başlamalıyım?” oluyor. Bu konularda kendinizi geliştirmek istiyorsanız önünüzde çok fazla seçenek var.

1. Eğitim

Bir konuyu hızlıca öğrenmek, hemen uygulamaya dökmek isterseniz en iyi yolu bu konuda tecrübeli kişilerden eğitim almak. Cloudera ve Hortonworks firmalarının eğitimleri bu konudaki en iyi seçenek. Aslında bu eğitimler genelde yurtdışında oluyor fakat Dilişim firması Cloudera’nın Türkiye partneri olarak bu eğitimleri Ankara ve İstanbul’da Türkçe olarak veriyor, zaman zaman buradan duyuruyoruz. Benzer eğitimler oldukça da duyurmaya devam edeceğiz.

Bunun dışında çevirim içi eğitimler var, örneğin Udemy üzerindeki gibi.

2. Sanal Makineler

Hadoop kurulumu ile uğraşmadan, hazır kurulu sanal makineleri indirip kurcalayabilirsiniz. Unutmayın, gerçekten uygulama yapmadan bir konuyu öğrenmeniz mümkün değil. Bu sanal makinelerden birisi ile örnekleri rahatça çalıştırabilirsiniz.

Cloudera Quick Start VM
Hortonworks Sandbox

3. Çevirim İçi Örnekler

Türkçe içerik açısından en zengin site tabi ki Devveri.com. Sitedeki yazıların hepsini incelemenizi tavsiye ederim. Daha fazlasını arıyorsanız başta Cloudera ve Hortonworks olmak üzere birçok sitede örnekler var. Bunlardan bazılarını aşağıda bulabilirsiniz:

Hortonworks Tutorials
Cloudera Tutorials
GetHue.com Tutorials
MapR Tutorials

4. Kitap

hadoop-the-definitive-guide

Hadoop konusunda başucu eseri olma özelliğini 4. baskısında da taşıyan Hadoop: The Definitive Guide kitabını almanızı ve baştan sona okumanızı mutlaka tavsiye ederim.

Bunun dışındaki kitapları size daha önce tanıtmıştık.

5. Sosyal Medya ve Blog’lar

Bunu yazmaya bile gerek yok aslında ancak bu konularda bilgili insanları sosyal medya üzerinden takip etmek, paylaştıkları yazılarını okumak da konuları yakından takip etmek açısından çok önemli.

OrientDB – Graph ve NoSQL Çözümü

orientdb_logo1Populerliği günden güne artan Çizge (Graph) veritabanları dünyasında OrientDB yetenekleri ile öne çıkıyor. Piyasada en çok bilinen Neo4J’den farklı olarak, OrientDB açık kaynaklı. Ayrıca destek almak istediğinizde Orient Technologies firması tarafından desteklenen kurumsal bir sürümü de mevcut.

OrientDB aslında sadece bir Çizge veritabanı değil, aynı zamanda döküman tabanlı bir NoSQL veritabanı. Tinkerpop Gremlin dilini desteklemesi, ACID, Multi-Master replikasyon, REST api ve en önemlisi SQL desteği ile bize harikalar vaadediyor. OrientDB’yi sevmemizin bir başka nedeni de dağıtık çalışabilmek için arka tarafta Hazelcast’den faydalanması.

Bu yazımızda OrientDB’nin kurulumunu, örnek bir Çizge veri yapısı oluşturmayı ve bununla basit bir ürün öneri sistemi yapmayı işleyeceğiz.

OrientDB oldukça küçük bir boyuta sahip. Uygun sürümü indirip açmamız kurulum için yeterli:

wget --output-document orientdb-community-2.0.4.tar.gz "http://www.orientechnologies.com/download.php?file=orientdb-community-2.0.4.tar.gz&os=multi"
tar xvf orientdb-community-2.0.4.tar.gz 
cd orientdb-community-2.0.4
bin/server.sh

Sunucu ilk seferinde ayağa kalkarken bize root şifresini soruyor. Bunu belirledikten sonra OrientDB’nin arayüzüne girebiliriz. Aslında konsol üzerinden de kullanılabilir ama OrientDB pek çok NoSQL’de eksik olan basit ama oldukça kullanışlı bir admin arayüzüne sahip. Bu arayüzden birçok işlemi gerçekleştirebilliyoruz. http://localhost:2480 üzerinden arayüzü açabiliriz. (Sizi ilk karşılayan ekran daki güneş manzarası da oldukça romantik)

Screen Shot 2015-03-06 at 00.10.05

Buradan yeni bir veritabanı oluşturmayı seçip ismini giriyoruz:

Screen Shot 2015-03-06 at 00.11.21

Girişi yaptıktan sonra karşımıza arayüz ekranı geliyor. Browse kısmında sorguları çalıştırabilir, Graph kısmında verileri görsel olarak inceleyebilirsiniz:

Screen Shot 2015-03-06 at 00.11.50

Örneğimizi gerçekleştirebilmek için Item ve User isimli iki sınıfa ihtiyacımız var. Burada Çizge veritabanında olduğumuz için veriler tablo değil sınıf olarak tanımlanıyor. Bu sınıflarda Vertex anlamına gelen V sınıfından türetiliyorlar. Vertex’ler arasındaki ilişkiler de Edge anlamına gelen E sınıfından türetiliyorlar.

Önce Item sınıfı ile başlıyoruz. Item nesnesini aşağıdaki komutla yaratıyoruz:

create class Item extends V

Ardından bu Item nesnesine id ve title isimli iki özellik ekliyoruz:

create property Item.id integer
create property Item.title string

Sınıf tanımından sonra örnek olması için birkaç Item yaratalım:

create vertex Item set id = 1, title = 'iPhone 6'
create vertex Item set id = 2, title = 'Samsung Galaxy S5'
create vertex Item set id = 3, title = 'Universal Charger'

Örnek verileri arayüzden SQL ile sorgulayabiliriz:

Screen Shot 2015-03-06 at 00.15.21

User sınıfını da aynı şekilde tanımlayıp örnek kullanıcılar oluşturalım:

create class User extends V
create property User.id integer
create property User.name string

create vertex User set id = 1, name = 'User 1'
create vertex User set id = 2, name = 'User 2'
create vertex User set id = 3, name = 'User 3'

Buraya kadar nesneler arasında herhangi bir ilişki kurmadık, çünkü daha ilişkinin tipini de oluşturmuş değiliz. User ve Item nesnesi arasında satın almayı simgeleyen Bought isimli bir ilişki olacak:

create class Bought extends E

Örnek nesne ilişkilerimiz de aşağıdaki şekilde olsun:

  • User 1, iPhone, Samsung Galaxy S5 ve Universal Charger almış
  • User 2, iPhone ve Universal Charger almış
  • User 3 sadece iPhone almış

İlişkileri veriyapımıza bu şekilde ekliyoruz:

create edge Bought from (select from User where id = 1) to (select from Item where id = 1)
create edge Bought from (select from User where id = 1) to (select from Item where id = 2)
create edge Bought from (select from User where id = 1) to (select from Item where id = 3)

create edge Bought from (select from User where id = 2) to (select from Item where id = 1)
create edge Bought from (select from User where id = 2) to (select from Item where id = 3)

create edge Bought from (select from User where id = 3) to (select from Item where id = 1)

İlişkileri de kurduğumuza göre, bunu arayüzden görsel olarak inceleyebiliriz:

Screen Shot 2015-03-06 at 00.19.44

Veriyapımız hazır olduğuna göre, iPhone alan bir kullanıcıya öneri yapmak istersek, iPhone ile beraber en çok alınan ürünlere ulaşmamız gerekir. Bunun için önce iPhone alan kullanıcılara ulaşmalıyız:

select expand(in('Bought')) from Item where id = 1

Bunun üzerine, iPhone alan kullanıcıların aldıkları tüm ürünlere ulaşmak istersek bir önceki sorguyu da kullanarak sorguyu genişletmemiz gerekir:

select expand(out('Bought')) from (select expand(in('Bought')) from Item where id = 1)

Son olarak da bu verileri gruplayıp sayısına göre sıralayıp, içlerinden de iPhone’ları elersek istediğimizi elde ediyoruz:

select id, title, count(*) as sold_count from
(select expand(out('Bought')) from
(select expand(in('Bought')) from Item where id = 1))
where id <> 1
group by id, title
order by sold_count desc
limit 10

Böylece iPhone alan bir kişiye Universal Charger önerebileceğimizi görüyoruz:

Screen Shot 2015-03-06 at 00.20.32

Bütün bunları yaparken Çizgi veritabanlarına özgü dilleri kullanmak yerine SQL kullanıyor olmak büyük bir avantaj. OrientDB barındırdığı özelliklerle ileride adını daha çok duyacağımız bir proje olacak.

Çizge veritabanları sosyal ağlarda “Tanıyor olabileceğiniz kişiler”, bankacılık sektöründe dolandırıcılıkların tespit edilmesi gibi konularda oldukça yaygın olarak kullanılıyor.

OrientDB ile ilgili detaylı bilgiye sitesinden ulaşabilirsiniz.

Cloudera Data Analyst Eğitimi Ankara

Daha önce eğitimlerinden bahsedilen Cloudera’nın Türkiye’deki tek eğitim partneri olan Dilişim, Cloudera Data Analist eğitimini 24-27 Şubat 2015 tarihlerinde ANKARA’da gerçekleştirecek.

dilisim-cloudera

Eğitmen eşliğinde alıştırmalar ile katılımcılar aşağıdaki konulara yoğunlaşacaktır:

  • Pig, Hive ve Impala’nın veri alma, saklama ve analiz etme özellikleri
  • Apache Hadoop ve ETL’in (extract, transform, load) temel özellikleri
  • Pig, Hive ve Impala ile veri analizi işlerinde verimliliği arttırma
  • Farklı veri setlerini birleştirerek değerli iş iç görülerini ortaya çıkarma
  • Veri setleri üzerinde gerçek zamanlı, kompleks sorgular uygulama

Bu eğitim veri analistleri, iş zekası uzmanları, geliştiriciler, sistem mimarları ve veritabanı adminleri için tasarlanmıştır. Katılım için programlama deneyiminin olması veya Apache Hadoop önbilgisi zorunlu değildir. Temel SQL bilgisinin olması yeterlidir.

Eğitim, sunum materyalleri İngilizce olmakla birlikte, Türkçe gerçekleşecek.

cloudera-logo
Cloudera’nın resmi eğitimini Türkçe olarak yetkilisinden almayı bu konuda sertifikalı olmak ve eğitim almak isteyen arkadaşlar için büyük bir fırsat olarak görüyorum.

Eğitim hakkında detaylı bilgiye buradan ulaşabilirsiniz.

Eğitime ön kayıt yaptırmak için ise bu linki kullanabilirsiniz.

Apache Phoenix

aa7u7-tbBu yazımızda size Apache Phoenix projesini tanıtmayı amaçlıyoruz. Apache Phoenix, HBase üzerindeki verileri SQL arayüzü ile yüksek performanslı bir şekilde sorgulamamızı sağlayan bir proje. Shell üzerinden kullanabileceğimiz gibi, bir JDBC sürücüsüne de sahip.

Phoenix, HBase’in özelliklerini çok iyi kullanarak yüksek performans sağlamayı amaçlıyor. SQL sorgularını HBase üzerinde scan yapacak şekilde derliyor, bu scan işlemlerinin başlangıç – bitişlerini ve paralel çalışmasını ayarlıyor, HBase’in performansını öne çıkartan coprocessor ve filter özelliklerini etkin bir şekilde kullanıyor. Bunlar dışında, secondary index desteği, istatistikler yardımıyla paralelleştirme ve optimizasyonlar da mevcut. Sadece okuma performansı değil, yazma performansını dağıtık bir şekilde sağlamak için salting özelliği de var. Bütün bunları yaparken de bize alışık olduğumuz SQL arayüzünü sunuyor. Bu özellikleriyle Phoenix oldukça kullanışlı bir araç olsa gerek.

Kurulum ve konfigürasyon

Phoenix kurulumu için HBase versiyonuna uygun bir sürüm seçmeniz gerekiyor. HBase 0.94.x için Phoenix 3.x, HBase 0.98.1 ve sonrası için Phoenix 4.x kullanmak gerekiyor.

Biz örneğimizi Cloudera Quickstart VM 5.1.0 üzerinde yapacağımız için Phoenix 4.x sürümünü indireceğiz. Phoenix içerisinde ayrıca MRv1 ve YARN için hadoop1 ve hadoop2 dizinleri bulunuyor. Uygun versiyon bizim için hadoop2 olacak.

Kurulum için Phoenix’i indirip açtıktan sonra, HBase kurulumunun yapıldığı yerdeki lib klasörü içerisine(bizim için /usr/lib/hbase/lib) Phoenix’in server jar dosyasını (phoenix-4.1.0-server-hadoop2.jar) sembolik linklememiz gerekiyor.

# ITU ve Bilken sunuculari hicbir zaman calismadigi icin mirror'dan indiriyoruz
wget http://www.eu.apache.org/dist/phoenix/phoenix-4.1.0/bin/phoenix-4.1.0-bin.tar.gz
# Kurulumu yapiyoruz
cp phoenix-4.1.0-bin.tar.gz /opt/
cd /opt/
tar xvf phoenix-4.1.0-bin.tar.gz
cd phoenix-4.1.0-bin/hadoop2/bin/
# hbase altina phoenix jar'ini linkliyoruz
cd /usr/lib/hbase/lib/
ln -s /opt/phoenix-4.1.0-bin/hadoop2/phoenix-4.1.0-server-hadoop2.jar

Veri Hazırlığı

Phoenix ile HBase üzerinde daha önce varolan tablolar da tablo ya da view olarak tanıtılıp sorgulanabiliyor fakat biz burada her zaman kullandığımız NYSE veri setini biraz değiştirerek kullanacağız. Örnek dosyamıza bir ID alanı ekleyerek, tab ile ayrılmış dosyayı virgül ile ayrılmış hale getirmek için Linux’ün muhteşem komutlarından faydalanıyoruz:

# Dosyayi indir ve ac
wget https://s3.amazonaws.com/hw-sandbox/tutorial1/NYSE-2000-2001.tsv.gz
gunzip NYSE-2000-2001.tsv.gz
# Dosyaya satir numarasi ekle ve virgulle ayir
awk '{printf "%s,%s\n",NR,$0}' NYSE-2000-2001.tsv | sed '2,$y/\t/,/' > data.csv

Veri Yükleme

Phoenix bin klasörü altında işimize yarayacak birkaç komut var. Bunlardan birisi sqlline.py aracı. Bu araç ile herhangi bir JDBC desteği olan veritabanına bağlanabiliyoruz. Phoenix de JDBC driver’ına sahip olduğu için bu aracı kullanmamız mümkün. Parametre olarak HBase’in kullandığı Zookeeper adresini belirtmemiz gerekiyor. Örneğimizde localhost:2181/hbase adresini kullanarak bağlanıyoruz.

[root@quickstart bin]# ./sqlline.py localhost:2181/hbase
Setting property: [isolation, TRANSACTION_READ_COMMITTED]
issuing: !connect jdbc:phoenix:localhost:2181/hbase none none org.apache.phoenix.jdbc.PhoenixDriver
Connecting to jdbc:phoenix:localhost:2181/hbase
14/10/26 14:27:21 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
14/10/26 14:27:23 WARN impl.MetricsConfig: Cannot locate configuration: tried hadoop-metrics2-phoenix.properties,hadoop-metrics2.properties
Connected to: Phoenix (version 4.1)
Driver: org.apache.phoenix.jdbc.PhoenixDriver (version 4.1)
Autocommit status: true
Transaction isolation: TRANSACTION_READ_COMMITTED
Building list of tables and columns for tab-completion (set fastconnect to true to skip)...
68/68 (100%) Done
Done
sqlline version 1.1.2
0: jdbc:phoenix:localhost:2181/hbase>

NYSE tablomuzu oluşturmak için aşağıdaki SQL komutunu çağırıyoruz:

0: jdbc:phoenix:localhost:2181/hbase> CREATE TABLE NYSE (ID INTEGER NOT NULL PRIMARY KEY, EXCHANGE VARCHAR, STOCK_SYMBOL VARCHAR, STOCK_DATE VARCHAR, PRICE_OPEN DOUBLE, PRICE_HIGH DOUBLE, PRICE_LOW DOUBLE, PRICE_CLOSE DOUBLE, STOCK_VOLUME INTEGER, PRICE_ADJ_CLOSE DOUBLE);
No rows affected (0.586 seconds)

Oluşan tabloları !tables komutu ile görebilirsiniz:

0: jdbc:phoenix:localhost:2181/hbase> !tables
+------------+-------------+------------+------------+------------+------------+---------------------------+----------------+-------------+----------------+--------------+-------------+
| TABLE_CAT  | TABLE_SCHEM | TABLE_NAME | TABLE_TYPE |  REMARKS   | TYPE_NAME  | SELF_REFERENCING_COL_NAME | REF_GENERATION | INDEX_STATE | IMMUTABLE_ROWS | SALT_BUCKETS | MULTI_TENAN |
+------------+-------------+------------+------------+------------+------------+---------------------------+----------------+-------------+----------------+--------------+-------------+
| null       | SYSTEM      | CATALOG    | SYSTEM TABLE | null       | null       | null                      | null           | null        | false          | null         | false     |
| null       | SYSTEM      | SEQUENCE   | SYSTEM TABLE | null       | null       | null                      | null           | null        | false          | null         | false     |
| null       | null        | NYSE       | TABLE      | null       | null       | null                      | null           | null        | false          | null         | false       |
+------------+-------------+------------+------------+------------+------------+---------------------------+----------------+-------------+----------------+--------------+-------------+
0: jdbc:phoenix:localhost:2181/hbase> 

Kullanabileceğimiz bir diğer araç olan psql.py yardımı ile CSV dosyaları Phoenix üzerinden HBase’e aktarmamız mümkün. Parametre olarak -t ile tablo ismini belirtiyoruz, Zookeeper adresini veriyoruz ve son olarak da içeri aktaracağımız CSV dosyasının adresini giriyoruz:

[root@quickstart bin]# ./psql.py -t NYSE localhost:2181/hbase /root/data.csv 
14/10/26 15:05:45 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
14/10/26 15:05:46 WARN impl.MetricsConfig: Cannot locate configuration: tried hadoop-metrics2-phoenix.properties,hadoop-metrics2.properties
csv columns from database.
14/10/26 15:05:50 ERROR util.CSVCommonsLoader: Error upserting record [1, exchange stock_symbol date stock_price_open stock_price_high stock_price_low stock_price_close stock_volume stock_price_adj_close]: 2
CSV Upsert complete. 812989 rows upserted
Time: 259.044 sec(s)

Veri Sorgulama

Artık verisi de aktarılmış olan NYSE tablomuza örnek sorgular atabiliriz.

0: jdbc:phoenix:localhost:2181/hbase> SELECT COUNT(*) FROM NYSE;
+------------+
|  COUNT(1)  |
+------------+
| 812989     |
+------------+
1 row selected (12.164 seconds)

0: jdbc:phoenix:localhost:2181/hbase> SELECT STOCK_SYMBOL, AVG(PRICE_HIGH) AS AVG_HIGH FROM NYSE GROUP BY STOCK_SYMBOL ORDER BY AVG_HIGH DESC LIMIT 20;
+--------------+------------+
| STOCK_SYMBOL |  AVG_HIGH  |
+--------------+------------+
| WPO          | 545.7559   |
| GTC          | 343.4477   |
| WTM          | 256.8117   |
| MTB          | 215.8028   |
| MKL          | 168.524    |
| PC           | 136.7031   |
| IVV          | 129.6019   |
| JNPR         | 123.9435   |
| KYO          | 121.965    |
| IJK          | 118.9919   |
| UBS          | 118.159    |
| EFA          | 117.7177   |
| NVR          | 115.8505   |
| SPW          | 115.6961   |
| BCS          | 115.2948   |
| IBM          | 110.9149   |
| SNE          | 108.451    |
| IJR          | 107.7051   |
| BT           | 107.5407   |
| MMC          | 106.4518   |
+--------------+------------+
20 rows selected (16.223 seconds)

Buradaki süreler sanal tek makinelik bir test ortamında olduğu için oldukça yüksek. Ancak gerçek bir kümede sorgular çok daha hızlı çalışacaktır. Buradaki amacımızın fonksiyonaliteyi test etmek olduğunu hatırlatmakta fayda var.

Phoenix kullanırken dikkat edilmesi gereken bir konu, tüm tablo ve kolon isimlerinin büyük harfli olması gerekliliği. Aksi durumda her bilginin “tırnak içerisinde” girilmesi gerekiyor. Biraz sinir bozucu bir durum.

Daha önce Hive ile HBase entegrasyonu üzerine bir yazı hazırlamıştık. Phoenix-HBase ile Hive-HBase karşılaştırmalı performans grafiği ise aşağıdaki gibi:

PhoenixVsHive

 

Phoenix ile ilgili bilgilere buradan ulaşabilirsiniz.

Cloudera Hadoop Developer Eğitimi

Daha önce eğitimlerinden bahsedilen Cloudera’nın Türkiye’deki tek eğitim partneri olan Dilişim, Apache Hadoop geliştirici eğitimini 22-25 Eylül 2014 tarihlerinde İstanbul’da gerçekleştirecek.

dilisim-clouderaEğitim süresince:

  • Hadoop’un çekirdek teknolojileri HDFS ve MapReduce’un işleyişleri ve MapReduce kodu yazımı
  • Hadoop geliştirmek, hata ayıklamak, iş akışı ve yaygın algoritmaların gerçekleştirilmesi için en iyi pratikler
  • Hive, Pig, Sqoop, Flume, Oozie, Mahout ve diğer Hadoop ekosistem projelerinden faydalanmak
  • Hadoop kümesini veri merkezine entegre etmek için en uygun donanım ve ağ yapılandırması
  • Veri setlerini birleştirme için MapReduce’da join operasyonu yazma ve yürütme
  • Gerçek-dünya veri analizi için gereken ileri Hadoop API konuları üzerinde yoğunlaşıp, belirtilen konularla ilgili sınıf ortamında alıştırmalar yapılacak.

Gereken donanım, örneğin eğitim süresince kullanılacak bilgisayarlar Dilişim tarafından sağlanacak.

Eğitime katılanlar Cloudera Certified Developer in Apache Hadoop (CCDH) deneme sınavına ücretsiz giriş hakkı kazanacak.

Eğitim, sunum materyalleri İngilizce olmakla birlikte, Türkçe gerçekleşecek.

cloudera-logo

Cloudera’nın resmi eğitimini Türkçe olarak yetkilisinden almayı; bu konuda sertifikalı olmak ve eğitim almak isteyen arkadaşlar için büyük bir fırsat olarak görüyorum.

Eğitim hakkında detaylı bilgiye buradan ulaşabilirsiniz.

Eğitime ön kayıt yaptırmak için ise bu linki kullanabilirsiniz.

Facebook Presto

presto-ogPresto, Facebook tarafından geliştirilmiş ve açık kaynaklı hale getirilmiş bir proje. Presto da diğer Dağıtık SQL motoru çözümleriyle (Impala, Drill, Spark SQL) aynı amacı güdüyor ve mimari olarak da olduça benzer. Hive projesini de Facebook’un geliştirdiğini düşünecek olursak projeden beklentimiz oldukça yüksek. Ancak arkasında bir topluluk veya ticari bir firma olmadığı için de geleceği konusunda kafamızda bir soru işareti olmuyor değil. Örneğin dökümantasyonunun yetersiz olduğunu söyleyebiliriz. Ancak en iyisi (ve keyiflisi) kendimizin deneyerek karar vermesi. Presto hali hazırda Hive ve Cassandra ile entegre olabiliyor. Bu yazımızda Presto’nun kurulumu ve Hive ile entegrasyonunu anlatacağız.

Kurulum ve konfigürasyon

Prestonun şu andaki en güncel hali olan 0.75 sürümünü buradan veya komut satırından indirmekle başlayalım:

wget http://central.maven.org/maven2/com/facebook/presto/presto-server/0.75/presto-server-0.75.tar.gz
tar xvf presto-server-0.75.tar.gz

Presto’nun kurulumu biraz karışık. Metadata’yı saklaması için bir data dizini, bir de konfigürasyon için etc dizini oluşturmamız gerekiyor. Nedense diğer projelerden alışık olduğumuz konfigürasyon şablonlarını kuruluma dahil etmemişler. Bunları bizim oluşturmamız gerekiyor. Bu amaçla etc dizini içerisinde node.properties, jvm.config ve config.properties isimli üç dosya yaratacağız. etc/node.properties dosyası içerisinde node.id ile her düğümün tekil id’sini belirtiyoruz. node.data-dir ile de data dizinini belirtiyoruz:

node.environment=test
node.id=node1-presto
node.data-dir=/opt/presto/data

etc/jvm.config dosyası ile jvm ayarlarını yapıyoruz. Burada Xmx parametresini sunucunun hafıza kaynaklarına göre vermemiz gerekiyor, aksi taktirde OutOfMemory hatası ile karşılaşmamız normaldir:

-server
-Xmx2G
-XX:+UseConcMarkSweepGC
-XX:+ExplicitGCInvokesConcurrent
-XX:+CMSClassUnloadingEnabled
-XX:+AggressiveOpts
-XX:+HeapDumpOnOutOfMemoryError
-XX:OnOutOfMemoryError=kill -9 %p
-XX:PermSize=150M
-XX:MaxPermSize=150M
-XX:ReservedCodeCacheSize=150M
-Xbootclasspath/p:/var/presto/installation/lib/floatingdecimal-0.1.jar

etc/config.properties içerisinde ise Presto süreçleri ile ilgili ayarları yapıyoruz. Presto süreçleri Coordinator ve Worker süreçlerinden oluşuyor. Coordinator sürecini NameNode sunucusunda, Worker süreçlerini de DataNode sunucularında çalıştırmak mantıklı olabilir. Presto düğümleri birbirlerini Discovery Service üzerinden bulurlar. Bunu yaparken de tüm haberleşme http üzerinden yapılıyor. Bu yüzden ayarlar farklılaşıyor. Coordinator düğümünde ayarlar şöyle:

coordinator=true
node-scheduler.include-coordinator=false
http-server.http.port=8080
task.max-memory=1GB
discovery-server.enabled=true
discovery.uri=http://hostname:8888

Worker düğümünde ise şu şekilde olmalı:

coordinator=false
http-server.http.port=8080
task.max-memory=1GB
discovery.uri=http://hostname:8888

Burada önemli parametrelerden birisi olan task.max-memory ile o sırada işlenen sorgu için kullanılabilecek maksimum hafıza miktarını belirtiyoruz. Özellikle group by, order by ve join işlemlerinde performans amacıyla işlemlerin tamamı hafızada yapıldığı için bu parametre doğru kullanılmalı. Az hafıza verilirse sorgular OutOfMemory hatası alıp tamamlanmayabilir.

Bitti sanıyorsanız yanılıyorsunuz. Bunların dışında ayrıca bir de Discovery servisini indirip kurmamız gerekiyor. Neden birlikte paketlenmediklerini, dökümantasyonda bu adımların neden olmadığı sorusunu kendi kendinize sorabilirsiniz.

wget http://central.maven.org/maven2/io/airlift/discovery/discovery-server/1.16/discovery-server-1.16.tar.gz
tar xvf discovery-server-1.16.tar.gz
ln -s /opt/presto/discovery-server-1.16 /opt/presto/discovery
mkdir /opt/presto/discovery/data /opt/presto/discovery/etc

Discovery servisi için de ayar dosyaları şu şekilde; discovery/etc/node.properties dosyası:

node.environment=test
node.id=node1-discovery
node.data-dir=/opt/presto/discovery/data

discovery/etc/config.properties dosyası:

http-server.http.port=8888

Bir de jvm.config ayarları:

-server
-Xmx1G
-XX:+UseConcMarkSweepGC
-XX:+ExplicitGCInvokesConcurrent
-XX:+AggressiveOpts
-XX:+HeapDumpOnOutOfMemoryError
-XX:OnOutOfMemoryError=kill -9 %p

Son olarak bu ayarların dışında Presto ile sorgulamak istediğimiz verileri catalog ayarları ile tanımlamamız gerekiyor. Biz Hive ile entegre olacağımız için catalog dizini altına ilgili ayar dosyasını oluşturacağız.

Hive ile Entegrasyon

Devam etmeden önce Hive tarafında örnek tabloyu oluşturmak için her zaman kullandığımız NYSE verisini indirdikten sonra hive konsolundan şunları çalıştırabilirsiniz:

CREATE TABLE nyse (exchangeSymbol string, stockSymbol string, stockDate string, stockPriceOpen double, stockPriceHigh double, stockPriceLow double, stockPriceClose double, stockVolume int, stockPriceAdjClose double) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' STORED AS TEXTFILE;

LOAD DATA LOCAL INPATH '/Users/devveri/dev/test/NYSE-2000-2001.tsv' OVERWRITE INTO TABLE nyse;

Hive ile ilgili daha fazla bilgiye ihtiyacınız varsa (biraz eskimiş de olsa) ilgili yazımıza bakabilirsiniz. Presto Hive’ın birçok farklı sürümünü destekliyor. Bunlar hive-hadoop1, hive-hadoop2, hive-cdh4, hive-cdh5 olarak zaten plugins klasörü altında görülebilir. Hive entegrasyonu için etc/catalog/hive.properties dosyasını oluşturuyoruz:

connector.name=hive-hadoop2
hive.metastore.uri=thrift://metastorehost:9083

hive.metastore.uri parametresi ile Hive metastore thrift adresini belirtiyoruz. Eğer daha önce yapmadıysanız Hive metastore servisini çalıştırmak için aşağıdaki komutu kullanabilirsiniz:

/opt/hive/bin/hive --service metastore

Presto süreçlerini başlatma ve durdurma

Presto süreçlerini başlatmak ve durdurmak için komut satırını kullanıyoruz:

bin/launcher start
bin/launcher stop

Küme olarak çalışması için Discovery servisinin de ayrıca başlatılması gerekiyor:

discovery/bin/launcher start

Log dosyalarını takip etmek isterseniz:

tail -f data/var/log/*

Presto komut satırı kullanımı

Bu kısım çok ilginç. Presto’yu komut satırından kullanmak isterseniz ilgili jar dosyasını ayrıca indirmeniz gerekiyor. Hangi kafayla bunu yaptıklarını gerçekten çok merak ediyorum. Neyse ki sizin için aşağıdaki komutları hazırladım:

wget http://central.maven.org/maven2/com/facebook/presto/presto-cli/0.75/presto-cli-0.75-executable.jar
chmod +x presto-cli-0.75-executable.jar
echo ./presto-cli-0.75-executable.jar --server localhost:8080 --catalog hive --schema default > presto-cli.sh

Artık presto-cli.sh ile Presto’ya istemci olarak bağlanabilir ve sorgularınızı çalıştırabilirsiniz:

$ ./presto.sh 
presto:default> show tables;
 Table 
-------
 nyse 
(1 row)

Query 20140827_215335_00015_96n4f, FINISHED, 1 node
Splits: 2 total, 2 done (100.00%)
0:00 [1 rows, 93B] [10 rows/s, 947B/s]

presto:default> select * from nyse limit 10;
 exchangesymbol | stocksymbol | stockdate | stockpriceopen | stockpricehigh | stockpricelow | stockpriceclose | stockvolume | stockpriceadjclose 
----------------+-------------+------------+----------------+----------------+---------------+-----------------+-------------+--------------------
 NYSE | ASP | 2001-12-31 | 12.55 | 12.8 | 12.42 | 12.8 | 11300 | 6.91 
 NYSE | ASP | 2001-12-28 | 12.5 | 12.55 | 12.42 | 12.55 | 4800 | 6.78 
 NYSE | ASP | 2001-12-27 | 12.59 | 12.59 | 12.5 | 12.57 | 5400 | 6.79 
 NYSE | ASP | 2001-12-26 | 12.45 | 12.6 | 12.45 | 12.55 | 5400 | 6.78 
 NYSE | ASP | 2001-12-24 | 12.61 | 12.61 | 12.61 | 12.61 | 1400 | 6.76 
 NYSE | ASP | 2001-12-21 | 12.4 | 12.78 | 12.4 | 12.6 | 18200 | 6.75 
 NYSE | ASP | 2001-12-20 | 12.35 | 12.58 | 12.35 | 12.4 | 4200 | 6.65 
 NYSE | ASP | 2001-12-19 | 12.42 | 12.6 | 12.35 | 12.6 | 10100 | 6.75 
 NYSE | ASP | 2001-12-18 | 12.37 | 12.5 | 12.37 | 12.41 | 10100 | 6.65 
 NYSE | ASP | 2001-12-17 | 12.4 | 12.52 | 12.4 | 12.52 | 8000 | 6.71 
(10 rows)

Query 20140827_215344_00016_96n4f, FINISHED, 1 node
Splits: 2 total, 2 done (100.00%)
0:01 [4.37K rows, 234KB] [5.82K rows/s, 312KB/s]

presto:default> select stockSymbol, sum(stockPriceClose) as total_value from nyse where stockVolume > 1000 group by stockSymbol order by total_value desc limit 10;
 stocksymbol | total_value 
-------------+--------------------
 WPO | 267022.80000000005 
 WTM | 117073.61 
 MTB | 106871.27 
 MKL | 82668.22 
 PC | 67790.19999999998 
 KYO | 60137.99999999997 
 JNPR | 59107.12999999994 
 BCS | 57008.43000000009 
 NVR | 56314.829999999994 
 SPW | 56300.86999999995 
(10 rows)

Query 20140827_215533_00018_96n4f, FINISHED, 1 node
Splits: 3 total, 3 done (100.00%)
0:04 [813K rows, 42MB] [217K rows/s, 11.2MB/s]

Bundan sonrasında Presto’yu incelemek, performans karşılaştırmaları yapmak size kalıyor. Bu yazımızı sevdiyseniz Spark SQL ve Impala yazılarımız da ilginizi çekebilir. Presto ile ilgili ayrıntıları kendi sitesinde bulabilirsiniz.

Spark SQL

spark-logoApache Spark projesinin yeteneklerinden birisi de SQL ve HiveQL arayüzleri ile veri işleyebilmesi. Yazıyı yayınlamadan önce bu proje Shark olarak isimlendiriliyordu, ancak ismi değiştirilerek Spark SQL olarak adlandırıldı ve mevcut projeye dahil edildi.

Spark SQL Hive, Impala, Drill projelerine bir alternatif oluşturuyor. JSON, Parquet vs gibi populer tüm veri tiplerini destekliyor. Ayrıca Hive metadata’sını da kullanabildiği için Hive tablolarını Spark SQL ile sorgulamak mümkün.

Spark yazımızda verilerin RDD’ler üzerinden işlendiğinden bahsetmiştik. SQL arayüzü için de SchemaRDD (Java için JavaSchemaRDD) tipini kullanıyoruz. Veriyi RDD olarak yükledikten sonra tablo olarak register ediyoruz, ardından bu tablo üzerinde SQL komutununu çalıştırabiliyoruz. SQLContext üzerinde sorgumuzu çalıştırdıktan sonra veri bize Row tipinde dönüyor.

Örnek amaçlı olarak daha önce de kullandığımız NYSE verilerini kullanacağız. Bu veriye karşılık gelen ExchangeRecord sınıfını yazdıktan sonra veriyi aşağıdaki gibi sorgulayabiliriz:

package com.devveri.spark.job;

import com.devveri.spark.model.ExchangeRecord;
import com.devveri.spark.util.SparkHelper;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.sql.api.java.JavaSQLContext;
import org.apache.spark.sql.api.java.JavaSchemaRDD;
import org.apache.spark.sql.api.java.Row;

import java.util.List;

public class NYSEExample {

    public static void main(String[] args) throws Exception {
        final String appName = "NYSEExample " + System.currentTimeMillis();
        final String stockFile = "file:///Users/devveri/dev/test/NYSE-2000-2001.tsv";

        // get contexts
        JavaSparkContext jsc = new JavaSparkContext(SparkHelper.getDefaultConf()); 
        JavaSQLContext sqlContext = new JavaSQLContext(jsc);

        // load data and convert to java object
        JavaRDD exchanges = jsc.textFile(stockFile).map(new Function<String, ExchangeRecord>() {
            public ExchangeRecord call(String s) throws Exception {
                return new ExchangeRecord(s);
            }
        });

        // apply schema
        JavaSchemaRDD schemaExchange = sqlContext.applySchema(exchanges, ExchangeRecord.class);
        schemaExchange.registerAsTable("exchanges");

        // execute an sql query
        JavaSchemaRDD topExchanges = sqlContext.sql(
                "select stockSymbol, sum(stockPriceClose) as total_value " +
                "from exchanges " +
                "where stockVolume > 1000 " +
                "group by stockSymbol " +
                "order by total_value desc " +
                "limit 10");

        List result = topExchanges.map(new Function<Row, String>() {
            public String call(Row row) throws Exception {
                return String.format("%s\t%f",
                        row.getString(0),
                        row.getDouble(1));
            }
        }).collect();

        for (String s : result) {
            System.out.println(s);
        }
    }

}

SQLContext sadece basit SQL cümlelerini destekliyor. Daha kompleks SQL cümleleri gerekirse HiveContext kullanmak gerekiyor.

Spark SQL, Hive uyumluluğu, SerDe desteği, JSON, Parquet dosyalarında direk destek vermesi, farklı projelerle olan entegrasyonu (Cassanda gibi) oldukça yetenekli görünüyor. Özellikle SQL arayüzü desteklemeyen projelere entegre ederek çok başarılı sonuçlar elde edilebilir. Sadece benchmark’lara baktığımızda performans olarak benzer projelerin önüne geçemediğini görüyoruz.

Daha fazla detay için dökümantasyona buradan erişebilirsiniz.

Apache Nutch

Tarihçe ve Tanım

nutch_logo_mediumDev veriden bahsedildiğinde Hadoop’un başlangıç projesi olan Nutch’tan söz etmemek olmaz. “Hadoop nasıl başladı?” sorusunun cevabı bizi Nutch isimli Apache projesine götürür. Nutch’ın temelleri ise Google arama motoru yapmak için işe başlandığında bunun en hızlı şekilde yapabilmesi için GFS ve MapReduce teknolojilerinin yayınlaması ile atıldı. Peki Nutch için HDFS ve MapReduce neden gerekli? Bir crawlera sahipseniz büyük veriye sahipsiniz demektir. Bir çok sitenin içeriğine sahip olmak ve bunlar üzerinden kolayca işlem yapabilmek için dağıtık bir sisteme ihtiyacınız vardır; bunun da en güzel yolu HDFS ve MapReduce’dur.

Projenin nasıl çalıştırılıp ve istenilen çalışma şekline nasıl getirileceği konularında bilgi vermeye çalışacağım. Anlatımlarım linux işletim sistemi üzerinden olacaktır. İşletim sisteminize uymuyorsa veya sorun yaşıyorsanız işletim sisteminiz üzerine Virtual Machine araçları (VMWareVirtualBox vs.) ile Ubuntu-12.04.4 kurup sıfır bir işletim sistemi ile deneyebilirsiniz.

İndirme ve Derleme

1) Öncelikle projenin kaynak kodunu Apache’nin sitesinden indirmeniz gerekmekte.

link : http://www.apache.org/dyn/closer.cgi/nutch/

Anlatımlarım apache-nutch-1.8 verisonun src’si için olacak. Projeyi indirdikten sonra bilgisayarınızda istediğiniz bir konuma zip’ten çıkartın.

2) Bilgisayarınızda JAVA_HOME ‘un ayarlı olması gerekiyor.

export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::")

komutunu çalıştırın veya ~/.bashrc dosyanıza bu komutu ekleyin.

3) Komut satırından projenizin bulunduğu klasöre gidin

$cd apache-nutch_Xsurum/

4)  $ant runtime komutunu çağırın ve projenizin bulunduğu klasörde runtime/local şeklinde bir klasör oluşmuş olması gerekiyor.

Not: ant bulunamadı hatası aldıysanız $sudo apt-get install ant komutunu çağırın ve tekrar deneyin.

Ayarlamalar için gerekli Config dosyalarıda runtime/local/conf/ klasörü altında bulunuyor. Hatırlatmakta fayda var $ant clean komutunu çalıştırmaya gerek duyduğunuzda runtime dosyası silineceğinden ant clean komutunu çalıştırmadan önce config dosyalarınızı yedekleyin.

Kontrol

Komut satırından runtime/local içinde iken $bin/nutch yazın, eğer bir sorun yoksa aşağıdaki ifadeyi görmeniz gerekmekte.

Usage: nutch COMMAND where COMMAND is one of:

readdb            read / dump crawl db
mergedb           merge crawldb-s, with optional filtering
readlinkdb        read / dump link db
inject            inject new urls into the database
generate          generate new segments to fetch from crawl db
freegen           generate new segments to fetch from text files
fetch             fetch a segment's pages
parse             parse a segment's pages

Erişim izni hatası alırsanız $chmod +x bin/nutch kodunu çalıştırıp tekrar deneyin.

Nutch Ayarları

1) Nutch için belirlenmiş default ayarları conf/default.xml dosyasının içinde bulabilirsiniz. Buradaki ayarlardan size gereken ayarı kullanmak için ise conf/nutch-site.xml ‘e o ayarı kopyalamanız gerekmekte.

Projemizi ilk kez çalıştırmadan önce bazı ayarlar yapmamız gerekmekte.

http.agent.name property ayarı yapmak için conf/nutch-site.xml dosyamıza aşağıdaki kodu kopyalayalım ve kaydedelim.

<property>
<name>http.agent.name</name>
<value>My Nutch Spider</value>
</property>

2) Nutch bize içeriğini çekeceğimiz siteleri belirlememiz için kolay bir yol sunmakta. Text dosyasına satırlar halinde içeriğini çekmek istediğimiz siteleri yazmamız gerekiyor. Bunun için aşağıdaki komutları çalıştırabilirsiniz veya normal yoldan runtime/local/ dosyası içine urls klasörü yaratıp içine seed.txt adında bir text file yaratıp içine satırlar halinde urlleri yazabilirsiniz.

$mkdir -p urls
$cd urls
$touch seed.txt

Bu komutlarla runtime/local/urls/seed.txt adında bir dosya yaratmış olduk içine içeriğini istediğiniz sitelerin urllerini yazmanız gerekiyor. Urllerin başlarında http:// olmasına dikkat edin yoksa hata alabilirsiniz. Örnek olarak http://devveri.com/ yazıp kaydediyoruz.

3) İsterseniz sitenin içinde istediğiniz şekilde bir veri alımı için regex yazabilirsiniz. Bunu yapmak için conf/regex-urlfilter.txt dosyasını açıp en alt kısımdaki;

# accept anything else

+.

yerine

+^http://([a-z0-9]*\.)*devveri.com/

yazabilirsiniz. Bu regex programınızın sadece site içinde bulduğu linklerden sitenin dışına çıkan linklerin içeriğine gitmeme faydası sağlar. Bu kısmı böyle bir dosyanın var olduğunu bilmeniz için anlattım +. şeklinde kalabilir.

Solr Ayarları

Anlatımımda çektiğiniz içerikler direk solra indexlenecektir.Bunun için localinizdeki solr ın schema.xml’ini ayarlamamnız gerekmekte. Nutch’ın Solr 4.3.0 ile sorunsuz çalıştığı söylenmekte bunun için localinizdeki Solr’ın bu versiyon olduğunu kabul edip anlatımıma devam ediyorum. Eğer mevcut değilse derlenmiş Solr 4.3.0’ı indirmeniz grekmekte. Derlenmiş 4.3.0 İndirmek için link :

http://archive.apache.org/dist/lucene/solr/4.3.0/

Nutch dosyanızdaki conf/schema-solr4.xml dosyasını Solr ın bulunduğu klasördeki schema.xml ile değiştirmeniz gerekiyor. Öncelikle solrın bulunduğu klasördeki schema.xml dosyanızın ismini schema.xml.org olarak değiştirip sonrasında  yerine conf/schema-solr4.xml dosyasını kopyalayıp ismini schema.xml olarak değiştirmenizi tavsiye ederim.

Sonrasında değiştridiğiniz yeni schema.xml ‘in 351. satırına

<field name="_version_" type="long" indexed="true" stored="true"/>

ifadesini ekleyiniz.

Solr’ı yeni bir komut penceresinde çalıştırın.

$java -jar start.jar

Nutch Akış Şeması

 

nutch _flowchartProje urls/seed.txt içerisinde tanımladığınız url’leri crawldb ‘ye koyar ve MapReduce çalıştırarak koyduğunuz sitenin içeriğini çekmeye başlar. Yukarıda ki şemada görülen döngünün sayısını siz verdiğiniz parametre ile belirlersiniz. Her döngü sonunda index güncellenir ve solr paremetre olarak verildiyse ilk döngü bittiğinde solr’ın panelinden ilk indexlerin geldiğini görebilirsiniz.

Crawl Komutu ile Çalıştırma

1) Artık projemizi belirlediğiniz sitenin içeriğini almak için çalıştırabiliriz.

$bin/crawl urls/seed.txt testcrawl http://localhost:8983/solr/ 2

Buradaki 2 değerini döngü sayısı gibi düşünebilirsiniz. Elinizde başlangıçta anasayfa url var.İlk döngüde anasayfanın içeriğini alır ve bulduğu linkleride ikinci döngüye hazırlar. İkinci döngüde birinciden gelen yeni urllerin içeriklerini alır ve bulduğu urlleri diğer döngüye hazırlar. 2 dersek proje burada durur. Aynı şekilde tekrar çalıştırdığımızda son kaldığı yerden 2 döngü daha atarak ilerler. 2 sayısının yerine bir seferde kaç döngüde çalışmasını istiyorsanız yazabilirsiniz.

2) Komutu çalıştırdığınızda MapReduce’un işlediğini göreceksiniz ve işlem bittiğinde aşağıdaki gibi yaratılmış bir dosya düzenine sahip olacaksınız.

testcrawl/crawldb
testcrawl/linkdb
testcrawl/segments

Nutch Komutu ile Çalıştırma

Projenizi $bin/nutch komutu ilede çalıştırabilirsiniz ama önerilmeyen bir çalışma biçimidir.

$bin/nutch crawl urls -dir crawl -depth 3 -topN 5

Komutunu çalıştırın

** depth anasayfadan ne kadar derine ineceğini gösterir.

Örnek : Anasayfada 111.html linki var bu sayfada 222.html linki var vs

Kısaca anasayfadan başlayıp her bulduğu linkinde içeriğini alıp onların götürdüğü linklerin içeriğinide alacakmı ne kadar derine gidecek depth onun ayarlanması içindir.

**topN ise her derinlikte maximum ne kadar url in yeni içerik alma listesine ekleneceğinin ayarıdır.

$bin/nutch crawl2 urls -solr http://localhost:8983/solr/ -depth 3 -topN 5

Not: crawl2 yazmamın sebebi solr olmadağan çalıştırdığımız komut crawl dosyası içinde veriler yaratmıştı ikinci kez crawl yazarsak ilk crawlda bulduğu veriler üzerinden devam eder.

Faydalı Bilgiler

*runtime/deploy klasörüde dikkatinizi çekmiştir. Eğer aynı komutları burada çalıştırmak isterseniz. urls klasörünün hdfs te olması gerekiyor. Ve sonuç crawl dosyanız hdfs e yazılır.

* nutch-site.xml den nasıl faydalanabileceğiniz konusunda birkaç örnek vereyim.

—Yazının başında yazdığımız regex in yaptığı iş için böyle bir ayar mevcut crawl işlemi esnasında value true ise sitenin dışına çıkmadan crawl işlemini gerçekleştirmeye yarıyor.

<property>
<name>db.ignore.external.links</name>
<value>false</value>
<description>If true, outlinks leading from a page to external hosts
will be ignored. This is an effective way to limit the crawl to include
only initially injected hosts, without creating complex URLFilters.
</description>
</property>

—Aynı sunucuya atılan ardışık isteklerdeki bekleme süresi

<property>
<name>fetcher.server.delay</name>
<value>5.0</value>
<description>The number of seconds the fetcher will delay between
successive requests to the same server.</description>
</property>

*Nutch crawl surecinin adimlarını merak ediyorsanız daha detaylı bilgi için

http://wiki.apache.org/nutch/NutchTutorial inceleyebilirsiniz.

Apache Spark

spark-logoApache Spark bugünlerde ismini daha sık duymaya başladığımız, büyük veri işleme amaçlı bir diğer proje. Hadoop’tan 100 kat daha hızlı olmak gibi bir iddia ile birlikte, gelişmiş “Directed Acyclic Graph” motoruna sahip, Scala dili ile yazılmış ve bellek-içi (in-memory) veri işleme özellikleriyle bu iddiayı boşa çıkartmıyor gibi görünüyor. Özellikle Yapay Öğrenme algoritmalarının dağıtık implementasyonu konusunda Hadoop’tan daha performanslı olduğunu söyleyebiliriz. Öyle ki, Apache Mahout projesi bundan böyle Hadoop ile değil Spark üzerinde çalışacak şekilde geliştirilmeye etme kararı aldı.

Ancak şunu söylemeliyiz ki Spark Hadoop’un yerine geçecek bir teknoloji olmaktan ziyade, Hadoop ailesinin bir üyesi olup Hadoop’un zayıf kaldığı bazı konulardaki eksiklikleri giderecek gibi görünüyor. Hadoop binlerce sunucu üzerinde petabyte’larca veriyi stabil şekilde saklayıp analiz edebilecek şekilde tasarlanmışken, Spark göreceli olarak daha az miktarda veriyi özellikle in-memory olarak işlemek ve daha hızlı sonuç almak amacıyla tasarlanmış. Spark HDFS gibi herhangi bir storage çözümü sunmuyor ancak HDFS üzerinden okuma yazma yapabiliyor. Java ile Hadoop MapReduce uygulamaları geliştirmek çok low-level sayılırken, Spark ile bir uygulama geliştirmek çok daha kullanıcı dostu. Bu yüzden Spark’ı alet çantamızdaki farklı bir araç olarak görmemiz gerektiğini düşünüyorum.

logistic-regression
Logistic regression algoritmasının Hadoop ve Spark üzerinde çalıştırılması sonucu elde edilen performans örneklenmiş. 

Spark kümesini standalone çalıştırmanın dışında Amazon EC2, Mesos ve YARN ile beraber çalıştırmanız mümkün. Dilerseniz test amaçlı olarak tek sunucuda lokal modunda da çalıştırabilirsiniz. Küme olarak çalıştırdığınızda bir master ve birden çok slave düğümü oluyor. Slave düğümlerinde kaç worker çalışacağını, bunların kaç cpu core ve ne kadar memory kullanacağını ayarlayamanız gerekiyor.

Uygulama geliştirme açısından Spark Scala’nın avantajlarını sonuna kadar kullanıyor. Örneğin artık “hello world” uygulaması yerine geçen “word count” uygulamasını Spark ile çok az bir kod parçası ile gerçekleştirebiliyoruz:

val file = spark.textFile("hdfs://...")
val counts = file.flatMap(line => line.split(" "))
 .map(word => (word, 1))
 .reduceByKey(_ + _)
counts.saveAsTextFile("hdfs://...")

Scala dışında Java ve Python dillerini de destekliyor. En güzel özelliklerinden birisi Spark’ın getirdiği soyutlama ile geliştirme yapmanın çok kolay hale gelmesi. Esnek Dağıtık Verisetleri ile (Resilient Distributed Dataset, kısaca RDD) veriyi sanki bir collection objesini işler gibi işlememiz sağlanmış. RDD’ler veri işlemeyi kolaylaştıracak map, filter, union, cartesian, join, groupByKey, sortByKey gibi birçok transformasyon metodunun yanı sıra, reduce, collect, count, distinct gibi aksiyon metodlarını içeriyor. Bir dosyayı veya bir collection objesini RDD’ye çevirip bu metodları ardışıl bir şekilde çağırarak veriyi işliyoruz. Transformasyon metodları lazy tasarlanmış, yani herhangi bir aksiyon metodu çağırılana kadar gerçekte bir işlem yapılmıyor. Spark uygulamalarını interaktif arayüzü (spark-shell) üzerinden test etmek mümkün. Örnek uygulamalara gözatabilirsiniz.

Java ile “word count” uygulaması örneği ise şöyle:

package com.devveri.spark;

import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.FlatMapFunction;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.PairFunction;
import scala.Tuple2;

import java.util.Arrays;
import java.util.regex.Pattern;

/**
 * Created by hilter on 11/05/14.
 */
public class WordCount {

 private static final String MASTER = "spark://localhost";

 private static final Pattern SPACE = Pattern.compile(" ");

 public static void main(String[] args) {
 // create context
 JavaSparkContext jsc = new JavaSparkContext(
 MASTER,
 "WordCount",
 System.getenv("SPARK_HOME"),
 JavaSparkContext.jarOfClass(WordCount.class)
 );

 // load file
 JavaRDD<String> file = jsc.textFile("/Users/devveri/test.txt");

 // split words
 JavaRDD<String> words = file.flatMap(new FlatMapFunction<String, String>() {
 public Iterable<String> call(String s) { return Arrays.asList(s.split(" ")); }
 });

 // create pairs
 JavaPairRDD<String, Integer> pairs = words.map(new PairFunction<String, String, Integer>() {
 public Tuple2<String, Integer> call(String s) { return new Tuple2<String, Integer>(s, 1); }
 });

 // count
 JavaPairRDD<String, Integer> counts = pairs.reduceByKey(new Function2<Integer, Integer, Integer>() {
 public Integer call(Integer a, Integer b) throws Exception { return a + b; }
 });

 // save result
 counts.saveAsTextFile("/tmp/result");
 }

}

Java 8’in yeni özelliklerinden faydalanmadığınız durumda Java ile Spark uygulaması geliştirmek böyle çirkin kodlar yazmanıza sebep oluyor, ancak çalışmasında herhangi bir performans farkı sözkonusu değil.

Örnekte ilk olarak bir JavaSparkContext objesi oluşturuyoruz. Sonrasında bir metin dosyasını yükleyip her bir satır bir String objesi olacak şekilde bir RDD oluşturuyoruz. Yüklenen her bir satırı flatMap metodu içerisinde yazdığımız fonksiyonda boşluklarından ayrılıyor, flatMap metodu da her bir elemanı birer satır haline dönüştürüyor. Kelime sayısını alabilmek için bu satırları map metoduna vererek [kelime, 1] formatında bir pair objesi haline getiriyoruz. Sonrasında reduceByKey metodu ile bu kelimelere karşılık gelen sayıları topluyoruz. En sonunda da sonucu bir metin dosyasına kaydediyoruz. Bütün bu işlemleri master düğümün arayüzünden takip edebilirsiniz.

spark-master

Spark ile ilgili dikkat edilmesi gereken konulardan birisi Spark’ı hangi Hadoop sürümü ile çalıştırmak istediğiniz. Hadoop v1, v2, CDH3, CDH4, CDH5 gibi farklı Hadoop sürümlerine uygun sürümü bulup kurmanız ya da koddan derlemeniz gerekiyor. Aksi takdirde sorun yaşamanız çok muhtemel.

Bunların dışında Spark Streaming özelliği ile aslında Apache Storm projesinin sağladığı sürekli akan verileri anlık olarak işleyebilme özelliğini sağlıyor. Ayrıca Spark, Hive ile entegre olan dağıtık SQL motoru Apache Shark projesinde de altyapı sağlıyor. Son olarak MLlib isimli Yapay Öğrenme ve GraphX isimli çizge veritabanı projeleri de Spark çatısı altında toplanmış.

İlerleyen günlerde Spark daha fazla önümüze çıkacakmış gibi görünüyor.

ElasticSearch ve Pig Entegrasyonu

elasticsearchPig ile sadece Hadoop üzerindeki verileri değil, MongoDB gibi farklı veri kaynaklarını da analiz edebileceğimizden bir yazımızda bahsetmiştik. Pig ile ElasticSearch üzerindeki verileri de analiz etmemiz mümkün. Aynı şekilde Hadoop üzerindeki verileri Pig aracılığı ile ElasticSearch üzerinde kolayca indekslemeniz ve analizler yapmanız oldukça kolay.

Hazırlık

Pig ile ElasticSearch entegrasyonu ile ilgili projeye GitHub üzerinden erişmeniz mümkün. Proje ile sadece Pig değil, Hive ve MapReduce entegrasyonu da gerçekleştirmek mümkün. Build ettikten sonra oluşan elasticsearch-hadoop.jar dosyasını Hadoop’un lib dizini içerisine kopyalamamız gerekiyor. Benim kurulumumda bu klasör /usr/lib/hadoop/lib şeklindeydi.

Maven ile kullanmak istediğinizde aşağıdaki ayarları kullanabilirsiniz.

<dependency>
 <groupId>org.elasticsearch</groupId>
 <artifactId>elasticsearch-hadoop</artifactId>
 <version>2.0.0.BUILD-SNAPSHOT</version>
</dependency>
<repositories>
 <repository>
 <id>sonatype-oss</id>
 <url>http://oss.sonatype.org/content/repositories/snapshots</url>
 <snapshots><enabled>true</enabled></snapshots>
 </repository>
</repositories>

Pig ve Hive ile ElasticSearch verilerini analiz ederken “Speculative Execution” özelliğini devredışı bırakmamız gerekiyor. “Speculative Execution” özelliği MapReduce işlemleri sırasında bir job’un yavaş çalışması durumunda o işin bitmesini veya fail etmesini beklemek yerine aynı anda aynı işi yapacak ve belki daha önce tamamlayacak başka bir job’ın başlatılarak sonucu garantilemeyi amaçlayan bir özellik.

Örnek amaçlı olarak Hortonworks’ün paylaştığı Newyork borsasının 2000-2001 yılı verilerini kullanacağız. Verileri https://s3.amazonaws.com/hw-sandbox/tutorial1/NYSE-2000-2001.tsv.gz adresinden indirdikten sonra HDFS üzerine aktarmamız gerekiyor.

ElasticSearch’e Veriyi Aktarma

ElasticSearch üzerindeki verilere Pig üzerinden erişim için EsStorage sınıfını kullanıyoruz. Bu sınıfın constructor metoduna bağlanacağımız sunucuların adres ve portları, bağlantı timeout değerlerini, indeksin otomatik yaratılıp yaratılmayacağı gibi ayarları veriyoruz.

HDFS üzerinde duran borsa verisini Pig ile yükleyip ElasticSearch’e aktarmak için neredeyse hiçbirşey yapmamıza gerek yok. Pig bizim için herşeyi halletmiş. Tek yapmamız gereken Load komutunu PigStorage sınıfı ile HDFS üzerindeki veriyi yüklemek, daha sonra Store komutunu EsStorage sınıfı ile kullanarak veriyi indekslemek.

REGISTER elasticsearch-hadoop.jar;

/* disable speculative execution */
set mapred.map.tasks.speculative.execution false
set mapred.reduce.tasks.speculative.execution false

DEFINE EsStorage org.elasticsearch.hadoop.pig.EsStorage('es.nodes=localhost:9200');

/* load nyse data */
A = LOAD '$INPUT' USING PigStorage() AS (exchange:chararray, stock_symbol:chararray, stock_date:chararray, stock_price_open:double,
 stock_price_high:double, stock_price_low:double, stock_price_close:double, stock_volume:double, stock_price_adj_close:double);

/* write to elasticsearch */
STORE A INTO '$OUTPUT' USING EsStorage();

ElasticSearch’ten Veriyi Okuma

EsStorage sınıfı ile veriyi okurken indeks içerisinden istediğimiz alanları sanki veritabanından okuyormuş gibi seçebiliyoruz. Hatta sorgu vererek sadece bu sorgunun sonucunu Pig tarafında da analiz etme şansımız bulunuyor.

REGISTER elasticsearch-hadoop.jar;

/* disable speculative execution */
set mapred.map.tasks.speculative.execution false
set mapred.reduce.tasks.speculative.execution false

DEFINE EsStorage org.elasticsearch.hadoop.pig.EsStorage('es.nodes=localhost:9200', 'es.query=?q=*');

/* load all documents from elasticsearch and filter by a stock symbol */
A = LOAD '$INPUT' USING EsStorage() AS (exchange:chararray, stock_symbol:chararray, stock_date:chararray, stock_price_open:double,
                stock_price_high:double, stock_price_low:double, stock_price_close:double, stock_volume:double, stock_price_adj_close:double);
B = FILTER A BY stock_symbol == '$SYMBOL';
DUMP B;

Örnek kodumuzda borsa bilgilerini yükleyip içerisinden sadece istediğimiz sembole sahip kayıtları getiriyoruz. Bu entegrasyon sayesinde örneğin HDFS üzerindeki verileri, ElasticSearch üzerindeki verileri ve örneğin MongoDB üzerindeki verileri join’leyebilme ve her türlü analiz etme imkanımız oluyor.

Kaynak: http://www.elasticsearch.org/guide/en/elasticsearch/hadoop/current/pig.html