8 Şubat 2015 Pazar

Redis (AB15)

Redis, özellikle web uygulamalarında yaygın kullanılan, gelişmiş bir anahtar-değer veritabanıdır. Kullanan bazı tanınmış şirketler: Twitter, Github, Weibo, Pinterest, Snapchat, Craigslist, Digg, StackOverflow, Flickr..



Kurulum (Centos 6.6 minimal için)

Önce epel(Extra Packages for Enterprise Linux) ve remi  paket depolarını ekleyelim.

#rpm -Uvh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
#rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

#yum repolist (depoların eklendiğini bu komutla görebiliriz.)

#yum install redis -y

#redis -version

Yapılandırma

vim /etc/redis.conf

(slaveof <master-ip> <master-port>)
slaveof 192.168.56.103 6379 (diğer makina(lar)ın ip'si portu)

#service redis start

redis loglarını görmek için:
#tail -f /var/log/redis/redis.log
 
# redis-cli
127.0.0.1:6379>info
127.0.0.1:6379>keys *
127.0.0.1:6379>monitor

Sentinel(koruyucu, muhafız) 
 
/etc/redis-sentinel.conf  
Master makinayı kapatınca slave makinalardan biri master olmaz. Sentinel'ler Redis yönetimi yapan dağıtık sistemdir. İzleme, uyarma, failover(yük devretme) özellikleri vardır. Master seçimi için önce kendi aralarında haberleşir, oy çokluğu ile yeni master makinayı seçerler. 

Yük dengeleme ve kesintisiz master erişimi için Haproxy ile kullanılıyor.
1 master ve 1 slave makinamız varsa, kesintisiz master erişimi için en az 3 sentinel ve 2 haproxy makinası ile sağlıklı bir sistem oluşturbiliriz.
 
Sentineller kendi aralarında ve Redis'lerle konuşur. Master'a karar verir ve onu izlerler. Bir yazma isteği gelirse, Virtual IP hangi Haproxy makinasında ise ona gider. Haproxy, Sentinel'lerden master makinayı öğrenir ve isteği master makinaya gönderir.

MongoDB (AB15)

MongoDB (humongous'dan geliyor. Çok büyük, kocaman anlamında)
* ölçeklenebilir
* doküman tabanlı
* C++ ile 10gen tarafından geliştirilmiş
* NoSQL veritabanı uygulaması.

MongoDB, özellikle hız gerektiren ve geleneksel ilişkisel veritabanlarının (rdbms) hantal ve yavaş kaldığı yapılarda kullanılmaktadır.

SQL                                            MongoDB

database                                    database

table                                           collection

row                                            document ya da BSON(Binary Json) document

column                                       field
 
Kurulum: (Centos 6.6 minimal için)

#vim /etc/yum.repos.d/mongodb.repo

[mongodb]
name=MongoDB Repository
baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64/
gpgcheck=0
enabled=1

# yum install -y mongodb-org

# chkconfig --add mongodb

Konsol yönetimi için , birincil arka plan kabuğunu çalıştırmamız gerekiyor.
#mongod

veritabanlanlarını listeler:
> show dbs
admin  (empty)
local  0.078GB

> use aborgtr
switched to db aborgtr

O anki veritabanını gösteriyor:
> db
aborgtr

veri basarken:
> for (var i = 1; i<=100; i++) {
... db.aborgtr.insert( {x : i} )
... }

döküman listelerken:
> db.aborgtr.find()
{ "_id" : ObjectId("54cdcc52a6b7739755db0c3c"), "x" : 1 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c3d"), "x" : 2 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c3e"), "x" : 3 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c3f"), "x" : 4 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c40"), "x" : 5 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c41"), "x" : 6 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c42"), "x" : 7 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c43"), "x" : 8 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c44"), "x" : 9 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c45"), "x" : 10 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c46"), "x" : 11 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c47"), "x" : 12 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c48"), "x" : 13 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c49"), "x" : 14 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c4a"), "x" : 15 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c4b"), "x" : 16 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c4c"), "x" : 17 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c4d"), "x" : 18 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c4e"), "x" : 19 }
{ "_id" : ObjectId("54cdcc52a6b7739755db0c4f"), "x" : 20 }
Type "it" for more

Replika için yapılandırma ayarları:
vim /etc/mongod.conf

#where to log
logpath=/var/log/mongodb/mongod.log

logappend=true

bind_ip = 0.0.0.0

# fork and run in background
fork=true

port = 27017

dbpath= /var/lib/mongodb

# location of pidfile
pidfilepath = /var/run/mongodb/mongod.pid

# Turn on/off security. Off is currently the default
noauth=true

# Specifies a maximum size in megabytes for the replication operation log
oplogSize = 12288

# Configure ReplicaSet membership
replSet = replicaadi

# Enable rest API (disabled by default)
rest = true

(smallfiles=true)
# service mongod start

Primary olarak belirlenmiş mongo makinesine bağlanılır :
# mongo --host (mongo-primary-ip)

Replica makineler gruba eklenir :(rs: replica set)
> rs.add("mongo-rep02")
> rs.add("mongo-rep03")

Replica seti ayarları ve durumu görüntülenebilir :
> rs.status()
> rs.conf()

dump alırken : 
# mongodump --username aybuke --password foo --db aborgtr --out /root --authenticationDatabase admin

#ls -l /root/aborgtr/

Master önceliklendirme
>cfg = rs.conf()
>cfg.members[0].priority = 0.5
>cfg.members[1].priority = 2
>cfg.members[2].priority = 2
>rs.reconfig(cfg)
rs.conf() ile duruma bakılabilir
2 yüksek öncelikli 0.5 düşük öncelikli manasında

Hidden Member(Gizli üye) Ayarlama
>cfg = rs.conf()
>cfg.members[0].priority = 0
>cfg.members[0].hidden = true
>rs.reconfig(cfg)
rs.conf() ile son duruma bakılabilir

Delayed (Gecikmeli) Üye Ayarlama
>cfg = rs.conf()
>cfg.members[0].priority = 0
>cfg.members[0].hidden = true
>cfg.members[0].slaveDelay = 3600
>rs.reconfig(cfg)
3600 sn geriden gelen bir replika set üyesi ayarlanır.

MongoOplog ile belirli bir süre önceki verileri alma
Primary oplog'undan belirli bir süreye kadar olan değişiklikler aşağıdaki şekilde aktarılır
mongodb0 primary makinesinin oplogundan son 1 saatteki değişiklikleri mongodb02 makinesine al :
# mongooplog --from mongodb0.ab.org.tr --host mongodb02.ab.org.tr --seconds 3600

yararlı komutlar:

abrep1:PRIMARY> rs.printReplicationInfo()
configured oplog size:   1024MB
log length start to end: 67144secs (18.65hrs)
oplog first event time:  Sun Feb 01 2015 15:34:43 GMT+0200 (EET)
oplog last event time:   Mon Feb 02 2015 10:13:47 GMT+0200 (EET)
now:                     Mon Feb 02 2015 10:44:59 GMT+0200 (EET)
---
abrep1:PRIMARY> rs.printSlaveReplicationInfo()
source: centos4.ab.org.tr:27017
        syncedTo: Mon Feb 02 2015 10:13:47 GMT+0200 (EET)
        0 secs (0 hrs) behind the primary
source: centos5.ab.org.tr:27017
        syncedTo: Mon Feb 02 2015 10:13:47 GMT+0200 (EET)
        0 secs (0 hrs) behind the primary

6 Şubat 2015 Cuma

Elastic Search (AB15)

Akademik Bilişim bu yıl Eskişehir'de düzenlendi. Konferans öncesinde 4 gün boyunca birçok alanda eğitim verildi. Ben de "Yeni Uygulama Servisleri 1" kursuna katıldım. İlk gün Elastic Search, 2 ve 3. gün MongoDB son gün de Redis anlatıldı. Bu yazımda Elastic Search hakkında öğrendiklerimi yazacağım.

Kursa gelmeden önce sanal makinede Centos 6.6 Minimal kurup gelmiştik. Ayrıca makinelerin internete çıkabilmesi ve kendi aralarında haberleşmesi için de ağ ayarlarını düzenlememiz gerekti. 


*Java ile geliştirilmiş 
*lucene tabanlı
*Apache License, version 2 ("ALv2")
*Ölçeklendirilebilir
*Tam metin(full-text) arama motoru ve veri analiz aracıdır.
*Büyük veriler ile çalışan sistemlerde içerik aramaları, veri analizi ve  sorgulamalar için kullanılır. Örneğin Foursquare, GitHub gibi.
*NoSQL doküman veritabanıdır. (JSON)
*Dokümanlar ilişkisel veritabanlarındaki tablo satırları gibi düşünebilir, veriler JSON formatında tutulur.

Kullanılan Terimler:

** Index : İlişkisel veritabanlarındaki veritabanına karşılık gelir.

** Type (Tip): İlişkisel veritabanlarındaki tablolara eştir.

** Mapping(haritalama): İlişkisel veritabanlarında shema tanımlarına denk düşer. Her index mapping'e sahiptir.

** Document: Elasticsearch'de JSON formatında saklanan dokümanlardır. İlişkisel veritabanı tablolarındaki row'a (satır) denk düşer. Her document bir index'de saklanır ve bir type ve id'ye sahiptir. Document, 0 ya da daha fazla alan barından ya da anahtar-değer çiftlerinden oluşan bir JSON nesnesidir.

** Id: Document'larin kimliğini belirlemek için kullanılır. index, type, id numarası her document için eşsiz olmalıdır. Eğer bir document için ID sağlanmamışsa otomatik olarak oluşturulur.

** Text: Yapılandırılmamış sıradan yazı bütünlerine verilen addır.

** Cluster(Küme): Aynı cluster adını paylaşan bir veya daha fazla node'u barındıran yapıya verilen addır. Her cluster, clusterın kendisi tarafından otomatik olarak seçilen tek bir master node'a sahiptir. Eğer var olan master node bir şekilde ulaşılamaz, servis veremez hale gelirse yine cluster tarafından cluster'daki başka bir node master node'un yerine geçirilir.

** Node: Bir cluster'a ait, sistemde koşan elasticsearch oluşumuna verilen addır. İdeal bir Elastic Search cluster yapısında bir sunucuda bir node bulunmalıdır.
Kurulum:
1) JDK Kurulumu:

Elastic Search kurmak için Jdk paketini kurmalıyız. Önce rpm paketini çekiyoruz.

# wget -c --no-cookies --no-check-certificate --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/7u75-b13/jdk-7u75-linux-x64.rpm -0 jdk-7u75-linux-x64.rpm

Kurulumu yaparken:
# rpm -ivh jdk*

Bu komutla da, jdk'nın kurduğumuz sürümünü kullanmak için ve önceden kurulu başka versiyonda bir jdk varsa karışmaması için kullanılacak dosyaları belirtiyoruz.

# alternatives --install /usr/bin/java java /usr/java/latest/bin/java 20000 \
--slave /usr/bin/keytool keytool /usr/java/latest/bin/keytool \
--slave /usr/bin/rmiregistry rmiregistry /usr/java/latest/bin/rmiregistry \
--slave /usr/bin/javaws javaws /usr/java/latest/bin/javaws \
--slave /usr/bin/orbd orbd /usr/java/latest/bin/orbd \
--slave /usr/bin/pack200 pack200 /usr/java/latest/bin/pack200 \
--slave /usr/bin/rmid rmid /usr/java/latest/bin/rmid \
--slave /usr/bin/rmiregistry rmiregistry /usr/java/latest/bin/rmiregistry \
--slave /usr/bin/servertool servertool /usr/java/latest/bin/servertool \
--slave /usr/bin/tnameserv tnameserv /usr/java/latest/bin/tnameserv \
--slave /usr/bin/unpack200 unpack200 /usr/java/latest/bin/unpack200 \
--slave /usr/bin/jar jar /usr/java/latest/bin/jar \
--slave /usr/bin/jarsigner jarsigner /usr/java/latest/bin/jarsigner

#java -version

2) Elastic Search Kurulumu

İlk olarak elasticsearch.repo  dosyasını oluşturmalıyız.
$ vim /etc/yum.repos.d/elasticsearch.repo

içeriği:

[elasticsearch-1.4]
name=Elasticsearch repository for 1.4.x packages
baseurl=http://packages.elasticsearch.org/elasticsearch/1.4/centos
gpgcheck=0
gpgkey=http://packages.elasticsearch.org/GPG-KEY-elasticsearch
enabled=1

(gpgcheck: Gpg dosyasının kontrol edilmesini sağlar. 1 kontrol et, 0 etme anlamındadır. 1 olursa daha güvenli bir kurulum olur)

# yum install elasticsearch

# chkconfig --add elasticsearch

(Chkconfig komutu istenilen runlevel seviyesinde servisimizi eklememizi, silmemizi , durumunun ne olduğunu öğrenmemizi ve durumunu istediğimiz gibi değiştirmemizi sağlar. --add: Yeni servis eklememizi sağlar.Yani /etc/rc.d/rc[0-6] dizinine servis ekler. chkconfig --list ile listeleyebiliriz.)

Yapılandırma:

Virtual Memory

max_map_count değeri işletim sistemlerinde varsayılan olarak, elasticsearch'ün ihtiyaç duyduğundan az bir değerle geliyor.

Tavsiye edilen değer:
# sysctl -w vm.max_map_count=262144

Eğer rpm/deb deposundan kurulum yapılmışsa bu değer ayarlı geliyor.

Swappiness

Elastic search'ün kullanmak için böldüğü ama kullanmadığı bellek alanını, işletim sistemi çekirdeği ihtiyaç duyduğu anda swap'a atmak ister. Elastic Search çalışan bir sistemde, bu çok büyük performans kaybına yol açar ve node dengesini bozar. Bu nedenle,

*Swap kapatılabilir.
#swapoff -a

*vm.swappiness 0 ya da 1 yapılabilir. (duruma ve ihtiyaca göre değiştirilebilir)
#sysctl -w vm.swappiness=1 (çekirdekdeki swap parametresini düzenlerken)

*mlockall - elasticsearch prosesinine ayrılan ram tamamen engellenebilir.
 /etc/elasticsearch/elasticsearch.yml içeriğinde :
bootstrap.mlockall: true

Eğer nodes çıktısında mlockall:false döndürüyorsa,
ulimit -a | grep locked çıktısı unlimited olmalı:
# ulimit -l unlimited

Bu ayarları şöyle gör :
# curl http://localhost:9200/_nodes/process?pretty

Çevre değişkenleri

/etc/init.d/elasticsearch dosyasında
export ES_HEAP_SIZE=1G
gibi Elasticsearch'ün maximum kullanabileceği ram miktarının üst limitini belirleyebiliriz.
Bu değer ayarlandığında:
ES_MIN(256m) ve ES_MAX(1g) olan değerleri aynı değere sabitler.

Cluster Ayarlama

/etc/elasticsearch/elasticsearch.yml de:

cluster.name : cluster_adi
node.name : elastic01                    # node'un ismi
node.master : true                         # master olup olamayacagi bilgisi
node.data : true                             # üzerinde veri tutup tutmayacagi bilgisi
index.number_of_shards: 5           # kullanilacak primary shard sayisi
index.number_of_replicas : 1        # her bir shard'in kaç replikasi olacagi sayisi
path.conf  /etc/elasticsearch         # elasticsearch ayar dizin yolu
path.data /var/lib/elasticsearch    # elasticsearch data dizin yolu
path.logs  /var/log/elasticsearch  # elasticsearch log dizin yolu
bootstrap.mlockall : true (ram lock için)
network.host: 0.0.0.0
discovery.zen.ping.multicast.enabled: false (çoklu bildirmeyi kapatiyoruz)
discovery.zen.ping.unicast.hosts: ["192.168.56.102] (diğer node'un IP'si)
Bu ayarlar diğer node(lar)'da da yapılıp servisler ayağa kaldırılır.
# service elasticsearch start

Kontroller

Cluster durumu :
# curl -XGET 'http://localhost:9200/_cluster/health?pretty=1'

Node bilgisi :
# curl http://localhost:9200/_nodes/process?pretty

Shardlarin durumu kontrolü :
# curl -XGET localhost:9200/_cat/recovery?v

Index durumu kontrolü:
#curl -XGET 'localhost:9200/_cat/indices?v

Veri İşlemleri

Bir JSON verisini sisteme basmak için önce veritabanı oluşturalım :

# curl -XPUT http://localhost:9200/shakespeare -d '
{
"mappings" : {
"_default_" : {
"properties" : {
"speaker" : {"type": "string" },
"play_name" : {"type": "string" },
"line_id" : { "type" : "integer" },
"speech_number" : { "type" : "integer" }
      }
    }
  }
}
';

Örnek JSON verisi:
# wget http://www.elasticsearch.org/guide/en/kibana/current/snippets/shakespeare.json

veriyi basarken :
# curl -XPUT localhost:9200/_bulk --data-binary @shakespeare.json

Sorgu çalıştırırken:
# curl -XGET 'http://localhost:9200/shakespeare/_search?q=play_name:Hamlet&q=speaker:Hamlet&pretty'

Kolay gelsin..