Büyük veri içindeki nadir görülen olayların keşfedilmesi

Bu yazımızda, veri madenciliği çalışmalarında sıkça karşılaşılan “büyük miktarda veri içinde nadir görülen olayların keşfedilmesi” problemlerini çözerken dikkat etmemiz gereken önemli bir konuyu ele alacağız. İstatistik literatüründe çoklu karşılaştırma problemiçoklu hipotez testi gibi isimlerle anılan bu problemler veri madenciliği alanında aktif araştırma konuları içinde yer almaktadır [1]. Değişik uygulama alanları olmakla birlikte, biz burada bir örnek üzerinden temel problemi anlatmaya çalışacağız.

Büyük veri içinde nadir görülen olayların konu bağlamında incelenmesinin güzel bir örneğini, Devasa Veri Setlerinde Madencilik [2] kitabında görüyoruz. Dünya süper gücü olan bir devletin, bütün dünyayı bir çok veri toplama yöntemi ile sürekli izlediğini varsayalım. Toplanan bu veriler işlenmekte, kişilerin ne yaptığı konusunda veri madenciliği yöntemleri ile otomatik çıkarımlar yapılmakta, çıkan sonuçlar olası tehdit değerlendirmeleri olarak istihbarat servisine aktarılmaktadır.

İstihbarat servisi çıkan bu bilgilere dayanarak elindeki imkanları belirlenen kişileri yakın takibe almak için kullanmaktadır. Böylelikle olası tehditlerin gerçekleşmeden önlenebilmesi için önemli bir kazanım elde edildiği düşünülmektedir.

Bu tarz bir sistemin çalışmasında elimizde büyük veri işleme imkan ve kabiliyetleri var ise nasıl bir çıkarım mekanizması kurulabilir? Bu çıkarım mekanizması bizi gerçekten faydalı bir sonuca götürebilir mi? Yani olası tehditleri gerçekleştirecek kişiler listesine. Yoksa masum insanları şüpheli konumuna düşürme, dolayısı ile hem bu kişileri rahatsız etme, belki de gözetim altına alma, hem de imkanların boş yere harcanması şeklinde istenmeyen bir sonuca varabilir miyiz? Cevap, aradığımız aktivitelerin tanımını ne kadar daralttığımıza bağlıdır. Bunun teorik bir arka planı da vardır.

 

Bonferroni prensibi

Elimizde bir miktar veri var ve bu verinin içinde belli tipteki olayların gerçekleşip gerçekleşmediğini araştırıyoruz. Elimizdeki bu veri tamamen rastgele üretilmiş bir veri olsa bile, aradığımız tipte olayların bu verinin içinde olma olasılığı vardır ve verinin boyutu büyüdükçe aradığımız tipte olayların bu verinin içinde bulunma sayılarının artmasını beklemek yanlış olmaz. Bu şekilde tespit edilen gerçeklemeler teknik olarak aldatmaca olarak nitelendirilir ve bazı az rastlanan özelliklerin önemli olarak gözükebileceği, fakat tamamen rastgele olan verilerde bu tip durumların şans eseri olabileceği düşüncesi ile önemsiz olduğu kabul edilir. İstatistikte Bonferroni düzeltmesi olarak geçen teorem kullanılarak, buradaki aldatmacalı pozitif dönüşlerin önemli bir kısmından kurtulmak mümkündür. Yani veri içindeki rastgele oluşmuş bulunan olayların gerçek olaylarmış gibi ele alınmasına engel olacak bir yöntemden bahsediyoruz.

Bunun için, verinin rastgele olduğu kabulü altında, araştırdığımız olayların beklenen vuku bulma sayıları hesaplanır. Eğer bu sayı gerçek veri içinde bulunmasını beklediğiniz sayıdan ciddi bir manada büyükse, bu durumda bulduğumuz her şeyin önemli bir kısmının aldatıcı olduğunu düşünebiliriz. Bu yorum Bonferroni prensibi olarak anılan yöntemin özünü oluşturmaktadır.

Kötü niyetli kişiler listesine geri dönecek olursak, herhangi bir zamanda çok az sayıda kötü niyetli kişi olmasını bekleyebiliriz. Bonferroni prensibi bize bu kişileri bulmanın çok nadir görülen ve rastgele verinin içinde olması adeta beklenmeyen olaylara dayandırılması gerektiğini söyler.

 

Uygulama örneği

Varsayalım ki gerçekten az sayıda niyetleri kötü olan kişiler var ve biz bu kişileri tespit etmek istiyoruz. Yine varsayalım ki, bu kişiler kötü niyetlerine erişmek amacı ile düzenli olarak bir otelde toplanıp kararlar alıyorlar. Problemin boyutunu belirlemek için; şu kabulleri yapalım.

Kabullerimiz

  • Muhtemel kötü kişiler bir milyar insan arasından çıkabilir.
  • Herkes 100 günde bir otele gider.
  • Her bir otel ortalama 100 kişiyi ağırlayabilir diye kabul edelim. Dolayısı ile 1 milyar kişinin %1 ini herhangi bir gün ağırlamak için 100,000 otelin var olduğunu kabul ediyoruz.
  • Oteller kayıtlarını 1000 günlük geçmişi tutacak şekilde saklıyor ve bu kayıtlara erişebiliyoruz.

Veri içinde aradığımız örüntüyü, iki farklı gün aynı otelde kalan insanlar olarak tanımlıyoruz.

Karşılaşabileceğimiz olası bir durum, gerçekte elimizdeki verinin içinde hiç kötü niyetli kişi olmamasıdır. Yani herkes tamamen rastgele davranarak 0.01 olasılıkla herhangi bir gün 105 otel içinden bir oteli rastgele seçerek ziyaret edebilir.

Eldeki büyük veride hiç kötü niyetli kişiler olmasa bile, veri madenciliği çalışması sonucu, şüpheli kişilerin bulunduğu söylenebilir mi? Basit hesaplamalar yaparak yukarıda yaptığımız kabuller altında bu soruyu cevaplamaya çalışalım.

 

Hesaplamalar

Herhangi iki kişinin aynı gün bir oteli ziyaret etme olasılığı 0.0001 dir. Bu otelin aynı otel olma olasılığı ise bu olasılığın otel sayısına yani 105 e bölümü ile çıkan sayıdır. Bu durumda bu iki kişinin aynı oteli aynı gün ziyaret etme olasılığı 10-9 dur. Bunun iki kere tekrar etme olasılığı ise 10-18 dir.

Şimdi kaç olayın tanımladığımız örüntü kapsamında kötü niyetli olay kapsamına girebileceğini hesaplayalım. Bu kapsamda olayı, iki farklı kişinin, aynı iki günde, aynı otellerde olması olarak ele alalım. Hesaplamalarda basitlik sağlamak için, n popülasyondaki kişi sayısı olmak üzere binom katsayılardan bildiğimiz üzere nC2 ( yani n nin 2 li kombinasyonları) sayısı büyük n değerleri için asimptotik formülasyondan [3]

nC2 ≤ n2 / 2!

olduğundan n2 / 2 olarak alacağız. Bu yaklaşık değeri alarak hesaplamalarımızı yapacak olursak;

Herhangi iki kişi sayısı yaklaşık 109C2 = 5 x 1017 = K

Herhangi iki gün sayısı yaklaşık 103C2 = 5 x 105 = G

Örüntü = Herhangi iki kişi ve herhangi iki günün aradığımız davranışın bir örneği olma ihtimali

ham P-değeri = 10-18

Belirlediğimiz olay tipinin gerçeklenme beklenen değeri = K x G x (ham P-değeri)

m örüntü sayısı olmak üzere,

m = 5×1017 ×5×105 ×10-18 = 250,000

elimizdeki veride istatistiksel olarak anlamlı olmasını beklediğimiz örüntü sayısını verir.

 

Sonuçların Yorumlanması

Kötü niyetli kişiler olmamasına rağmen elimizdeki veriden 250,000 kişilik bir olası kötüler listesi çıkarmış olduk. Bu uygulanabilir bir sonuç da çıkarmadı aynı zamanda. 10 kişi olsaydı bile bu 250,000 kişi arasından bu 10 kişiyi bulmak pratik olarak imkansız olacaktır.

Bu sayı başta belirlediğimiz popülasyon olan 1 milyar kişi içinde olası olan 5 x 1017 tane ikili dikkate alındığında yüzde olarak 5 x 10-13 ü oluyor.  α = 0.05 olarak seçildiğinde 250,000 sayısı bütün mümkün ikilileri gösteriyor anlamına geliyor.

 

Bonferroni düzeltmesi

Oysaki Bonferroni düzeltmesini uyguladığımızda α= α / 5 x 1017 = 10-19 olarak bulunur. Yani, çıkan p değeri 5 x 10-13 < 10-19 şartı sağlanmadığından istatistiksel olarak çıkan ikililerin anlamlı olmadığı sonucunu çıkarabiliriz. Bu şekilde veri madenciliği sonuçlarına göre yanlış pozitif olarak değerlendirilen kişilere karşı yapılacak gereksiz işlemlerin önüne geçmiş oluyoruz.

 

İyileştirme

Aldığımız sonuca göre başta aldığımız örüntü tanımlarını daha fazla daraltmak gerektiğine hükmedebiliriz. Bu daraltma, örneğin aynı otelde iki gün kalma şartını üç güne çıkartarak yapılabilir.

Bu örnek çerçevesinde görüldüğü üzere, büyük veri ile çalışırken eldeki verinin işlenmesinde klasik yöntemlerin kullanılması sırasında istenmeyen durumlar oluşabilir. Bu durumlar kurum ve şirketlerde bazen etkisi hissedilmeyen, bazen de etkisi para, zaman veya prestij kaybına yol açabilen şekillerde de hissedilebilen kararların alınmasına yol açabilir [4].

 

Kaynaklar

[1] Multiple Hypothesis Testing in Data Mining, Doctoral Dissertation, Sami Hanhijarvi, Department of Information and Computer Science, Aalto University, Finland, 2012.

[2] Mining of Massive Datasets, A. Rajaraman, J. Leskovec, J. D. Ullman, p. 5, 2014

[3] http://en.wikipedia.org/wiki/Binomial_coefficient#Bounds_and_asymptotic_formulas

[4] http://bytesizebio.net/2010/10/27/but-did-you-correct-your-results-using-a-dead-salmon/

 

 

 

 

Apache Solr ile Otomatik Tamamlama

Bu yazımızda Apache Solr kullanılarak otomatik tamamla ( bazen tavsiye olarak da isimlendiriliyor) nasıl yapılır onu anlatacağım.

Bu örneği olabildiğince genel hazırlamak için solr dağıtımını indirdiğimizde içinden çıkan varsayılan örnek üzerine inşa edeceğiz. java –jar start.jar ile çalıştırdığımız.

Schema.xml‘e yapılacak eklentiler:

İki tane yeni alan ve tip ekleyelim ve bu alanları copyField ile dolduralım.

<field name="subject_edgy_keyword" type="edgy_keyword" indexed="true" stored="false"/>
<field name="subject_edgy_ws" type="edgy_ws" indexed="true" stored="false"/>

<copyField source="subject" dest="subject_edgy_keyword"/>
<copyField source="subject" dest="subject_edgy_ws"/>

<fieldType name="edgy_keyword" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    <tokenizer class="solr.KeywordTokenizerFactory" />
    <filter class="solr.TrimFilterFactory" />
    <filter class="solr.LowerCaseFilterFactory" />
    <filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="20" />
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.KeywordTokenizerFactory" />
    <filter class="solr.LowerCaseFilterFactory" />
  </analyzer>
</fieldType>

<fieldType name="edgy_ws" class="solr.TextField" positionIncrementGap="100">
  <analyzer type="index">
    <tokenizer class="solr.WhitespaceTokenizerFactory" />
    <filter class="solr.LowerCaseFilterFactory" />
    <filter class="solr.EdgeNGramFilterFactory" minGramSize="1" maxGramSize="20" />
  </analyzer>
  <analyzer type="query">
    <tokenizer class="solr.WhitespaceTokenizerFactory" />
    <filter class="solr.LowerCaseFilterFactory" />
  </analyzer>
</fieldType>

Solrconfig.xml‘e yapılacak eklentiler: aşağıda gösterildiği tamamla isimli bir request handler kaydediyoruz.

<requestHandler name="/tamamla" default="false">
  <lst name="defaults">
    <str name="defType">dismax</str>
    <str name="echoParams">none</str>
    <str name="omitHeader">true</str>
    <float name="tie">0.01</float>
    <str name="qf">subject_edgy_ws^8 subject_edgy_keyword^4</str>
    <str name="pf">subject_edgy_ws^2 subject_edgy_keyword^20</str>
    <str name="fl">subject</str>
    <int name="ps">0</int>
    <int name="qs">0</int>
    <str name="q.alt">*:*</str>
    <str name="mm">100%</str>
    <str name="version">2.2</str>
    <int name="rows">10</int>
    <int name="start">0</int>
  </lst>
  <arr name="components">
    <str>query</str>
  </arr>
</requestHandler>

Veri: Umuma açık bulunan MovieLens 10M verisini kullanacağız. ml-10m.zip dosyasını indirebilirsiniz.

Bu sıkıştırılmış klasörü açtığımızda içinden çıkan dosyalardan bize lazım olanı movies.dat dosyası. Bu dosyayı solr’a gönderebilmemiz için ufak bir iki değişiklik yapacağız. İndirdiğimiz dosyanın orijinal içeriği (10K satır) şu şekilde olacak:

solr1

Bu değişiklikler bir metin editöründe bul-ve değiştir işlemi olacak. Notepad++, TextWrangler gibi bir programla açıp şu iki işlemi sırasıyla yapalım:

1) Bütün | karakterlerini boşluk ile değiştirelim.

2) Bütün :: karakterlerini | ile değiştirelim.

solr03

Dosyayı bu hali ile kaydedelim. Artık elimizde solr’a doğrudan beslenebilecek formatta getirdik. Curl programı ile bu dosyayı aşağıdaki komut ile indexleyelim:

curl "http://localhost:8983/solr/update?commit=true&fieldnames=id,subject,&separator=|&encapsulator=/" --data-binary @movies.dat -H 'Content-type:application/csv; charset=utf-8'

İşlemin sonunda söyle bir mesaj almamız lazım her şey yolunda gittiyse :

<?xml version="1.0" encoding="UTF-8"?>
<response>
  <lst name="responseHeader">
    <int name="status">0</int>
    <int name="QTime">2404</int>
  </lst>
</response>

Not: Windows işletim sistemlerinde curl programı hali hazırda gelmiyor. Ama Windows için sonradan kurmak mümkün. Ama ek kurulum yapmak istemezseniz, solr’un içinden (example/exampledocs dizini altında) post.jar kullanarak indeksleme için aşağıdaki komut satırını kullanabilirsiniz.

java -Durl="http://localhost:8983/solr/update?commit=true&fieldnames=id,subject,&separator=|&encapsulator=/ " -Dtype=text/csv -jar post.jar movies.dat

Her şey yolunda gittiyse, işlem sonunda siyah ekranda şuna benzer bir çıktı alırsınız:

SimplePostTool version 1.5
POSTing file movies.csv
1 files indexed.
COMMITting Solr index changes to ...
Time spent: 0:00:04.649

Arama: Kullanıcı tuşlara bastıkça, her tuşa basma sonunda /tamamla adresine tuşlanmış olan karakter serisini gönderiyoruz. Kullanıcı w tuşuna basmış olsun,
http://localhost:8983/solr/collection1/tamamla?q=w&wt=json&indent=true
gelen ilk üç sonuç şu şekilde olacaktır.

"subject": "Wild Wild West (1999)"
"subject": "What Women Want (2000)"
"subject": "When We Were Kings (1996)"

solr04

Yukardaki resimde (godf sorgusuna) dikkat ettiğiniz gibi ilk kelimesi godfather olanlar üstte, sonrasında ise ilk kelimesi olmadığı halde godfrey geçen film başlıkları da gelmiştir.

sex c sorgusuna ise gelen sonuçlar aşağıdaki gibidir.

http://localhost:8983/solr/collection1/tamamla?q=sex+c&wt=json

solr05

Eğer otomatik tamamlanın sıralamasına dahil etmek istediğiniz başka nümerik alanlarınız varsa onları da edismax’ın boost parametresi ile ekleyebilirsiniz. Örneğin bu örnekte filmlerin izlenme sayıları (view_count) elimizde olsaydı boost=sqrt(view_count) FunctionQuery olarak sıralamaya etki ettirebilirdik. Ya da son iki yılda çıkan filmleri üste getirmek için bq=year:[2013 TO 2014]^50 diye parametre ekleyebilirdik.

Kaynakça:

Auto-Suggest From Popular Queries Using EdgeNGrams

ExtendedDisMax

Different Ways To Make Auto Suggestions With Solr

Super flexible AutoComplete with Solr

Apache Pig – Domuzcuğun Hikayesi

pig-on-elephantApache Pig

Apache Pig, Apache Hadoop üzerinde prosedurel bir data akışı yazmayı sağlayan bir veri işleme platformudur. Veri kullanıcılarına Hadoop’un güçlü, dağıtık ve esnek yapısına ileri seviye java kodları yazmadan daha üst bir katmandan erişim imkanı sağlayan bir yapıdır.

Pig’in iki önemli bileşeninden Pig Latin dilini kullanarak kullanıcılar data akışı scriptleri yazabilirler ve Pig bunları Hadoop üzerinde MapReduce kodlarına çevirerek run eder. Pig’in en büyük getirisi Java bilmeyen kullanıcılara da Hadoop üzerinde üstseviye prosedurel bir script dili ile veriye ulaşma ve işleme imkanı vermesi, Map Reduce programları yazmaya gerek bırakmamasıdır.

Tabi şöyle bir problem veya risk yine buradada olacak; nasıl ki RDBMS üzerinde veri modeli, veri uzmanlığı olmayan kullanıcılar performans problemlerine yol açan anlamsız bazı SQL’ler yazabiliyorsa burada da pig latin scriptleriyle yazılan scriptlerde de benzer bir risk var. Aynen SQL’de olduğu gibi veri konusunda uzman veriyi iyi tanıyan kişilerin kontrolu altında bu data akışlar yazılmalıdır. Kullanıcı nerede hangi veriye hangi join yapacağını iyi bilmelidir.

Bu riski eski Yahoo Pig geliştirme ekibinden Alan Gates Pig’i şöyle tanımlıyor “ “Because… Pig is domestic animal, does whatever you tell it to do.”
Yani “Çünkü…Pig evcil bir hayvandır, ne söylerseniz onu yapar. ”

Pig

Pig, Yahoo bunyesindeki bir geliştirme ekibi tarafından Hadoop üzerinde veri transform ve analiz işlemlerini yazmayı hızlandırmak amacıyla geliştirildi. Alan Gates’de bu ekibin üyelerinden biriydi daha sonra kendisi şu anda Hadoop dünyasının önemli katkı veren şirketlerinden Hortonworks’un kurucularından birisi oldu.

Alan Gates’in O’Reilly’den Pig Programming kitabına ulaşmak için : http://www.gocit.vn/files/Oreilly.Programming.Pig-www.gocit.vn.pdf

Yazılan Pig Latin scripti bir dizi Map ve Reduce işlerine dönüştürülüyor ve Hadoop üzerinde çalıştırılıyor. Pig kodu geliştiricisi yazdığı Pig Latin scriptinin arka tarafta kaç adet MapReduce koduna çevrildiğini, compile edildiğini, paketlenip çalıştırılarak sonuçların getirildiğini farketmiyor. Bunu ancak logdaki ifadelere bakarak anlayabiliyor.

Nerelerde kullanılabilir

ETL (Extract-Transform-Load) işlemlerinde ve özellikle de ETL’in “T”’si Transform işlemlerinde kullanılabilir, tabi klasik RDBMS üzerindeki ETL’den farklı bir bakış gerektirecektir.

Ham Veri üzerindeki bazı ön araştırma, veri temizliği, analiz, hazırlık işlemlerinde Doğrusal veya DAG yapısında kompleks veri işleme ve dönüştürme akışlarında

Pig ismi nereden geliyor

Pig’in geliştiricilerinden Alan Gates bu konuda kendilerine çok soru geldiğini, Pig isminin bir kısaltma olmadığını ekipteki bir kişinin bu ismi bulduğunu ve sonra hoşlarına gittiğini ifade ederken, IBM’in bu konudaki yorumu bana çok daha anlamlı ve güzel geldi. “Nasılki bir domuz, önüne koyduğunuz (hatta koymadığınız) her şeyi yiyebildiği gibi, Pig’de gösterdiğiniz her türlü veriyi işleyebildiği için Pig(Domuzcuk) adını almıştır.”

Pig deyince

Aslında Pig deyince iki şeyden bahsediyoruz; birincisi Pig Latin diye isimlendirilen programlama dili, diğeri Hadoop sistemi üzerindeki Pig Latin kodlarının çalıştırıldığı ortam.

Pig latin programlama diline baktığımızda alt alta birbirini takip eden adımlar halinde prosedurel bir dil ile karşılaşıyoruz. Her adımda oluşan veri bir sonraki adıma aktarılabiliyor ancak saklanmıyor. Yani session bittiğinde ara bir adımdaki verinizi kalıcı hale getirmediyseniz ulaşamıyorsunuz. Bunu data işleme üzerine geliştirilmiş Base SAS programlama diline benzetebiliriz. SAS kodlarıda alt alta adımlardan oluşur her adımda bir işlem yapılarak devam edilir, eğer kalıcı hale getirmezseniz session bittiğinde ara adımlardaki veriler kaybolur.

Pig’i en genel haliyle 3 adımdan ibarettir diyebiliriz.

  1. Veriye ulaşma; HDFS sisteminden işlenecek veriyi load etme adımı
  2. Veri işleme veri dönüştürme amaçlı transform adımları
  3. Dump yani çıkan sonuç verisini bir yere saklama veya ekrana getirme adımı

Çalıştırma

Pig kodlarını çalıştırmak için 3 farklı opsiyonumuz var.

Script: Piglatin komutlarından oluşan .pig Script’leri oluşturmak ve bunları bir arayuz veya komut satırından çalıştırmak
Not: Normal şartlarda Pig verilen akıştaki her işlemi dönen sonuç değerine bakmaksızın baştan sona çalıştırır. Eğer akışta bir adımda hata alınırsa ve genel akışın durmasını isterseniz pig scriptinizi çalıştırırken “-F” veya “-stop_on_failure” opsiyonu verebilirsiniz. Yani;

$ pig -F pigisleri.pig
yada
$ pig -stop_on_failure pigisleri.pig
İle Pig scriptiniçalıştırmanız gerekir.
Shell mode: Grunt, Pig’in interaktif shell ortamıdır. Piglatin komutlarını shell ortamında çalıştırabilirsiniz.
Embedded: Pig programları Java kodlarının içindende çalıştırılabilir.

Pig Extensible

Pig’in güçlü yanlarından biriside Pig tarafından sağlanan fonksiyon ve komutlar sizin için yeterli olmazsa, java bilginizde yeterliyse kendi fonksiyonlarınızıda tanımlayabilir ve bunlarıda scripleriniz içinde kullanabilirsiniz.

Pig Latin’in üstün yanları

Pig’in en önemli bileşeni Hadoop üzerinde çalışan Pig Latin programlama dili veri işlemede pek çok avantaj sağlar

Prosedurel Yapısı

A = Load Data
C = Transform A
D= Transform C
Dump D

Yukarıda verilen Pig Latin’in genelleştirilmiş yapısına baktığımızda alt alta adımlarla baştan sona veri işleme akışı net olarak görülebiliyor. Her adımın sonucu bir sonraki adımda kullanılarak zincirleme anlaşılabilir bir akış sözkonusu.

Kontrol Noktaları

Pig Latin koduna baktığınızda her adımda oluşan verinin bir sonraki adıma aktarıldığını ancak saklanmadığını görüyoruz. Veri ile uğraşanlar iyi bilir, peki akışta bir yerde bir kesinti veya hata alınırsa ne olacak, çok uzun süre çalışmış veya kritik bir verinizi kaybetmeyi göze alabilir misiniz? Bunun çözümü için Pig Latin kodunuzda, akışınızın kritik noktalarına verilerinizi kalıcı tutmayı sağlayan bazı adımlar koyabilirsiniz. Yukarıdaki örnekte diyelimki C verisi kritik.

A = Load Data
C = Transform A
Store C into ‘Csakla’;
D= Transform C
Dump D

Bu şekilde C verisi Csakla ile kalıcı olarak korunur.

Optimizasyon

Pig Latin ile geliştirilmiş script kodları SQL benzeri ( Sort, Group By, Join ..) pek çok işlem yapmakta olabilirler. Bu nedenle bunları yazarken domain bilgisi, veriyi iyi tanıma, büyük veri işlemeyi bilmek gerekir.

Ayrıca Pig’in yazılan kodu nasıl yorumlayacağını nerelerde bazı hintler kullanılabileceği bilinmelidir. Optimizasyon konusu ayrı bir yazı konusudur.

DAG (Directed acyclic graph) Graf yapısı

Pig Latin kodları için veri akışı yazmaya olanak sağlar demiştik. Bu akış baştan sona birbirini takip eden adımlar olabileceği gibi bastan itibaren paralel bir şekilde ikili üçlüde devam edebilen Graf şeklinde flowlarda yapılabilir.

Pig Uzmanlığı

2008 yılında ilk versiyonu yayınlanan Apache Pig 2009 yılından hızla populer hale gelmeye basladı. Öyleki 2009 yılı sonunda Yahoo’nun aradığı hadoop job ilanlarından yarısı Pig job’larıydı.

Sonuç

Pig Latin geleneksel programlama dillerinden veya SQL’den farklı bir paralel veri işleme akışı dilidir. Veri kaynaklarının ve tiplerinin giderek çeşitlendiği, hızlı veri işlemenin daha önemli hale geldiği bir dünya Pig ‘i daha da önemli hale getirmektedir.

Pig’in ne olup ne olmadığı ile ilgili SQL ile karşılaştırmalı bir analiz yapabiliriz. SQL neredeyse günümüzde bir analiz yapmak veya bir rapor almak isteyen herkesin bildiği, tanıdığı bir sorgu dilidir. Ancak SQL bu kadar yaygın olmasına rağmen sadece RDBMS üzerinde şeması, yapısı belli veriler üzerinde sorgu için kullanılır.

Buna karşın Pig, Hadoop’un güçlü paralel ve dağıtık veri işleme yeteneğini kullanarak ham, doğal halde, farklı tiplerde pek çok veri üzerinde işlem yapmayı sağlamaktadır.

Alan Gates’in bu konuda yine güzel bir benzetme yapıyor;

“Diyelimki ben çok iyi ingilizce ve çok az da fransızca biliyorum, buna karşın eşim çok iyi fransızca konuşabiliyor. İkimizde gezmek için Fransa’ya gidiyoruz, ben Fransa gezim sırasında herkesin az çok bildiği global bir dil olan ingilizcemin geçerli olduğu daha çok turistik alanları, şehir merkezlerini rahatça gezebiliyorken, eşim ise gezisi sırasında çok iyi Fransızca biliyor olması sebebiyle, Fransa’nın pek turistlerin uğramadığı en ücra kasabalarını keşfedebiliyor, oralardaki kişilerle konuşabiliyor, benim ulaşamadığım pek çok şeyi öğrenebiliyor. Onun Fransa gezisi sonucu elde ettiği bilgiler, deneyim benden çok farklı, çünkü o yörenin ana dilini biliyor.

İşte SQL veriye ulaşma, veriyi sorgulama dünyasının ingilizcesi, herkes biliyor, herkes kullanabiliyor, ancak ulaşabildiği veriler sınırlı, Pig Latin ise lokal dilleri ifade ediyor, SQL ile ulaşılamaya yerlere, verilere ulaşıyor, daha fazla sayıda veriyi işleyebiliyor, Hadoop ile entegre olarakda paralel ve hızlı olarak bunu yapabiliyor “

Referanslar

[1] http://pig.apache.org/
[2] http://pig.apache.org/docs/r0.7.0/piglatin_ref1.html
[3] http://pig.apache.org/docs/r0.9.1/perf.html
[4] http://sites.computer.org/debull/A13mar/gates.pdf
[5] http://www-01.ibm.com/software/data/infosphere/hadoop/pig/
[6] http://developer.yahoo.com/blogs/hadoop/comparing-pig-latin-sql-constructing-data-processing-pipelines-444.html [7] http://www.slideshare.net/Hadoop_Summit/innovations-in-apache-hadoop-mapreduce-pig-hive-for-improving-query- performance
[8] http://infolab.stanford.edu/~usriv/papers/pig-latin.pdf
[9] Alan Gates, Programming Pig , O’Reilly, 2011
[10] http://hortonworks.com/blog/pig-performance-and-optimization-analysis/
[11] http://blog.cloudera.com/wp-content/uploads/2010/01/IntroToPig.pdf

Malaysia Airlines Flight 370

Pekin’e varmak üzere 8 Mart 2014 de Kuala Lumpur’dan havalanan 153 ü Çin vatandaşı olmak üzere 15 ülkeden 227 yolcu ve 12 mürettebat olmak üzere toplam 239 kişi taşıyan Boeing 777-200 tipi yolcu uçağı oniki gündür kayıp. Uçağın ve yolcuların akıbeti konusunda somut bir açıklama henüz yok. Olayın ilk günlerinde, bilinmeyen bir nedenle düştüğü düşünülen ve normal rotasında güney çin denizinde yapılan kurtarma ve arama çalışmaları son birkaç gündür uçağın rotasının ortadan kaybolmadan hemen önce değiştirildiği iddiası ile farklı bir boyut kazandı. Artık birçok değişik senaryonun düşünüldüğü ve konuşulduğu bir olay haline geldi.

Bugün itibari ile 26 ülkenin araştırma ve arama eforuna katıldığı, dünya tarihindeki en karmaşık arama operasyonlarından birini, pazarlama ve satış ağırlıklı söylemlerden uzakta kalarak, büyük veri teknolojilerinin gelmiş olduğu noktadan değerlendirmesini yapmaya çalışacağız.

Veri Kaynakları

İlişkisel Veritabanları; Öncelikle normal bir ticari uçuşta toplanan bilgilerle başlamakta fayda var. Bu bilgiler, temel olarak, uçuş mürettebatı, yolcu listeleri, uçuş seyir, uçak bakım, havayolu şirketi, uçulan lokasyonlar, bu lokasyonlardaki güvenlik ve yer hizmeti veren personel, uçağın taşıdığı eşya ve diğer yükler, yeme ve içme desteğinin alındığı firma ve kişiler, uçuşun gerçekleştiği hava koşulları vb. ilişkisel veri tabanlarında tutulan fakat genel olarak bir merkezden işlenmesi için yapılandırılmamış bilgilerdir. Bu bilgiler her uçan uçak için vardır ve 11 Eylül olaylarında teknik sebepler ve hava korsanlığı dışında sebeplerle de yakından takip edilmesi gerektiği ortaya çıkmıştır.

Kapsamı Belirli Büyük Veri; Ayrıca, bir uçağın uçması sırasında bu bilgiler dışında uçuşu gözleme amacı olmadan toplanan bilgiler de vardır ve normal bir uçuş söz konusu olduğunda bu bilgilerin kullanılması doğrudan aklımıza gelmez. Uydulardan alınan video ve fotoğraflar, değişik elektronik sinyal verileri, uçuş rotasında bulunan ve değişik amaçlarla kullanılan radar ve gözlem verileri, askeri ve sivil amaçlı uçan uçakların üzerindeki radarların topladığı veriler, uçaktaki kişilerin cep telefonlarının herhangi bir baz istasyonu ile yaptığı sinyalleşme bilgileri, yine uçaktaki yolcuların internette yaptıkları aktiviteler gibi.

Kapsamı Belirsiz Büyük Veri; Bunların dışında uçak ve gerçekleşen uçuş dışında, uçuş öncesi ve olay sırasında olaya ışık tutacak doğrudan bağlantısı olmayan ya da olduğu başta düşünülmeyen kişilerin yaptıkları telefon konuşmaları, mesajlaşmalar, internette yaptıkları her türlü faaliyet, istihbarat bilgileri var.

Bütün bu bilgilerin olayla ilgili olarak “ne? ne zaman? nerede? nasıl? neden? kim?” sorularına cevap vermek için kullanıldıkları bir dünyada, büyük veri teknolojilerinin yeri neresi dediğimizde bazı reklam ve pazarlama faaliyetlerinin yapıldığını görüyoruz. Gerçek ise 12 gündür kayıp olan söz konusu uçağın nerede olduğu ve başına ne geldiği ile ilgili herhangi bir haber veya bilginin olmadığı.

Temel Soru

Olayın genel resmini ortaya koyduk, büyük veri teknolojileri bu problemi çözmede kullanılmadı mı? Kullanıldı ise neden halen çözülemedi? Burada büyük veri teknolojilerinin bu problemin çözümünde kullanmanın zorlukları ve ileride çözüm üretebilmesi için yapılması gerekenler neler?

Çözüm Bileşenleri

Entegrasyon

Öncelikle büyük veri teknolojileri mevcut veri tabanı teknolojileri ile entegre bir şekilde çalışabilmektedir. Bu konuda önemli yol alınmış durumda ve sıkıntı olabilecek konu veri kaynaklarına doğrudan erişim haklarının olmaması olabilir. Böyle bir olayda farklı kurum ve ülkelerdeki veri tabanlarına hızlı erişim ihtiyacı olduğundan, bilgilerin paylaşımı için bir yöntem ve kuralların olup olmadığı sorusu akla geliyor. Burada farklı dillerde olan verilere erişmenin ve bu bilgileri kaynaştırmanın zorluklarının da teknik olarak çözülmesi gerektiğini belirtmek gerekiyor. Örnek olarak; Malay dili ve Çin dili uçağın kalkış ve iniş noktalarında kullanılan diller ve bu dillerdeki bilgi kaynaklarının birleştirilmesi gerekiyor.

Büyük Veri kaynaklarına Erişim ve İşleme

Büyük veri daha da zor olarak erişilebilen bilgiler olacak kuşkusuz. Uydulardan alınan olay yeri ile ilgili görüntülerin işlenmesi başlı başına bir büyük veri problemi. Şu anda Amerika Birleşik Devletleri toplam yüz ölçümüne denk olan Günay Asya da bir bölgeye ait uydu görüntülerinin işlenmesinden bahsediliyor[1]. Zaman dilimi de olayın üzerinden geçen zaman arttıkça artıyor tabii ki. Bu bilgilerin kim ile, hangi şartlarda paylaşılacağı, ve çıkan sonuçların kim tarafından kullanılacağı da net değil. Fotoğraf, radar, GSM baz istasyonu bilgileri gibi daha sayısız veri kaynağı benzer durumda. Uçaktaki kişilerin yapmış olduğu internetteki aktivitelerin bilgiye dönüştürülmesi de ayrı bir problem.

Bunların dışında daha çok istihbarat servislerinin ilgi alanına giren konularda, uluslararası güvenlik açısından konunun değerlendirilmesi gerekiyor ki bu yazının dışında tuttuğumuz bir konu.

Ele alınan problem bağlamında düşünüldüğünde, eski yöntemler yeni bir veri işleme teknolojisi ile birlikte günümüz dünyasının çok karmaşık ve hızlı çözüm gerektiren problemlerine çözüm üretmek için kullanılmak istendiğinde “acaba uydu görüntülerinde uçağın enkazlarını bulabilir miyiz?” şeklinde bazı belirli soruların cevaplanmasında kullanılabilir. Ama ilgili bütün veri kaynaklarına erişen, bunları ele alınan problem kapsamında hızla değerlendiren bir sistemin çok uzağındayız.

Farklı bir dünya kooperatif akıllar

Bunun yerine, interneti ortak insanlık aklının somutlaşması olarak gören görüşü haklı çıkaracak tarzda yaklaşımları görüyoruz. Hadoop tarzı paralel işleme ve sonuç çıkarma kapasitesine sahip bir ortam olarak web i, işlemciler olarak da bilgisayarlar dışında insanları da kullanan bir yaklaşımda uydu görüntülerini gönüllüler tek tek inceliyor ve bulgularını paylaşıyorlar [2]. İsmi Tomnod ve anlamının Moğolca da Büyük Göz anlamına geldiği söyleniyor [3]. Sloganları şu “Join the Tomnod team! Your task is to explore the satellite images and tag any important locations you find.”

Tomnod, bütün örüntü işleme algoritmalarının performansına erişmeye çalıştığı, en iyi örüntü işleme makinası olan insan beyninin, en azından benzeri bir algoritma yapılana kadar böyle bir problemde kooperatif olarak nasıl kullanılabileceğine ilişkin değişik problem çözüm yöntemlerine farklı bir örnek sunuyor.

Yeni bir çağ, yeni bilgi işleme teknikleri, fakat aklımızda çözülmesi daha önce düşünülemeyen sorular. Bu soruların çözülebilmesi, belirli yöntemlere odaklanarak değil problemlere odaklanarak yapılabilir ancak. Ülkemizde ve dünyada var olan problemlere çözüm üretmek istiyorsak, yol ve yöntemleri ararken teknolojiden faydalanma ve gerektiğinde yeni teknolojileri üretmek kaçınılmazdır. Bunun için sadece problemlere odaklanmamız gerekiyor.

Kaynaklar;

[1] http://www.theguardian.com/world/2014/mar/13/malaysia-airlines-flight-satellite-images

[2] http://www.dailymail.co.uk/news/article-2583807/Did-Malaysian-fisherman-missing-flight-MH370-flying-low-Gulf-Thailand.html

[3] http://emergencyjournalism.net/featured-tool-tomnod/

[4] http://www.tomnod.com/nod/

Büyük Veri, Veri Bilimi ve Ontoloji

Bu yazıda büyük veri ve işlenmesi için temel unsur haline gelen veri bilimcinin temel uğraş alanına ilişkin kendi fikirlerimi paylaşacağım. Okuyucu büyük verinin geçmişi, bugünü ve geleceğine ilişkin genel bir bilgi edinecek, konunun temel bileşenleri ve aralarındaki ilişkileri verilen referanslarla birlikte zenginleştirme ve kendi yorumunu oluşturma fırsatı bulacaktır. Konu hakkında bilgi ve tecrübesi olan kişiler için de farklı bir görüş alma fırsatı sunulmaktadır.

 

Büyük Veri Kavramı

1960 lı yıllardan itibaren gelişme evresinde olan veri analizi ve entegrasyonu çalışmalarının bir bütün olarak değerlendirilmesi ile Veri Bilimcisi (ing. Data Scientist) [1] teriminin 1996 yılında ortaya çıkmasını ilişkilendirebiliriz  [2, 7]. O yıllar, büyük miktarda verinin toplandığı ilişkisel veri tabanlarında önceden fark edilemeyen bilginin keşfedilmeyi beklediği yıllar olarak da hatırlanır [3] .

 

Büyük verinin anlamlandırılması ve bilgiye dönüştürülme süreci, önceki bilimsel ve teknolojik birikimlerin üzerine yeni yapılan çalışmaların ve ortaya konan yeni problemlerin eklenmesi, Hadoop [6] gibi  dağıtık işleme yapan ve kolayca erişilebilen açık kaynak kodlu bir yazılımın ortaya konması ile farklı bir aşamaya geldi. Daha önce başa çıkılabilenden çok daha fazla veri ile başa çıkmak, dolayısı ile iş dünyasına, araştırmalara yön verecek kararlar alacak bilgiler elde etmek mümkün hale geldi.

 

Büyük verinin grid hesaplama (ing. Grid Computing) yöntemleri ile işlenmesinin en az yirmi yıllık bir geçmişi olmasına rağmen, uygulandığı problem ve uygulayan kurum ve şirketlerin sayısı yıllar içinde sınırlı kaldı. Bu sınırlamada verinin her işlem öncesi ağ (ing. Network) üzerinde ilgili makineye taşınmasının problemler çıkarması ve çözümün bir türlü istenen şekilde gelmemesinin etkili olduğu söylenebilir. Yeni fikir, verinin merkezi silolarda tutulup onu işleyecek griddeki makinelere taşınması yerine, doğrudan en başta verinin gridi oluşturan makinelere dağıtılması, çalışacak prosedürün verinin olduğu makineye yollanması şeklinde ortaya çıktı. Bunu ilk çözen Google şirketi oldu ve problemi nasıl çözdüğünü 2003 yılından itibaren yayınladığı üç makale ile dünyaya duyurdu [16, 17, 18]. Böyle bir sistemin temel bileşenlerini anlatan bu makaleler, özel bir dağıtık dosyalama sistemi ( ing. Google File System -GFS), Dağıtık tablo yapısı (ing.  BigTable ) ve bu dağıtık yapıda işleme yapacak bir algoritma (ing. MapReduce) dan oluşmaktaydı.

Daha sonraki süreçte bu makalelere dayanarak yapılan çalışmalar sonucu Hadoop doğdu. Tabii bu süreçte verinin birçok makineye dağıtılarak dağıtık işlenmesinin mümkün hala getirilmesi, aynı verinin anlamlandırılması ve sonuç çıkarımında da çok yol alındığı anlamı çıkarılmamalı [8]. Bu problemin henüz tam anlamı ile çözülememesinin sebeplerini aşağıda detaylandıracağız, fakat öncelikle bu sürecin sahibi olarak isimlendirilen Veri Bilimci ve neden bu ismin ön plana çıktığı üzerinde durmakta fayda var.

 

Veri Bilimci ve Ontoloji Kavramı

Science yani bilim nedir? Latince scientia kelimesi yani bilgiden geldiği söylenir. Evren hakkında test edilebilir açıklamalara ve tahminlere dayandırılmış bilgiyi, organize eden, sınıflandıran disiplin olarak tanımlamak mümkündür [5]. Tabii bu işle meşgul olan kişiye de bilimci diyoruz. Bilimsel çalışmalar gözleme dayanır ve bu veri (ing. Data) toplamak ile eşdeğerdir. Toplanan verilerin daha önce çözülmemiş bir problemi çözmek için belli bir sistematiğe dayanarak incelenmesi bilimsel, daha önce çözülmüş bir problemin farklı bir alanda yada ölçekte uygulanması ise genellikle mühendislik olarak görülebilir.  Bu açıdan bakıldığında bilim insanı çözülmüş problemlerle uğraşmaz, yani gözlem zaten bilinen bir gerçeği, örüntüyü ortaya çıkarmak için yapılıyorsa mühendislik alanına geçilmiş olur. Verinin mühendisliği ile bilimi arasında ki bu fark nereden kaynaklanıyor? Bu konuda birçok yazı var ve henüz üzerinde uzlaşılan genel net bir tanım olduğunu söylemek güç [19, 20].

 

Konu üzerinde kendi görüşümüzü geliştirmek için, Türkiye’de yazılım dünyasında akademik çalışma yapanlar dışında pek ilgi görmediğini düşündüğümüz farklı bir disiplinden bahsetmek zorunluluğu hissediyoruz. Felsefenin bir kolu olan ve metafizik olarak adlandırılan bir çalışma alanının içinde yer alan Ontoloji [9] nin “Varlık nedir? Varoluş nedir? Bir nesnenin özellikleri veya ilişkileri nedir? Var oluş bir özellik midir? Bir nesne nasıl değişir, nasıl yok olur?” gibi sorulara cevap ararken kullandığı bilimsel birikimden yararlanmak gerekiyor. Peki büyük veriyi incelerken yazılım dünyası ontolojiden nasıl faydalanabiliyor?

 

Büyük veri içindeki bilgiye dönüştürme sürecinin en önemli aşamalarından olan nesneleri tespit etmek ve bu nesneler ve aralarındaki ilişkilerin gösterim yapısına karar verme sürecinde, bilgi mühendisi (ing. Knowledge Engineer) [13],  ontoloji biliminin de katkısı ile geliştirilmiş dilleri kullanır. Bilgi Tabanlı Sistemler (Knowledge-Based Systems) kurmak için bu kaçınılmazdır [14]. Bilimsel bir problem çözme yöntemi uygulanmadığı durumda, ontolojik [12] açıdan incelenme süreci yerine her zaman tekrar tekrar aynı analiz ve çözümleme çabalarına girişmek, ciddi zaman ve emek kaybı anlamına gelmektedir. Daha da önemlisi çözülen problem her defasında yeniden çözülmek durumundadır. Bu çalışmalar sırasında alana bağlı olarak değişik bilim dallarından insanlar işbirliği içinde olabilirler. Örneğin, fiziksel nesneler ile ilgili bir veriden bahsediyorsak, fizik bilimcisi, okyanus ile ilgili bir veriden bahsediyorsak okyanus bilimcisi, uzay ile ilgili bir veriden bahsediyorsak uzay bilimcisi gibi. Peki, ya eldeki verinin gerçek dünyada doğrudan bir karşılığı yoksa ve sanal dünya dışında var olmayan bir bilgiden söz ediyorsak hangi bilim dalından yardım alınacak? İşte bu noktada veri bilimcisinin devreye girmesi gerekiyor ve veri dünyasında olan nesneler ve ilişkileri konusunda bilgi mühendisi ile birlikte çalışıyor. Tabii, bilgi mühendisi zaten bilgi teknolojileri dünyasından olan bir kişi olduğundan dolayı veri bilimcisi ile bilgi mühendisini çoğu durumda aynı kişide birleştirmek pratik bir sonuç olacaktır. Ontolojik olarak incelenen veri, özellikle alan bilgisinin de olduğu bir ontolojik yapı içerisinde incelendiğinde, tekrarlar algoritmalara aktarılmış olacak, veri bilimcisi daha önce yapılmayana odaklanacaktır [10]. Bu seneki Ontology Summit 2014 ün ana konusu ve vurgusu bu odaklanmayı somut bir şekilde göstermektedir “Big Data and Semantic Web Meet Applied Ontology” [11].

 

Büyük Veri İle İlgili Yeni Yaklaşımlar

1989 da HTTP (HyperText Transfer Protocol) protokolünü ve HTML (HyperText Markup Language) formatını icad ederek; yazı, resim ve video içeren zengin içerikli dokümanların birbirine bağlanması fikri olan WWW (World Wide Web) nin mucidi ve babası olan Tim Berners-Lee, benzer  bir devrimin verilerin birbirine bağlanması ile de gerçekleşeceğine inanıyor [15]. Lee nin Bağlı Veriler (ing. Linked Data) olarak adlandırdığı verilerin birbirine bağlanması ile Semantic Web gerçek olacak ve Web de yer alan verilerin otomatik olarak algoritmalarla işlenebilir bir semantik yapıda olması sağlanabilecek. Her yeni gelen verinin daha ilk saklanma aşamasında aynı insan beyninde olduğu gibi ilişkili olduğu bilgi ile birlikte saklanması bu şekilde çok büyük miktarda bir sonradan işleme (ing. post processing) gereksinim duyulmadan aranan bilginin bulunması ve çıkarım yapılabilmesinin mümkün olması sağlanmış olacak. Yani büyük veride en acılı süreç olan verilerin toplanması ve tasnif edilmesi aşaması Web in kendisinin bu şekilde organize olması ile önceden çözülmüş olacak.

 

Veri Bilimcisinin Kullandığı Yaklaşımlar

Verinin yapılanması dışında, işlenip bilgiye dönüştürülürken kullanılacak algoritmalar veri bilimcisinin sıklıkla başvurduğu araçlar olmak durumundadır. Bu algoritmalardan en çok kullanılanlar veriyi ele alma tarzına göre iki yaklaşıma dayanmaktadır.

 

Birinci yaklaşım olarak, gözlenen sistemden elde edilen verinin stokastik yani bir şekilde rastgelelik taşıdığı ve çözüm için verinin modellenmesinin öncelikle bu rastgeleliği modellemekten geçtiği düşüncesi hakimdir ve istatistiki algoritmalara dayanır.

 

İkinci yaklaşım ise aynı verinin yapısının bilinmez kabul edildiği ve bir veri modeli kurmadan doğrudan uygun algoritma ile sonuç elde etmenin mümkün olduğu düşüncesini savunur ve bilgisayar bilimlerinin bir alt dalı olan makine öğrenmesi içinde ele alınır [4]. Yapay sinir ağları ve karar ağaçları bu yöntemlere örnek olarak verilebilir. İki yaklaşımın da başarılı olduğu alanlar vardır ve bu alanlar iki yaklaşımın da halen kullanılmasının ana nedenidir. İlk yaklaşım ile ilgili adı geçen çalışmada 205.sayfada “.. how the commitment to data modeling has prevented statisticians from entering new scientific and commercial fields where the data being gathered is not suitable for analysis by data models.” denerek istatistikçilerin sadece modellemeye uygun veriler üzerinde yoğunlaşarak yapısal olmayan verilerin bir anlamda ihmal edildiğine dikkat çekilmektedir.

 

Son olarak, bilgiye ulaşmak dışında bunun kullanılabilirliği de günümüzün en önemli konularından biridir. Ayrı bir uzmanlık alanı olarak da görenler vardır. Özellikle bellekte analitik çözümleme (ing. in-memory analytics ) ve bunun görsel bir şekilde karar vericilere sunulması büyük veri ile birlikte üretilen çözümün bir parçası haline gelmiştir. Büyük analitik çözüm firmaları geçtiğimiz yıl ve bu yıl yaptıkları çalışmalarda tamamen bu konuya odaklanmış görünmekteler.

 

Özetle;

Veri bilimci, bilimsel yöntemler kullanarak büyük veriyi

  • analiz ederek gösterimi için en uygun yapıya karar verir ve tasniflemesini yapar,
  • dağıtık bir şekilde otomatik olarak işleyecek mimari konusunda uzmanlığını ortaya koyar,
  • kullanımına ilişkin temel kural ve çıkarım mekanizmasını ortaya koyar,
  • faydalanma yöntemlerini de ortaya çıkarır ve sunar.

 

 

Kaynaklar;

[1] http://devveri.com/big-data/data-scientist-veri-bilimci-kimdir

[2] http://www.forbes.com/sites/gilpress/2013/05/28/a-very-short-history-of-data-science

[3] From Data Mining to Knowledge Discovery in Databases, Usama Fayyad, Gregory Piatetsky-Shapiro, and Padhraic Smyth, AI Magazine Volume 17 Number 3 1996

[4] 2001 Leo Breiman, “Statistical Modeling: The Two Cultures”, Statistical Science, , Vol. 16, No. 3, 199–231, 2001

[5] http://en.wikipedia.org/wiki/Science

[6] http://hadoop.apache.org/

[7] What is Data Science ? Fundamental Concepts and a Heuristic Example, Proceedings of the Fifth Conference of the International Federation of Classification Societies (IFCS-96), Kobe, Japan, March 27–30, 1996

[8] http://breakinggov.com/2012/04/23/big-data-systems-need-data-science-and-knowledge-bases/

[9] http://www.cangungen.com/2011/03/10/ontoloji-varlik-felsefesi/

[10] http://vitalflux.com/key-to-big-data-data-science-data-framework/

[11] http://ontolog.cim3.net/OntologySummit/2014

[12] Yazılım Mühendisliğinde Ontolojilerin Kullanımı, Görkem Giray, Murat Osman Ünalır

[13] http://en.wikipedia.org/wiki/Knowledge_engineering

[14] International Conference on Knowledge Engineering and Ontology Development, 21-24 October 2014

[15] http://www.ted.com/talks/tim_berners_lee_on_the_next_web

[16] http://research.google.com/archive/gfs.html

[17] http://research.google.com/archive/mapreduce.html

[18] http://research.google.com/archive/bigtable.html

[19] http://www.datasciencecentral.com/profiles/blogs/data-scientists-vs-data-engineers

[20] http://www.datasciencecentral.com/profiles/blogs/data-scientist-versus-data-engineer

[21] http://www.visual-analytics.eu/faq/

 

 

Hive ile HBase Entegrasyonu

hbase_logoHadoop ekosistemindeki projelerin en büyük avantajlardan birisi de birbirleriyle uyumlu olarak çalışabilmeleri. Bu yazımızda HBase üzerindeki verileri Hive üzerinden sorgulamayı inceleyeceğiz.

HBase ile Hive’ı entegre edebilmek için ilk adım olarak gerekli kütüphanelerin classpath üzerinden erişilebilir olmasını sağlamak. Aşağıdaki jar dosyalarını (tabii ki uygun versiyon numaraları ile) Hive’ın ya da direkt olarak Hadoop’un lib dizini içerisine bulunması gerekiyor:

hive-hbase-handler-0.9.0.jar
hbase-0.92.0.jar
zookeeper-3.3.4.jar
guava-r09.jar

Örnek olması açısından HBase tarafında bir tablo yaratmak amacıyla Sqoop kullanabiliriz. Veritabanımızda bulunan mevcut bir tabloyu HBase’e Sqoop üzerinden aktarıyoruz:

sqoop import --driver com.mysql.jdbc.Driver --connect "jdbc:mysql://myhost/test" --username myuser --password mypass --table mytable --hbase-table mytable --column-family c --hbase-create-table

Sqoop parametrelerinde –hbase-create-table ile verileri HBase’e aktaracağımızı, –hbase-table ile de HBase tarafındaki tablo ismini belirtiyoruz. Komutun çalışması sona erdikten sonra HBase shell üzerinden verileri kontrol edebiliriz:

$ hbase shell
HBase Shell; enter 'help' for list of supported commands.
Type "exit" to leave the HBase Shell
Version 0.94.6-cdh4.5.0, rUnknown, Wed Nov 20 15:46:19 PST 2013

hbase(main):001:0>scan 'mytest', {LIMIT=>1}
ROW                                           COLUMN+CELL
 1                                            column=c:field1, timestamp=1392992550443, value=val1
 1                                            column=c:field2, timestamp=1392992550443, value=test1
1 row(s) in 0.1050 seconds

Daha sonrasında Hive tarafında HBase’deki tablomuzu external table olarak tanımlıyoruz:

CREATE EXTERNAL TABLE mytest(rowkey STRING, field1 STRING, field2 STRING)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ('hbase.columns.mapping' = ':key,c:field1,c:field2')
TBLPROPERTIES ('hbase.table.name' = 'mytest');

Tanımı yaparken HBaseStorageHandler sınıfını kullanıyoruz. Tabloyu yaratırken verdiğimiz kolon tanımları ile SerDe tanımlarının birebir örtüşmesi gerekiyor. Yani :key ile HBase tarafındaki rowkey değerini rowkey alanı ile, c:field1 alanını da field1 alanı ile örtüştürüyoruz. hbase.table.name parametresi ile de HBase tarafındaki tablo ismini belirtiyoruz.

Tanımı yaptıktan sonra artık Hive tarafında sorgulama yapabilir hale geliyoruz:

hive> SELECT * FROM mytest limit 3;
OK
1	val1	test1
2	val2	test2
3	val3	test3

Her ne kadar HBase üzerindeki verileri Hive ile sorgulamak kulağa çok hoş gelse de bu entegrasyon halen geliştirme aşamasında. Yaptığım denemelerde çok verimli sonuç aldığımı malesef söyleyemeyeceğim. Sorgular ya çok uzun sürüyor ya da bir noktada başarısız oluyor. Ancak geliştirmeler tamamlandığında oldukça kullanışlı olacağını tahmin ediyorum.

Daha detaylı bilgi için ilgili sayfayı ziyaret edebilirsiniz.

Hive JDBC Bağlantısı

hive_logo_mediumHive üzerindeki verilere erişmenin birkaç yöntemi var. Bu yöntemlerden birisi de JDBC sürücüsünü kullanmak. Hive JDBC sürücüsü ile verileri programatik olarak sorgulamak ve bir SQL arayüzü (örneğin SQuirreL) kullanmak mümkün hale geliyor.

Hive tarafından yönetilen verilerin dışarı açılmasını HiveServer2 uygulaması sağlıyor. Önceden HiveServer (ya da ThriftServer) olarak adlandırılan bu uygulama aynı anda sadece tek bir bağlantıya izin verdiği ve herhangi bir güvenlik desteği bulunmadığı için geliştirilerek HiveServer2 adını almış. JDBC sürücüsü de bu uygulama üzeriden thrift kullanarak verilere erişiyor.

JDBC Kullanarak Erişim

JDBC kullanarak erişim oldukça kolay, maven ayarları şöyle:

<dependency>
  <groupId>org.apache.hive</groupId>
  <artifactId>hive-jdbc</artifactId>
  <version>0.10.0-cdh4.5.0</version>
</dependency>

Örnek kod ise şu şekilde:

package com.devveri.hive.jdbc.test;

import org.junit.Test;
import java.sql.*;

public class HiveJdbcTest {

    private static final String JDBC_DRIVER = "org.apache.hive.jdbc.HiveDriver";
    private static final String JDBC_URL = "jdbc:hive2://myhost:10000/test";
    private static final String JDBC_USER = "";
    private static final String JDBC_PASS = "";

    @Test
    public void test() throws ClassNotFoundException, SQLException {
        Class.forName(JDBC_DRIVER);

        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            con = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASS);
            stmt = con.createStatement();
            rs = stmt.executeQuery("select * from test.nyse limit 10");
            while (rs.next()) {
                System.out.println(String.format("%s\t%s\t%f",
                        rs.getString("exchange"),
                        rs.getString("date"),
                        rs.getDouble("stock_price_open")));
            }
        } finally {
            if (rs != null) {
                rs.close();
            }
            if (stmt != null) {
                stmt.close();
            }
            if (con != null) {
                con.close();
            }
        }
    }

}

SQuirreL Üzerinden Erişim

SQuirreL, Java ile geliştirilmiş bir SQL arayüzü. Bağlanmak istediğiniz veritabanının JDBC sürücüsünü tanıtarak arayüz üzerinden sunucuya erişmenizi sağlıyor. Hive JDBC driver kullanarak erişim yapmak için aşağıdaki jar dosyalarına ihtiyaç var:

Screen Shot 2014-02-23 at 01.52.20

 Ardınan bağlantı ayarları yapılarak erişimi test edebilirsiniz:

Screen Shot 2014-02-21 at 15.44.28

Pig üzerinden Hadoop ile MongoDB Entegrasyonu

mongodb-hadoop-connectorAçık kaynaklı büyük veri teknolojilerinin en beğendiğim özelliği, birden fazla projeyi birlikte kullanabilmek. Bu sayede, farklı projelerin güçlü olduğu taraflardan faydalanarak ortaya daha büyük bir değer çıkartmak mümkün oluyor. Bu yazıda MongoDB ile Hadoop‘u Pig üzerinden entegre ederek nasıl kullanabileceğimize bir örnek vermeye çalışacağız.

Hazırlık

MongoDB’nin geliştirdiği connector sayesinde, MongoDB’deki verileri Hadoop üzerine taşımak ya da Hadoop MapReduce işleri ile MongoDB’deki verileri analiz etmek mümkün oluyor. Bunun için öncelikle connector projesini indirip build etmemiz gerekiyor:

$ git clone https://github.com/mongodb/mongo-hadoop

Yalnız build etmeden önce hangi Hadoop versiyonu ile entegre edecekseniz bunu build.sbt dosyasında belirtmeniz gerekiyor. Ben örneği Hortonworks Sandbox içerisinde çalıştırdığım için build.sbt dosyası içerisindeki ThisBuild satırını 2.2 olacak şekilde, aşağıdaki gibi düzenledim:

name := "mongo-hadoop"
organization := "org.mongodb"
hadoopRelease in ThisBuild := "2.2"

Hangi Hadoop versiyonu için ne yazmanız gerektiğini GitHub sayfasında bulabilirsiniz. Daha sonrasında projeyi build ediyoruz:

$ ./sbt package

Build işlemi başarılı bir şekilde tamamlandığında aşağıdaki jar dosyalarının oluşması gerekiyor:

$ find . | grep jar
./core/target/mongo-hadoop-core-1.2.0.jar
./core/target/mongo-hadoop-core_2.2.0-1.2.0.jar
./flume/target/mongo-flume-1.2.0.jar
./hive/target/mongo-hadoop-hive-1.2.0.jar
./hive/target/mongo-hadoop-hive_2.2.0-1.2.0.jar
./pig/target/mongo-hadoop-pig-1.2.0.jar
./pig/target/mongo-hadoop-pig_2.2.0-1.2.0.jar
./target/mongo-hadoop-1.2.0.jar
./target/mongo-hadoop_2.2.0-1.2.0.jar
./testing/mus_tests/helpers.jar

Son olarak MongoDB Java Driver kütüphanesinin ve build ettiğimiz jar dosyalarından gerekli olanları Hadoop’un lib dizini içerisine kopyalamamız gerekiyor. Benim kurulumumda bu klasör /usr/lib/hadoop/lib şeklindeydi. Aşağıdaki dosyaların bu dizinde olması gerekiyor:

mongo-hadoop_2.2.0-1.2.0.jar 
mongo-hadoop-core_2.2.0-1.2.0.jar 
mongo-hadoop-pig_2.2.0-1.2.0.jar 
mongo-java-driver-2.11.1.jar

MongoDB tarafında örnek olarak oluşturduğum users tablosu içerisindeki veriyi mongo istemcisi üzerinden kontrol ediyorum:

$ mongo
MongoDB shell version: 2.4.9
connecting to: test
> use test
switched to db test
> show collections
system.indexes
user
> db.user.find()
{ "_id" : ObjectId("52e52e3349008a3f31dea285"), "id" : 1, "name" : "test1", "email" : "test1@test.com" }
{ "_id" : ObjectId("52e52e5b49008a3f31dea286"), "id" : 2, "name" : "test2", "email" : "test2@test.com" }

MongoDB’den Veriyi Okuma

Amacım kullanıcı verisini Pig kullanarak sorgulamak. Bunu yapmamız için gereki olan Pig kodu şu şekilde:

/* Kullanacagimiz kutuphaneleri ayni zamanda Pig tarafindan da erisilebilir bir yere yuklenmeli */
register /tmp/udfs/mongo-hadoop-core_2.2.0-1.2.0.jar
register /tmp/udfs/mongo-hadoop-pig_2.2.0-1.2.0.jar
register /tmp/udfs/mongo-java-driver-2.11.1.jar
set default_parallel 1

/* MongoLoader sinifi icin kisaltma */
define MongoLoader com.mongodb.hadoop.pig.MongoLoader;

/* Veriyi yukle */
a = load 'mongodb://localhost:27017/test.user' using MongoLoader() as (user: map[]);
b = foreach a generate user#'id', user#'name', user#'email';
dump b;

Bu kodu açıklamaya çalışırsak; Öncelikle register komutuyla gerekli kütüphaneleri Pig’e tanıtıyoruz. Tabii gerekli olan bu kütüphaneleri HDFS üzerinde Pig tarafından erişilebilir bir yere upload edilmiş olması gerekiyor. Ben /tmp/udfs klasörüne yükledim.

Sonrası oldukça kolay; MongoLoader sınıfı ile belirttiğimiz adresteki MongoDB’ye bağlanıp, test şemasındaki user tablosunu yüklemesini sağlıyoruz. Yüklenen bu veri Pig tarafında Map tipine dönüştürülüyor. Bu veri içerisinden istediğimiz kolonları alıyoruz ve dump komutu ile ekrana basıyoruz.

Bu yöntem ile JS kullanarak MapReduce yazmak yerine Pig’in avantajlarını kullanabiliriz.

Hadoop’tan Veriyi MongoDB’ye Aktarma

Tam tersi şekilde, Hadoop üzerindeki veriyi de MongoDB’ye aktarabiliriz. Örneğin Hadoop üzerinde içerisinde ürün numarası, kullanıcı numarası ve zaman bilgisi içeren bir dosyamız olduğunu düşünelim:

1	111	1386704549204
2	222	1386704549325
3	333	1386704550446
4	444	1386704551837
5	444	1386704554568
6	666	1386704554613

Bu veriyi MongoDB’ye aktarmak için şu Pig kodunu kullanabiliriz:

register /tmp/udfs/mongo-hadoop-core_2.2.0-1.2.0.jar
register /tmp/udfs/mongo-hadoop-pig_2.2.0-1.2.0.jar
register /tmp/udfs/mongo-java-driver-2.11.1.jar
set default_parallel 1

/* Tekrar eden kayit olmamasi icin Speculative Execution ozelligini devre disi birakiyoruz */
set mapred.map.tasks.speculative.execution false
set mapred.reduce.tasks.speculative.execution false

/* MongoInsertStorage sinifi icin kisaltma */
define MongoInsertStorage com.mongodb.hadoop.pig.MongoInsertStorage;

/* dosyayi yukle */
a = load '/user/hue/useritems' using PigStorage() as (userId:int, memberId:int, time:long);
/* memberId'ye gore grupla */
b = group a by memberId;
c = foreach b generate group as memberId, $1 as items;
/* Mongo'ya kaydet */
store c into 'mongodb://localhost:27017/test.useritem' using MongoInsertStorage('items:bag', 'memberId');

MongoDB’ye verileri kaydederken herhangi bir problem yaşamamak için Hadoop’un Speculative Execution özelliğini devre dışı bırakmak gerekiyor. Burada useritems dosyasını yükleyip, verileri memberId alanına göre grupluyoruz. Sonrasında bu veriyi grupladığımız haliyle MongoDB’ye MongoInsertStorage sınıfını kullanarak test şeması içindeki useritem tablosuna kaydediyoruz.

Kodun çalışması sonucunda MongoDB’de aşağıdaki veriler girilmiş bulunuyor; 444 numaralı memberId kaydının birden fazla item bilgisi olduğunu görebilirsiniz:

> db.useritem.find()
{ "_id" : ObjectId("52e55730e4b0c7d85da7ecd7"), "memberId" : 111, "items" : [ 	{ 	"userId" : 1, 	"memberId" : 111, 	"time" : NumberLong("1386704549204") } ] }
{ "_id" : ObjectId("52e55730e4b0c7d85da7ecd8"), "memberId" : 222, "items" : [ 	{ 	"userId" : 2, 	"memberId" : 222, 	"time" : NumberLong("1386704549325") } ] }
{ "_id" : ObjectId("52e55730e4b0c7d85da7ecd9"), "memberId" : 333, "items" : [ 	{ 	"userId" : 3, 	"memberId" : 333, 	"time" : NumberLong("1386704550446") } ] }
{ "_id" : ObjectId("52e55730e4b0c7d85da7ecda"), "memberId" : 444, "items" : [ 	{ 	"userId" : 5, 	"memberId" : 444, 	"time" : NumberLong("1386704554568") }, 	{"userId" : 4, 	"memberId" : 444, 	"time" : NumberLong("1386704551837") } ] }
{ "_id" : ObjectId("52e55730e4b0c7d85da7ecdb"), "memberId" : 666, "items" : [ 	{ 	"userId" : 6, 	"memberId" : 666, 	"time" : NumberLong("1386704554613") } ] }

Daha fazla bilgi için aşağıdaki sayfaları inceleyebilirsiniz:

https://github.com/mongodb/mongo-hadoop

http://docs.mongodb.org/ecosystem/tutorial/getting-started-with-hadoop/

http://hortonworks.com/blog/pig-as-connector-part-one-pig-mongodb-and-node-js/

Apache Flume ile Veri Toplama

flume-logoDevveri, big data, büyük ölçekli veri analizi sözkonusu olduğunda artık Hadoop hızlıca konu başlığı olur durumda. Nerdeyse konu sadece Hadoop ile ilgili, “devveri” başlığı ise sadece nezaketen söylenen bir genelleme gibi. Hadoop dendiğinde ise konu doğrudan MapReduce ve bazen HDFS oluyor. Durum, tarihsel oluşum sebebiyle normal olmakla beraber devveri konusunun sadece MapReduce ve HDFS’ten ibaret olmadığını hatırlamak gerekiyor. Bu yazıda doğrudan Hadoop ekosistemine dahil olmayan ancak konuyla yakından ilgili başka bir sistemden bahsetmeye çalışacağım: Flume.

Bir çok yerde okuyabileceğiniz üzere, HDFS büyük verilerin kaydedildiği yer, MapReduce ise bunların işlendiği programlama yapısı. Genellemeleri bir süreliğine kenara bırakıp pratik örneklerden ilerlersek, web sunucularından alınan accesslog’lar HDFS’te kaydediliyor, MapReduce kullanarak da sitenin belli sayfalarının hangi saatlerde daha aktif olduğu hesaplanıyor. Bu cümledeki bir çok eksik noktadan biri, accesslog’ların HDFS’e nasıl kaydedileceği. İlk akla gelen çözüm HDFS’i normal bir dosya sistemi gibi web sunucuya mount edip logların oraya yazılmasını sağlamak olabilse de endüstride bu tip bir kullanım görmek çok olası değil. Flume’un da bir üyesi olduğu “veri aktarma sistemleri” diyebileceğimiz araçlar ise bu boşluğu doldurmaya çalışıyor. Alternatifleri arasında scribe ve chukwa gibi ürünler var, ancak bunlar hakkında çok bir bilgi sahibi olmadığım için karşılaştırma yapamayacağım.

Flume çalışma yapısı

Flume, agent adında bir java uygulaması şeklinde çalışıyor ve birbirine bağlı 3 yapıya sahip:

  1. Source (kaynak): Logların flume’a geldiği yer
  2. Channel (kanal): Logların flume içinde bulunacağı yer
  3. Sink (hedef): Logların yazılacağı yer

olarak özetlenebilir.

En temel haliyle 1 source, 1 channel ve 1 sink ile ayarlanan bir agent, logları tek bir noktadan alıp tek bir yere yazacak şekilde çalışıyor. Birden fazla channel/sink ve/veya birden fazla agent çalıştırarak karmaşık modeller kurmak mümkün. Bunlara yazının sonunda kısaca değineceğim.

Az önceki örnek ile bu yapıları bağdaştıracak olursak, web sunucunun accesslog’ları (misal syslog ile) göndereceği yer agent konfigürasyonunda source kısmında ayarlanıyor. HDFS’e yazılacak yer ise sink kısmında ayarlanıyor. Flume konfigürasyonu şuna benziyor:

# 'weblog' agent adi, kullanilacak yapilar tanimlaniyor
weblog.sources = source1
weblog.channels = channel1
weblog.sinks = hdfs1

# 'source1' adli source ayarlari
weblog.sources.source1.type = syslogudp
weblog.sources.source1.port = 514
weblog.sources.source1.channels = channel1

# 'channel1' adli channel ayarlari
weblog.channels.channel1.type = memory

# 'hdfs1' adli sink ayarlari
weblog.sinks.hdfs1.type = hdfs
weblog.sinks.hdfs1.channel = channel1
weblog.sinks.hdfs1.hdfs.path = hdfs:///flume/weblog

Bu konfigürasyonu çalıştıran bir makina kabaca UDP 514 portunu dinlemeye başlayacak, ve oraya gelen syslog olaylarının verisini HDFS’teki `/flume/weblog` dizinine yazacak. Tarihlere göre bölme, dosya formatları, dosyaların hangi aralıklarda roll edileceği gibi bir çok ek ayar dökümantasyonda detaylıca anlatılmış.

Kritik detaylar

Daha önce de bahsettiğim gibi flume, devveri analizi için gerekli ama önemsiz bir detayı gibi göründüğünden bu yukarıdaki gibi basit bir konfigürasyonla bile arada bir programı restart ederek hayata devam etmek gayet mümkün. Ancak yapılan işler kritikleşmeye başladığında bu restart’ların maliyeti ciddi boyutlara ulaşabilir. Bu durumda birkaç küçük ayar durumu toparlayabilir.

Flume ile benim en çok karşılaştığım hata:

org.apache.flume.ChannelException: Space for commit to queue couldn't be acquired Sinks are likely not keeping up with sources, or the buffer size is too tight

şeklinde bir mesaj. Dikkatlice öğrenildiğinde gayet açıklayıcı olan ama bir çok zaman olduğu gibi ezbere yapılan kurulumlarda çok da anlam ifade bu mesaj, özetle “HDFS’te bir problem oldu ben yazamadım, şimdi de yetiştiremiyorum.” demek. Flume’daki channel yapısı, bu tip hatalar için buffer gibi çalışır, ancak normal değeri 100 olan channel kapasitesi bir çok kurulum için yeterli değildir. Çok kaba bir hesapla web sunucu saniyede 1000 istek karşılıyor ve log üretiyorsa, 100 olay kapasiteli bir channel en fazla 100 ms’lik hataları tolere edebilir. Problem durumu bir kaç saniye sürüyorsa buffer hızlıca dolacak ve yukarıda görülen hata oluşacaktır. Daha kötüsü bu durum geçene kadar olan log’lar hiçbir yere yazılamadığı için kaybolacak ve analizlerde eksikler oluşmasına sebep olacaktır. `weblog.channels.channel1.capacity` gibi bir değeri artırmak bu sorunu azaltacaktır. Bu 100 olan değerin sonuna birkaç sıfır koymak çok da yanlış bir yaklaşım değildir.

Bir diğer durum ise gerçekten yoğun aktiviteden kaynaklı HDFS’in yetişememesi durumu olabilir. Yine yukarıdaki gibi saniyede 1000 event üreten bir sistem için her eventin HDFS’e ayrıca yazılması pek çalışabilecek bir senaryo değildir. Bu yüzden bir çok veri sistemi gibi yazma işlemleri paketler (batch) halinde yapılır. `weblog.sinks.hdfs1.hdfs.batchSize` değeri normal paket boyutunu 100 olarak tanımlamıştır ve kabaca 1000 gibi bir değere çıkarmak yazma hızını ciddi miktarda artıracaktır.

Ekstralar

En sık kullanımı yukarıdaki gibi olsa da Flume bunlarla sınırlı değil. Olayları alabilmek için syslog yanında doğrudan dizinden okuma, netcat, HTTP, avro, thrift gibi farklı yapıları kullanmak mümkün. Channel’lar için ise hafıza yanında, dosya, JDBC gibi kalıcı yerler kullanılabiliyor. Event’leri yazmak içinse HDFS dışında normal dosyalar, başka yerlerdeki avro, thrift alıcıları ya da HBase, Solr, ElasticSearch gibi veritabanları kullanılabilir. Ayrıca birden fazla channel/sink ayarlayarak replication, multiplexing, failover ya da load-balancing senaryoları tasarlanabilir.

Flume olay/log taşıma dışında, bir kısım iş mantığını da halledebilir. Bu yazının yazılmasına da vesile olan yapıların adı interceptor‘ler. Source’lar üzerine tanımlanan küçük kod parçacıkları gelen olayların filtrelenmesi, değiştirilmesi ya da anlamlandırılması gibi işleri yapabiliyor. Hatta birden fazla interceptor zincirleme bağlanarak birinde yapılan iş diğerinde yorumlanabiliyor. Bu konu benim için de gayet yeni olduğundan çok basit bir örnek verebileceğim:

Web sunucularından ya da yük dengeleyiciden alınan olayların hepsi tek bir sistem için anlamlı olmayabilir. Örneğin sitenin web içeriği ile medya içeriği aynı yük-dengeleyiciden geçiyor ancak analizler ayrı ayrı yapılıyorsa misal `/static` şeklinde başlayan medya istekleri başka bir channel’a, oradan da başka bir HDFS dizinine yönlendirilebilir. Böylece web istekleri için yapılacak analizler ciddi miktarda kolaylaşacaktır. Ya da bazı tip istekler tamamen anlamsız olabilir ve filtrelenmek istenebilir. Bu durumda:

weblog.sources.source1.interceptors = i1
weblog.sources.source1.interceptors.i1.type = regex_filter
weblog.sources.source1.interceptors.i1.regex = GET\\s/crossdomain.xml
weblog.sources.source1.interceptors.i1.excludeEvents = true

gibi bir ayar `/crossdomain.xml` şeklinde bilinen flash’ın otomatik gönderdiği istekleri filtreleyecektir. Utanarak kabul ediyorum ki daha yakın zamanda servislerimizden birinde bunun gibi küçük bir ayarla kaydettiğimiz/işlediğimiz veri miktarında ciddi tasarruf sağladık.

Regex işlemlerinin yanısıra UUID, timestamp ve morphline gibi farklı tip interceptor’leri bağlayarak çok daha akıllıca işler yapmak mümkün. Hatta çok tavsiye edemesem de bazı girişimler sadece interceptor’ler kullanılarak real-time analiz yapılabileceğini gösteriyor.

Son olarak tüm bu yapılar kolaylıkla modifiye edilebiliyor ve yeni tip source/channel/sink/interceptor/vs. tanımlanabiliyor. Bu sayede Flume istenilen tüm işlere tüm sistemlere uygun hale getirilebiliyor. Bu konuyu ayrı bir yazıya bırakıyorum.

Data Scientist kimdir?

Data Scientist (Veri Bilimci) kavramını son yıllarda özellikle Facebook ve Linkedin firmalarından ötürü daha sık duymaya başladık. İş ilanlarında bu görev için adayların arandığına daha sık rastlar olduk. Peki ama Data Scientist kimdir, ne iş yapar?

Data Scientist, bağlı bulunduğu kurum için değer yaratmak amacıyla büyük ve çeşitliliğe sahip veriyi uçtan uca analiz eder. Bu veriler bazen ilişkisel veritabanlarında olabileceği gibi, bazen de log dosyaları, sensör verileri gibi değişik kaynaklardan toplanan veriler de olabilir. Data Scientist bu verileri analiz ederek, sonuçlarını yönetim ile paylaşıp aksiyon alınmasını sağlar ve “Veri Odaklı Uygulamalar” geliştirir. Bu uygulamaların birkaç önemli karakteristiği vardır:

  • Bu uygulamalar veriden faydalanarak ortaya çıkar
  • Bu uygulamaların kullanımı sonucunda yeni veriler ortaya çıkar
  • Yeni çıkan bu veriler uygulamaların iyileştirilmesi için kullanılır

Veri odaklı uygulamalar, kullanıcıların ilgisini çekebilecek ürünleri önermek, pazar analizi, talep analizi, sahtekarlıkların tespit edilmesi gibi örneklendirilebilir.

Google veri odaklı uygulamaya örnek olarak verilebilir. İlk arama motoru Google değildi, Altavista, Yahoo ve benzeri siteler zaten mevcuttu, ancak PageRank algoritması ile Google öne çıktı ve pazar lideri oldu. Daha sonrasında AdSense, AdWords ve Analytics gibi diğer veri odaklı ürünleriyle başarısını ileriye taşıdı.

Linkedin de alanındaki ilk örnek değildi, ancak tanıyor olabileceğimiz kişileri göstermesi, ilgimizi çekebilecek grupları ya da iş fırsatlarını bize sunuyor olması gibi veri odaklı uygulamaları ile benzerlerinin arasından sıyrıldı ve öne çıktı.

Amazon yayına çıktığı ilk günden bu yana öneri sistemine sahip. Bunun dışında hangi ürüne bakan kullanıcıların daha sonrasında hangi ürünü aldığını göstermesi, bu ürünü alan kullanıcıların başka hangi ürünleri aldıkları gibi çok çeşitli veri odaklı uygulamayı da içinde barındırıyor.

eBay açık arttırmalı ürünlerin başlıklarının otomatik olarak doğrulanması, kaybedilen bir açık arttırma ardından kullanıcıya benzer ürünlerin önerilmesi, resim ile arama gibi farklı uygulamalara sahip.

Büyük ve çeşitliliğe sahip veriyi analiz etmek ve veri odaklı uygulamalar geliştirebilmek için birden fazla disiplinde bilgi ve tecrübe gereklidir. Bu nedenle Data Scientist, Yazılım Mühendisliği (belki biraz da Sistem Mühendisliği), İstatistik ve İş Alanı Deneyimi (Domain Experience) alanlarını bir araya getiren çoklu bir disiplindir. Data Scientist olmak isteyenlerin aşağıdaki yetenek ve tecrübelere sahip olması gerekir:

  • Analitik bir zeka ve geniş bir matematik bilgisi
  • Özellikle ölçeklendirilebilirlik başta olmak üzere Yazılım Mühendisliği bilgisi
  • İlişkisel veritabanı sistemlerinde tecrübe
  • Hem teknik (yazılım, sistem, veriambarı, vs) hem de teknik olmayan (pazarlama, satış, yönetim, vs) birimleriyle efektif bir şekilde iletişim kurabilme yeteneği
  • İçinde bulunduğu sektör ile ilgili (finans, bankacılık, internet, vs) yeterli tecrübe

Yazılımcı açısından bakıldığında, Data Scientist genel amaçlı yazılım üretmekten ziyade soruları cevaplamak, sorunları çözmek amacıyla yazılımdan faydalanır. Bu sebeple daha ziyade script dilleri (özellikle Python yaygın olarak kullanılmakta) ve otomasyon üzerine odaklanırlar. Bunların dışında Yapay Öğrenme (Machine Learning) konularında bilgi ve tecrübe gereklidir.

Veri Analisti, İş Zekası Uzmanı veya İstatistikçi daha ziyade mevcut araçları kullanmaya odaklanmışken Data Scientist ise çok farklı kaynaklardan, daha fazla veri toplar ve bu veriyi işlemek için yeni araçlar geliştirir. Çoğunlukla mevcut araçların işleyemediği büyük miktarda, yapılandırılmamış ve kirli veriyle çalışır.

İş Analisti açısından ise, her ikisi de iş odağına sahipken Data Scientist kimseden yardım almadan sorularının cevaplarını bulabilecek teknik bilgiye sahiptir.

Son olarak, Data Scientist yaptığı analizlerin veya geliştirdiği veri odaklı uygulamanın sonuçlarınının görselleştirilmesinden de sorumludur. Bu sebeple görselleştirme konusundaki araçlar hakkında da bilgi sahibi olmalıdır.

DataScienceDisciplines

Cloudera Impala: Hadoop üzerinde Gerçek Zamanlı Sorgulama

Hadoop üzerindeki verileri SQL arayüzü ile analiz etmek amacıyla Hive projesi yaygın bir şekilde kullanılıyor. Hive ile yazılan SQL sorguları Hadoop mimarisinde dağıtık bir şekilde çalıştırılmak amacıyla MapReduce kodlarına çevriliyor. Bu sayede klasik RDBMS’lerin çoğunun cevap dahi veremeyeceği sorgular Hive ile kısa bir zamanda tamamlanabiliyor. Örneğin sağlam bir donanıma da sahip olsa tek bir MySQL sunucusu üzerinde 5 dk süren bir sorgu, Hive ile 40 sn gibi bir sürede tamamlanabiliyor. Ancak Hive, daha ziyade veri ambarı işleri ve büyük miktardaki veri üzerinde kullanılma amacıyla tasarlandığı için, anlık olarak sorgulara cevap verme gibi bir özelliği bulunmuyor.

Ancak günümüzde anlık olarak verilerin işlenmesi ihtiyacı giderek artıyor, dolayısı ile Hadoop’un da bu konuda bir cevaba ihtiyacı var. Bu ihtiyacı ilk olarak görerek bu konuda çalışmaları yapan her zaman olduğu gibi tabiiki Google. 2010 yılında yayınladıkları Dremel makalesinde kendi altyapılarında bu ihtiyaçları nasıl karşıladıklarını anlatıyorlar. Bu makeleden faydalanan birçok ticari ve açık kaynaklı proje bulunuyor.

Cloudera tarafından geliştirilen açık kaynaklı Impala, bu projelerden bir tanesi. HDFS veya HBase üzerindeki veriler, SELECT, JOIN ve aggregation fonksiyonları ile gerçek zamanlı sorgulanabiliyor. Impala’nın en önemli avantajlarından birisi de Hive ile aynı SQL arayüzünü, sürücüleri ve ortak metadata’yı kullanabilmesi. Impala da Hive gibi text, sequence, avro, rcfile vb. birçok farklı dosya formatını destekliyor.

Impala çalışma mantığını “Dağıtık SQL Sorgulama Motoru” olarak tanımlayabiliriz. Hive’dan farklı olarak Impala sorguları MapReduce işlerine çevrilmez. Bu sayede MapReduce işlerinin başlatılması, koordine edilmesi, gerektiğinde tekrar çalıştırılması gibi zaman alan işlevlerden arınır. Bunun yerine dağıtık sorgular aracılığı ile, verilere direkt erişir. Sorgulama motoru verilen sorguyu analiz ederek dağıtık olarak nasıl çalıştırılacağını hesaplar, sonrasında her düğüm üzerinde gerekli sorguları çalıştırır. Sorguların sonrasında her düğümden alınan sonuçlar HDFS üzerinde değil direkt olarak hafıza üzerinde birleştirilir. Birleştirilme işlemi hafıza üzerinde yapıldığından dolayı daha hızlı çalışır fakat bunun için sistemde yeterli hafıza olması gerekir. Bu işlemler sırasında Parquet adı verilen daha işlevsel ve performanslı bir format kullanılıyor.

impala

Performans açısından Impala ile Hive karşılaştırıldığında;

  • Impala sistem kaynaklarını Hive’dan daha efektif bir şekilde kullanır. Bu sayede bir performans kazancı sağlanır.
  • Hive’da birden fazla MapReduce işi ile yapılması gereken ya da Reduce Side Join yöntemi gerektiren sorgularda Impala öne çıkar. Benzer bir performans kazancı join yapılan sorgular için de geçerli.
  • Basit aggregation sorgularında Impala daha fazla cache ve hafıza kullandığı için çok daha hızlı çalışır.

Performans olarak Impala gerçekten şaşırtıcı derecede hızlı. Yazının başında bahsettiğim, Hive’da 40 sn süren bir sorgu Impala ile gerçekten 1 saniyenin altında cevaplanıyor. Hatta o kadar hızlı çalışıyor ki, ilk anda sorgunun gerçekten çalışıp çalışmadığını kontrol etmek zorunda hissediyorsunuz. Her sorgu için bu durum geçerli değil elbette, ancak performansı net bir şekilde gözdolduruyor diyebilirim, en azından denediğim kadarıyla.

Impala işlev olarak Hive’a benzese de aslında Hive’ın yerini almayı amaçlamıyor. Hive çok daha uzun sürecek, çok büyük miktarda veri işlemek vs gibi durumlarda kullanılmaya devam edilirken, Impala gerçek zamanlı analitik sorgularında kullanılmaya müsait.

Öteyandan Impala’dan da gerçek bir RDBMS’den beklenen sorgu kabiliyetlerinin tamamını beklemek Hadoop mimarisi ve felsefesinden dolayı doğru değil. Ayrıca Impala şu anda beta olduğu için başka bazı eksiklikleri de bulunuyor. Bunlardan birisi kullanıcı tanımlı fonksiyonları (UDF) desteklememesi ve özellikle text formatındaki verileri işlerken yaşanabilen problemler.

Impala bu konudaki ihtiyacı karşılamaya çalışan tek proje değil. Hortonworks tarafından geliştirilen Stinger projesi ve Facebook tarafından geliştirilen Presto projeleri de aynı amaca hizmet ediyor.

Daha fazla bilgi için Cloudera sitesini ziyaret edebilirsiniz.

Hadoop 2.0 – YARN

Apache Hadoop 2.0 sürümünde alt proje olarak yayınlanan YARN (Yet Another Resource Negotiator) kaynak yönetimi ile veri işleme bileşenlerini ayırıp, mimarideki eksikleri ve yeni ihtiyaçları da gözeterek, Hadoop’un gücünü bir sonraki adıma taşımayı hedefliyor.YARN, bu yeni mimari ile HDFS üzerinde çalışacak MapReduce, HBase, Giraph, Storm gibi uygulamaların temelini oluşturacak. Bu sayede MapReduce’e bağımlı kalmadan diğer yeteneklere de doğal yoldan kullanabilecek. Bu aynı zamanda Hadoop’a interaktif, gerçek zamanlıya yakın çalışma yetenekleri kazandıracak.

YARN ile MapReduce v2 yeteneği gelse de halen MapReduce v1 ile geliştirilmiş uygulamalar geriye uyumlu bir şekilde çalışabilecek.

YARN’ın kaynak yönetimi sayesinde aynı anda birçok uygulama kaynakları önceliklere göre düzgün bir şekilde paylaşarak çalışabilecek. Bu sayede çok daha önemli bir uygulama varsa daha fazla kaynak kullanabilecek, önemsiz işler daha az kaynak kullanacak. Yine bu sayede daha önceki sınır olan 4000′den fazla düğümden oluşan kümeler kurulabilecek, kümelerin yönetimi kolaylaşacak. Ayrıca YARN kaynakları çok daha efektif bir şekilde kullanacak şekilde geliştirildi.

 

YARN

 

İlk mimaride yer alan JobTracker ve TaskTracker süreçleri YARN ile değişiyor. Yeni mimaride global bir ResourceManager bulunuyor. Bu süreç küme üzerindeki tüm kaynakların paylaşımından sorumlu. Bunun dışında her düğüm üzerinde çalışan bir NodeManager süreci bulunuyor. Bu süreç de her düğüm üzerinde çalışacak uygulamaların  ayağa kalkmasından, kaynak yönetiminden, takip edilmesinden ve durumların ResourceManager’a iletilmesinden sorumlu. Yani eskiden JobTracker’ın tek başına yapmaya çalıştığı görev birden çok sürece bölünerek ölçeklendirilmiş.

Bir uygulama başlatıldığı zaman da o uygulamaya ait bir ApplicationMaster süreci başlıyor.  Bu süreç ResourceManager üzerinden kaynakları alıp NodeManager üzerinden işin parçalarını yapacak Container süreçlerini çalıştırıyor ve yönetiyor.

YARN hakkında daha fazla bilgi almak için Hortonworks’ün sitesini ziyaret edebilirsiniz.

 

ElasticSearch ve Native Script Kullanımı

elasticsearchElasticSearch gün geçtikçe popülerliğini arttırıyor. Özellikle Apache Solr projesine çok ciddi bir rakip olarak ortaya çıktı ve barındırdığı özellikler sayesinde Solr projesinin de gelişmesini sağladığını söyleyebiliriz. Solr 4.x sürümü ile beraber gelen Cloud özelliklerini ElasticSearch olmasaydı herhalde daha uzun süre kullanamayabilirdik.

ElasticSearch birçok yönden Solr’dan farklı. Sıfır konfigürasyon ile kullanmaya başlıyabiliyorsunuz. Ayrıca yeni sunucular ekledikçe otomatik olarak küme oluşturuyorlar, bu sayede peformans ve ölçeklenebilirlik kolayca sağlanıyor.

Ancak biraz daha ciddi birşeyler yapmak istediğiniz zaman ElasticSearch’ün sıkıntılarını yaşamaya başlıyorsunuz. Öncelikle arkasındaki community gerçekten Apache ile kıyaslanamayacak kadar küçük. Bunu fazlasıyla yetersiz dökümantasyonu içerisinde debelenirken çok ciddi hissediyorsunuz. Özellikle Java API ve dökümantasyonu çok yetersiz.

Bir başka problemli konu River konusu. Solr’daki DataImportHandler mantığının ElasticSearch karşılığı olan River malesef her seferinde indeksi baştan oluşturacakmış gibi konfigüre edilebiliyor. Sunucu her açıldığında River otomatik çalışarak tüm veriyi(!) indekslemeye çalışıyor. Eğer milyonlarca satırdan oluşan bir tabloyu vs indekslemek isterseniz sizin için pek kullanışlı değil. Belki ince ayarı vardır ancak ben bulamadım. Hem JDBC hem Mongo ile benzer problemler yaşayınca, indeksi kendi yazdığım kod ile oluşturup/güncellemeye karar vermiştim.

Bunun gibi sebeplerle ve tabiki şahsi fikrim, Solr kesinlikle açık ara çok daha kurumsal bir proje niteliğinde. Karmaşık konfigürasyonları Solr ile yapmak hem çok rahat hem de çok fazla özellik barındırıyor. Ancak ElasticSearch gelişmeye çok açık ve farklı kullanım alanları olabilecek bir araç. Özellikle log uygulamalarında NoSQL veritabanı gibi kullanıldığında gerçekten faydalı olabiliyor.

Eğer ElasticSearch kullanıyorsanız ve dökümanlarınızı belirli bir mantığa göre kendiniz sıralamak isterseniz o zaman ElasticSearch size scripting desteği sunuyor. Tabiki JavaScript burada varsayılan dil. Yani dökümanları sizin yazdığınız bir JS ile elde edilecek skora göre dizebiliyorsunuz.

Bazı durumlarda ise yapmak istediğiniz işlemi JS ile yazamıyor olabilirsiniz. Bu durumda Native dil desteği sayesinde Java kodu yazarak istediğiniz şekilde sıralama yaptırabilirsiniz. (Bu özelliğe Native Script denmesi bana soracak olursanız biraz saçma olmuş ancak gelin beraber nasıl yapıldığını inceleyelim)

NativeScript özelliğini kullanabilmek için, NativeScriptFactory sınıfından bir adet factory, bir adet de AbstractDoubleSearchScript benzeri bir sınıftan türeyen script sınıfını yazmamız gerekiyor. Burada farklı tipte sonuç dönmek için farklı sınıflar mevcut, ama bizim hesaplayacağımız skor double cinsinden olacağı için bunu tercih ettim. ElasticSearch üzerinde arama yaparken bu script’i kullanmasını ilettiğimizde, her döküman için tek tek bu script çalıştırılacak ve dökümanlar oluşan bu skora göre sıralanacak. Burada dikkat edilmesi gereken şey, her döküman için çalıştırılacağı için script içerisinde kompleks bir kodun çalışmasının (veritabanına gidip gelmek) pek mümkün olmadığı.

Örnek olması açısından, vereceğimiz bir parametre ile başlayan dökümanların üstte gelmesini sağlamak istediğimizi düşünelim. Bunun için TestScriptFactory sınıfını şu şekilde yazabiliriz:

import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.script.ExecutableScript;
import org.elasticsearch.script.NativeScriptFactory;
import java.util.Map;

public class TestScriptFactory implements NativeScriptFactory {

    @Override 
    public ExecutableScript newScript (@Nullable Map<String,Object> params) {
        return new TestScript(params);
    }

}

Ardından script sınıfına da şöyle bir implementasyon yapabiliriz:

import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.script.AbstractDoubleSearchScript;

import java.util.Map;

public class TestScript extends AbstractDoubleSearchScript {

    public static final String PREFIX = "prefix";
    public static final String NAME = "name";

    private String memberPrefix;

    public TestScript(@Nullable Map<String,Object> params) {
        memberPrefix = params == null ? null : XContentMapValues.nodeStringValue(params.get(PREFIX), null);
    }

    @Override
    public double runAsDouble() {
        String currentMember = getFieldAsString(NAME);
        if (currentMember != null && currentMember.startsWith(memberPrefix)) {
            return 1;
        }
        return 0.1;
    }

    private String getFieldAsString(String fieldName) {
        ScriptDocValues.Strings fieldData = (ScriptDocValues.Strings) doc().get(fieldName);
        return fieldData.getValue();
    }

}

Burada prefix parametresi ile bize gelen değeri alıp daha sonra skorunu hesaplayacağımız dökümanın name field’ı ile karşılaştırarak, prefix mevcutsa yüksek puan (1.0), değil ise düşük puan (0.1) dönüyoruz. Eğer prefix’in bulunmadığı durumlarda sıfır (0) dönseydik sonuç setinde bu dökümanlar yer almayacaktı.

Yazdığımız bu kodu jar olarak paketleyerek ElasticSearch’ün kurulu bulunduğu dizinin altındaki lib klasörüne atıyoruz. Bu sayede ElasticSearch’ün classpath’ine eklemiş oluyoruz. Unutmadan, küme olarak çalıştırıyorsanız tüm düğümlerin lib klasöründe bu jar’ın bulunması gerekir.

Ardından config dizini içerisindeki elasticsearch.yml dosyasına aşağıdaki tanımı yapıyoruz:

script.native:
  testscript.type: com.devveri.search.script.TestScriptFactory

ElasticSearch açıldıktan sonra, script’imizi şu istek ile test edebiliriz:

curl -XGET "http://localhost:9200/test/doc/_search" -d '{
  "query" :{
     "custom_score": {
       "query" : { "match_all": {}},
       "script" : "testscript",
       "params" :{
          "prefix": "member2"
       },
       "lang": "native"
     }
  }
}'

Örnek kodları GitHub üzerindeki elasticsearch-native-script-example projesinde bulabilirsiniz.

Sqoop ile Veritabanı Hadoop Arasında Veri Aktarımı

apache-hadoop-sqoop1

Hadoop platformunun en büyük özelliklerinden birisi de farklı kaynaklardan farklı formatlarda gelen verilerin saklanması ve analiz edilebilmesini sağlaması.

İlişkisel veritabanında saklanan verilerin Hadoop üzerinde efektif biçimde işlenebilmesi için bu verilerin HDFS üzerine aktarılması gerekiyor. Sqoop, ilişkisel veritabanları ile Hadoop arasında veri aktarımı için tasarlanmış bir açık kaynaklı bir araç olarak karşımıza çıkıyor. Zaten ismi de Sql-to-Hadoop kelimelerinden türetilmiş.

Sqoop genel olarak MySQL, PostgreSQL, Oracle, SQL Server ve DB2 gibi popüler veritabanlarının hepsini desteklemekle beraber Hadoop gibi Java ile geliştirilmiş bir proje olduğu için JDBC ile erişilebilen tüm veritabanlarıyla da çalışabiliyor.

Sqoop ile hem import hem export yapılabiliyor. Veritabanından HDFS üzerine, direkt Hive tablosu olarak ya da HBase’e veri aktarmak mümkün. Sqoop’un avantajı ise veri aktarım işlemlerini MapReduce görevleri ile paralel olarak yaparak aktarımı çok daha hızlı tamamlamak. Ayrıca MySQL ve PostgreSQL için JDBC kullanmadan (mysqldump gibi) daha düşük seviyeli ve performanslı veri aktarımı da yapılabiliyor.

Import işlemi sırasında Sqoop basitçe meta verilerden faydalanarak tablonun birincil anahtarını bulup minimum ve maksimum değerlerini alarak eşit olarak Map sayısına uygun olarak bölerek farklı düğümler üzerinde bu verileri paralel olarak aktarıyor. Bu yüzden sonuç klasör içinde birden fazla dosyaya yazılıyor. Aktarım sırasında veritabanına yeni kayıt geliyorsa bunlar aktarılmayabilir, veri tutarlılığına dikkat etmek gerekir.

Export işlemi sırasında ise aksi belirtilmediği sürece verileri binerli gruplar halinde veritabanına INSERT ediyor. Bu işlem de paralel olarak yapıldığı için aktarım sırasında veritabanında yük oluşturabilir. Her bir grubun yazılması kendi başına bir transaction olduğu için burada da veri tutarlılığına dikkat etmek gerekir. Eğer kayıtların tamamı aktarıldıktan sonra aktif olması isteniyorsa ara tablo kullanımını sağlayan –staging-table parametresi kullanılabilir. Bu tablonun yaratılması ve temizlenmesi de otomatik yapılmaz, elle yapmak gerekir.

Şimdi Sqoop ile veritabanından Hive’a verilerin aktarılması, Hive’da yapılan bir sorgu sonucu oluşan verilerin de tekrar veritabanına aktarılmasını örnek olarak inceleyelim. (Hive ile ilgili bilgi için ilgili yazımızı inceleyebilirsiniz)

Örnekleri MySQL üzerinde hazırladım ve internetten bulabileceğimiz örnek verileri kullandım. Verilerimizi internetten indirip veritabanına şu şekilde aktarabiliriz:

$ wget https://launchpad.net/test-db/employees-db-1/1.0.6/+download/employees_db-full-1.0.6.tar.bz2
$ tar -xjf employees_db-full-1.0.6.tar.bz2
$ cd employees_db/
$ mysql -h localhost -u test -P -t < employees.sql

Veriler hazır olduğuna göre şimdi Sqoop’u kuralım. Örnekleri Hadoop’un 1.0.3 sürümünde yaptığım için bu sürüme uygun olan son sürümü indirip kurdum:

$ cd /usr/java/
$ wget http://www.eu.apache.org/dist/sqoop/1.4.3/sqoop-1.4.3.bin__hadoop-1.0.0.tar.gz
$ gzip -dc sqoop-1.4.3.bin__hadoop-1.0.0.tar.gz | tar xf -
$ ln -s /usr/java/sqoop-1.4.3.bin__hadoop-1.0.0 sqoop

Sqoop’un çalışması için Hadoop’un kurulu olduğu dizin ile ilgili tanımlamaları yapmamız gerekiyor:

export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_MAPRED_HOME=$HADOOP_HOME

MySQL JDBC sürücüsünü de indirip Sqoop kurulumunun buluğunduğu yerin altındaki lib klasörüne aktarmamız gerekiyor. Güncel sürücüyü burdan indirebilirsiniz.

Kurulumlar ve verilerimiz hazır olduğunu anlayabilmek için Sqoop ile tablolarımızı listeleyebiliriz:

$ sqoop list-tables --connect jdbc:mysql://localhost:3306/employees --username test -P
Warning: /usr/lib/hbase does not exist! HBase imports will fail.
Please set $HBASE_HOME to the root of your HBase installation.
Enter password:
13/07/07 19:59:31 INFO manager.MySQLManager: Preparing to use a MySQL streaming resultset.
departments
dept_emp
dept_manager
employees
employees_with_titles
employees_with_titles_ex
salaries
titles

Bu örnekte HBase ile ilgili herhangi bir ayar yapmadığımız için bir uyarı alıyoruz. Eğer tablo isimleri listelendiyse ayarlarımız doğru demektir.

Sqoop komut satırından parametrik olarak çalıştırılan bir araç, genel parametreleri şu şekilde:

$ sqoop help
Warning: /usr/lib/hbase does not exist! HBase imports will fail.
Please set $HBASE_HOME to the root of your HBase installation.
usage: sqoop COMMAND [ARGS]

Available commands:
  codegen            Generate code to interact with database records
  create-hive-table  Import a table definition into Hive
  eval               Evaluate a SQL statement and display the results
  export             Export an HDFS directory to a database table
  help               List available commands
  import             Import a table from a database to HDFS
  import-all-tables  Import tables from a database to HDFS
  job                Work with saved jobs
  list-databases     List available databases on a server
  list-tables        List available tables in a database
  merge              Merge results of incremental imports
  metastore          Run a standalone Sqoop metastore
  version            Display version information

See 'sqoop help COMMAND' for information on a specific command.

Bu komutlardan belli başlıları şöyle; codegen parametresi ile tablolara karşılık gelen Java sınıflarının oluşturulması sağlanıyor. create-hive-table ile Hive üzerinde tabloların yaratılması sağlanıyor. import komutu ile veritabanından Hadoop’a, export komutu ile Hadoop’dan veritabanına veri aktarılıyor. Komutlar ile ilgili daha fazla detay için, örneğin import için, sqoop import help yazabilirsiniz.

Şimdi employees tablosunu HDFS üzerine şu şekilde aktarabiliriz:

$ sqoop import --connect jdbc:mysql://localhost:3306/employees --username test -P --table employees
Warning: /usr/lib/hbase does not exist! HBase imports will fail.
Please set $HBASE_HOME to the root of your HBase installation.
Enter password:
13/07/07 17:49:30 INFO manager.MySQLManager: Preparing to use a MySQL streaming resultset.
13/07/07 17:49:30 INFO tool.CodeGenTool: Beginning code generation
13/07/07 17:49:30 INFO manager.SqlManager: Executing SQL statement: SELECT t.* FROM `employees` AS t LIMIT 1
13/07/07 17:49:30 INFO manager.SqlManager: Executing SQL statement: SELECT t.* FROM `employees` AS t LIMIT 1
13/07/07 17:49:30 INFO orm.CompilationManager: HADOOP_MAPRED_HOME is /usr/java/hadoop
Note: /tmp/sqoop-haqen/compile/53e09041098415156dfde1b76932ac43/employees.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
13/07/07 17:49:32 INFO orm.CompilationManager: Writing jar file: /tmp/sqoop-haqen/compile/53e09041098415156dfde1b76932ac43/employees.jar
13/07/07 17:49:32 WARN manager.MySQLManager: It looks like you are importing from mysql.
13/07/07 17:49:32 WARN manager.MySQLManager: This transfer can be faster! Use the --direct
13/07/07 17:49:32 WARN manager.MySQLManager: option to exercise a MySQL-specific fast path.
13/07/07 17:49:32 INFO manager.MySQLManager: Setting zero DATETIME behavior to convertToNull (mysql)
13/07/07 17:49:32 INFO mapreduce.ImportJobBase: Beginning import of employees
13/07/07 17:49:33 INFO db.DataDrivenDBInputFormat: BoundingValsQuery: SELECT MIN(`emp_no`), MAX(`emp_no`) FROM `employees`
13/07/07 17:49:34 INFO mapred.JobClient: Running job: job_201307071405_0001
13/07/07 17:49:35 INFO mapred.JobClient: map 0% reduce 0%
13/07/07 17:49:55 INFO mapred.JobClient: map 25% reduce 0%
13/07/07 17:49:58 INFO mapred.JobClient: map 50% reduce 0%
13/07/07 17:50:01 INFO mapred.JobClient: map 75% reduce 0%
13/07/07 17:50:04 INFO mapred.JobClient: map 100% reduce 0%
13/07/07 17:50:09 INFO mapred.JobClient: Job complete: job_201307071405_0001
13/07/07 17:50:09 INFO mapred.JobClient: Counters: 18
13/07/07 17:50:09 INFO mapred.JobClient: Job Counters
13/07/07 17:50:09 INFO mapred.JobClient: SLOTS_MILLIS_MAPS=37151
13/07/07 17:50:09 INFO mapred.JobClient: Total time spent by all reduces waiting after reserving slots (ms)=0
13/07/07 17:50:09 INFO mapred.JobClient: Total time spent by all maps waiting after reserving slots (ms)=0
13/07/07 17:50:09 INFO mapred.JobClient: Launched map tasks=4
13/07/07 17:50:09 INFO mapred.JobClient: SLOTS_MILLIS_REDUCES=0
13/07/07 17:50:09 INFO mapred.JobClient: File Output Format Counters
13/07/07 17:50:09 INFO mapred.JobClient: Bytes Written=13821993
13/07/07 17:50:09 INFO mapred.JobClient: FileSystemCounters
13/07/07 17:50:09 INFO mapred.JobClient: HDFS_BYTES_READ=464
13/07/07 17:50:09 INFO mapred.JobClient: FILE_BYTES_WRITTEN=122484
13/07/07 17:50:09 INFO mapred.JobClient: HDFS_BYTES_WRITTEN=13821993
13/07/07 17:50:09 INFO mapred.JobClient: File Input Format Counters
13/07/07 17:50:09 INFO mapred.JobClient: Bytes Read=0
13/07/07 17:50:09 INFO mapred.JobClient: Map-Reduce Framework
13/07/07 17:50:09 INFO mapred.JobClient: Map input records=300024
13/07/07 17:50:09 INFO mapred.JobClient: Physical memory (bytes) snapshot=387411968
13/07/07 17:50:09 INFO mapred.JobClient: Spilled Records=0
13/07/07 17:50:09 INFO mapred.JobClient: CPU time spent (ms)=29100
13/07/07 17:50:09 INFO mapred.JobClient: Total committed heap usage (bytes)=343277568
13/07/07 17:50:09 INFO mapred.JobClient: Virtual memory (bytes) snapshot=1597562880
13/07/07 17:50:09 INFO mapred.JobClient: Map output records=300024
13/07/07 17:50:09 INFO mapred.JobClient: SPLIT_RAW_BYTES=464
13/07/07 17:50:09 INFO mapreduce.ImportJobBase: Transferred 13.1817 MB in 37.2724 seconds (362.1456 KB/sec)
13/07/07 17:50:09 INFO mapreduce.ImportJobBase: Retrieved 300024 records.

Bu aktarım işlemini –direct parametresi ile yapsaydık JDBC yerine paralel olarak mysqldump kullanarak tabloyu aktarması 33.5059 sn (402.8555 KB/sec) sürecekti. Şimdi HDFS üzerinde dosyaların oluşup oluşmadığını kontrol edebilirsiniz.

Sqoop ile tablonun tamamını aktarmak zorunda değiliz, –query parametresi ile verdiğimiz sorgu sonucunun aktarılmasını sağlayabiliriz. Bunun dışında varsayılan olarak metin dosyası haline aktarılan verilerin alan ve satır ayraçlarını belirleyebiliriz, metin dosyaları dışında Hadoop’un binary formatı olan SequenceFile veya Avro formatında da veriler aktarılabiliriz.

Örneğimize devam etmek için veritabanındaki tüm tabloları –hive-import komutunu da kullanarak direkt olarak Hive’a aktarmak için şu komutu çalıştırıyoruz:

$ sqoop import-all-tables --connect jdbc:mysql://localhost:3306/employees --username test -P --direct --hive-import

Aktarım tamamlandıktan sonra hive komutu ile tabloların düzgün bir şekilde aktarılıp aktarılmadığını kontrol edebilirsiniz:

hive> show tables;
OK
departments
dept_emp
dept_manager
employees
salaries
titles
Time taken: 3.899 seconds

hive> select * from employees limit 10;
OK
10001 1953-09-02 Georgi Facello M 1986-06-26
10002 1964-06-02 Bezalel Simmel F 1985-11-21
10003 1959-12-03 Parto Bamford M 1986-08-28
10004 1954-05-01 Chirstian Koblick M 1986-12-01
10005 1955-01-21 Kyoichi Maliniak M 1989-09-12
10006 1953-04-20 Anneke Preusig F 1989-06-02
10007 1957-05-23 Tzvetan Zielinski F 1989-02-10
10008 1958-02-19 Saniya Kalloufi M 1994-09-15
10009 1952-04-19 Sumant Peac F 1985-02-18
10010 1963-06-01 Duangkaew Piveteau F 1989-08-24
Time taken: 0.631 seconds

Şimdi Hive üzerinde bir tablo oluşturarak, employees tablosu ile titles tablosunu join işlemiyle birleşiminin sonucunu bu tabloya aktaralım:

hive> create table employees_with_titles (emp_no int, first_name string, last_name string, title string) row format delimited fields terminated by '\t';

hive> insert overwrite table employees_with_titles select e.emp_no, e.first_name, e.last_name, t.title from employees e join titles t on t.emp_no = e.emp_no where t.to_date = '9999-01-01';

hive> select * from employees_with_titles limit 10;
OK
10001 Georgi Facello Senior Engineer
10002 Bezalel Simmel Staff
10003 Parto Bamford Senior Engineer
10004 Chirstian Koblick Senior Engineer
10005 Kyoichi Maliniak Senior Staff
10006 Anneke Preusig Senior Engineer
10007 Tzvetan Zielinski Senior Staff
10009 Sumant Peac Senior Engineer
10010 Duangkaew Piveteau Engineer
10012 Patricio Bridgland Senior Engineer
Time taken: 0.151 seconds

Son olarak da Hive üzerindeki bu verileri MySQL’e aktaralım. Burda dikkat edilmesi gereken konu, export işlemi sırasında import işleminde olduğu gibi tablolar otomatik olarak oluşturulmuyor. Bunun sebebi ise her veritabanında veri tiplerinin farklılık gösteriyor olması. Örneğin Hive’da string formatında bulunan veri veritabanına char, varchar, nvarchar gibi farklı formatlarda aktarılabilir. Bu yüzden export işlemi öncesinde tablo yaratılma işlemini elle biz yapıyoruz.

delimiter $$
CREATE TABLE `employees_with_titles` (
`emp_no` int(11) NOT NULL,
`first_name` varchar(50) NOT NULL,
`last_name` varchar(50) NOT NULL,
`title` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

Sqoop ile Hive’dan MySQL’e verileri aktararak örneğimizi tamamlıyoruz:

$ sqoop export --connect jdbc:mysql://localhost:3306/employees --username root -P --table employees_with_titles --export-dir /user/hive/warehouse/employees_with_titles --input-fields-terminated-by '\t'
Warning: /usr/lib/hbase does not exist! HBase imports will fail.
Please set $HBASE_HOME to the root of your HBase installation.
Enter password:
13/07/07 18:58:21 INFO manager.MySQLManager: Preparing to use a MySQL streaming resultset.
13/07/07 18:58:21 INFO tool.CodeGenTool: Beginning code generation
13/07/07 18:58:21 INFO manager.SqlManager: Executing SQL statement: SELECT t.* FROM `employees_with_titles` AS t LIMIT 1
13/07/07 18:58:21 INFO manager.SqlManager: Executing SQL statement: SELECT t.* FROM `employees_with_titles` AS t LIMIT 1
13/07/07 18:58:21 INFO orm.CompilationManager: HADOOP_MAPRED_HOME is /usr/java/hadoop
Note: /tmp/sqoop-haqen/compile/d0f66a6a6613a7a744d66e9779d8a0ec/employees_with_titles.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
13/07/07 18:58:22 INFO orm.CompilationManager: Writing jar file: /tmp/sqoop-haqen/compile/d0f66a6a6613a7a744d66e9779d8a0ec/employees_with_titles.jar
13/07/07 18:58:22 INFO mapreduce.ExportJobBase: Beginning export of employees_with_titles
13/07/07 18:58:24 INFO input.FileInputFormat: Total input paths to process : 1
13/07/07 18:58:24 INFO input.FileInputFormat: Total input paths to process : 1
13/07/07 18:58:24 INFO util.NativeCodeLoader: Loaded the native-hadoop library
13/07/07 18:58:24 WARN snappy.LoadSnappy: Snappy native library not loaded
13/07/07 18:58:24 INFO mapred.JobClient: Running job: job_201307071405_0026
13/07/07 18:58:25 INFO mapred.JobClient: map 0% reduce 0%
13/07/07 18:58:43 INFO mapred.JobClient: map 50% reduce 0%
13/07/07 18:58:52 INFO mapred.JobClient: map 100% reduce 0%
13/07/07 18:58:57 INFO mapred.JobClient: Job complete: job_201307071405_0026
13/07/07 18:58:57 INFO mapred.JobClient: Counters: 18
13/07/07 18:58:57 INFO mapred.JobClient: Job Counters
13/07/07 18:58:57 INFO mapred.JobClient: SLOTS_MILLIS_MAPS=38842
13/07/07 18:58:57 INFO mapred.JobClient: Total time spent by all reduces waiting after reserving slots (ms)=0
13/07/07 18:58:57 INFO mapred.JobClient: Total time spent by all maps waiting after reserving slots (ms)=0
13/07/07 18:58:57 INFO mapred.JobClient: Launched map tasks=4
13/07/07 18:58:57 INFO mapred.JobClient: Data-local map tasks=4
13/07/07 18:58:57 INFO mapred.JobClient: SLOTS_MILLIS_REDUCES=0
13/07/07 18:58:57 INFO mapred.JobClient: File Output Format Counters
13/07/07 18:58:57 INFO mapred.JobClient: Bytes Written=0
13/07/07 18:58:57 INFO mapred.JobClient: FileSystemCounters
13/07/07 18:58:57 INFO mapred.JobClient: HDFS_BYTES_READ=8453800
13/07/07 18:58:57 INFO mapred.JobClient: FILE_BYTES_WRITTEN=121908
13/07/07 18:58:57 INFO mapred.JobClient: File Input Format Counters
13/07/07 18:58:57 INFO mapred.JobClient: Bytes Read=0
13/07/07 18:58:57 INFO mapred.JobClient: Map-Reduce Framework
13/07/07 18:58:57 INFO mapred.JobClient: Map input records=240124
13/07/07 18:58:57 INFO mapred.JobClient: Physical memory (bytes) snapshot=417497088
13/07/07 18:58:57 INFO mapred.JobClient: Spilled Records=0
13/07/07 18:58:57 INFO mapred.JobClient: CPU time spent (ms)=25760
13/07/07 18:58:57 INFO mapred.JobClient: Total committed heap usage (bytes)=388956160
13/07/07 18:58:57 INFO mapred.JobClient: Virtual memory (bytes) snapshot=1607860224
13/07/07 18:58:57 INFO mapred.JobClient: Map output records=240124
13/07/07 18:58:57 INFO mapred.JobClient: SPLIT_RAW_BYTES=596
13/07/07 18:58:57 INFO mapreduce.ExportJobBase: Transferred 8.0622 MB in 34.3876 seconds (240.077 KB/sec)
13/07/07 18:58:57 INFO mapreduce.ExportJobBase: Exported 240124 records.
« Older Entries