11 Eylül 2015 Cuma

PHP ile Thread kullanımı

Diyelim ki üç işimiz var ve her biri 1 saniye sürüyor. Normalde arka arkaya çalıştığında bu işlem 3 (üç) saniye sürer. Bir sürü işimiz olsun her biri 1 saniyelik. Tek thread lik bir süreçte bu işler arka arkaya bir birini bekleyerek çalışacağı için toplam işlem süresi iş sayısı kadar olacaktır.
Bunlara işlem sayısı kadar thread açarsak bütün işler 1 saniye sürer.

PHP ile bir örnek yapalım;
Projede Thread kullanmak için PHP de pthread isimli extension yüklemek gerekiyor.


brew install php55-pthreads

Bunu yapınca bütün PHP nin ve eklentilerinin yeniden derlenmesi gerektiğini söylemem gerekiyor.

Örnek kullanım:


result = $sleep;
        sleep($sleep);
    }

    public function getResult() {
        return $this->result;
    }
}

echo "basladi\n";
$timer = microtime(true);
$pool = new Pool(4);
$pool->submit
    (new WebWork());
$pool->submit
    (new WebWork());
$pool->submit
    (new WebWork());
$pool->submit
    (new WebWork());
$pool->shutdown();

$pool->collect(function($query){
    var_dump(
        $done = $query->getResult());
    
    return count($done);
});

printf("islem %f saniye surdu\n", microtime(true)-$timer);
echo "bitti\n";
?>

Yukarıdaki kodu isterseniz console isterseniz web üzerinden çalıştırın aynı sonucu alacaksınız. İşlemler yaklaşık olarak 1 saniye sürecek. Eğer thread sayısını 4 yerine 3 yaparsanız doğal olarak süre uzayacak.

Daha fazla örnek için https://github.com/krakjoe/pthreads/tree/master/examples

28 Ağustos 2015 Cuma

Solr Facet Pivot kullanımı


İhtiyaç: Filtrede birden fazla seçim yapıldığında bu seçimlerin hangi seçimlere bağımlı olduğunun bulunması.

Çözüm: Seçimi yapılan filtrelerin kırılımları solr facet pivot ile kolayca keşfedilebilir.

Örnek sorgu ve sonucu:
http://localhost:8983/solr/browse?wt=json&facet=true&q=*&facet.pivot.mincount=1&facet.pivot={!key%3Dsize-provider-brand-color}facet_attribute_slug_size,facet_provider_url,facet_brand_model_url,facet_color_url




{"responseHeader":{"status":0,"QTime":1},"response":{"numFound":6,"start":0,"docs":[]},"facet_counts":{"facet_queries":{},"facet_fields":{},"facet_dates":{},"facet_ranges":{},"facet_intervals":{},"facet_pivot":{"size-provider-brand-color":[{"field":"facet_attribute_slug_size","value":"m","count":1,"pivot":[{"field":"facet_provider_url","value":"nautica","count":1,"pivot":[{"field":"facet_brand_model_url","value":"nautica","count":1,"pivot":[{"field":"facet_color_url","value":"gri","count":1}]}]}]}]}}}

Bu gelen sonuçları arka tarafta işleyip istediğiniz gibi kullanabilirsiniz.

Not: Bu tür işlemler ekstra yük getirecektir. Bu nedenle solrconfig.xml dosyanızın içine benzer sorgularda Listener eklemelisiniz. Böylece "Searcher" açıldığında bu sorgu çalıştırılacak ve sorgular önceden çalıştırılmış olduğundan normalden daha hızlı çalışacaktır. Tabii cache ayarlarının da iyi olması gerekiyor.

Örnek:

     
        
             *
                /browse
                
                    sum(product(0.001,score_product_like),
                    product(0.02,score_product_hit),
                    product(0.50, score_provider_boost),
                    product(0.45,score_product_boost),
                    product(0.30, score_provider_boost_cpc),
                    product(0.30, score_provider_boost_cps),
                    product(0.50, score_category_product_boost),
                    product(0.09,score_random),
                    scale(random_1,1,5)) desc
                
                true
                facet_attribute_slug_size,facet_provider_url,facet_brand_model_url,facet_color_url
           
        
     


Kolay gelsin.

24 Temmuz 2015 Cuma

Redis Sentinel'e geçin rahat edin :)

Uzun zamandır yazmayı planladığım ama hep ertelediğim bir konuyu sizlerle paylaşmak istiyorum.

Vitringez de memory cache olarak master-slave yapısında Redis kullanıyoruz. Bir süre önce (2014 Haziran) ciddi sorunlar yaşamaya başladık. Sorun Redis tarafında oluyordu. Araştırmalarım neticesinde bizim sorunumuzu Redis Sentinel'in çözeceğini gördüm. Önce local de bazı testler yaptık. Sonrasında ise alt yapıda ufak güncellemeler yaptık. credis kütüphanesini kullanarak yeni yapıyı yayına aldık. O gün bugündür çok memnunuz. Sağladığı otomatik ayağa kaldırma mekanizması ile çok rahat ettik.

Şimdi birlikte bir çalışma yapalım.
1. İlk olarak redis kurulumu yapın.
brew install redis


2. Şuradaki https://github.com/volkan/redis-work dosyaları bir klasöre indirin.
git clone git@github.com:volkan/redis-work.git
3. Sentinel leri aktif hâle getiriyoruz. Failover mekanizması için en az iki sentinel aktif olmalı. Ben bunları logları rahat takip etmek için ayrı tablarda açtım.
redis-sentinel redis-sentinel_26379.conf
redis-sentinel redis-sentinel_26380.conf
4. Redisleri aktif hâle getiriyoruz. (Ayrı tablarda açma olayı redisler içinde geçerli.)
redis-server redis_6381.conf
redis-server redis_6380.conf
redis-server redis_6379.conf
5. Sentinel durumunu kontrol ediyoruz;
redis$  redis-cli -h localhost -p 26379 info     
Aşağıda görüldüğü üzere henüz işlem yapılmıyor.
➜  redis git:(master) redis-cli -h localhost -p 26379 info     
# Server
redis_version:2.8.17
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:447fbed5d78be577
redis_mode:sentinel
os:Darwin 14.4.0 x86_64
arch_bits:64
multiplexing_api:kqueue
gcc_version:4.2.1
process_id:22338
run_id:db7af31f3bcacd0cd7433cb3aadc03751059f9fe
tcp_port:26379
uptime_in_seconds:351
uptime_in_days:0
hz:18
lru_clock:11625915
config_file:/Users/volkan/project/redis/redis-sentinel_26379.conf

# Sentinel
sentinel_masters:0
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
6. Sentinel'e master redis'i verip takip etmesini istiyoruz. Bu işlemi iki sentinel içinde yapıyoruz.
redis-cli -h localhost -p 26379 SENTINEL monitor mymaster 127.0.0.1 6381 2
redis-cli -h localhost -p 26380 SENTINEL monitor mymaster 127.0.0.1 6381 2
Sonrasında aldığımız çıktı da son satır önemli.
master0:name=mymaster,status=ok,address=127.0.0.1:6381,slaves=2,sentinels=2
➜  redis git:(master) redis-cli -h localhost -p 26379 info     
# Server
redis_version:2.8.17
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:447fbed5d78be577
redis_mode:sentinel
os:Darwin 14.4.0 x86_64
arch_bits:64
multiplexing_api:kqueue
gcc_version:4.2.1
process_id:22338
run_id:db7af31f3bcacd0cd7433cb3aadc03751059f9fe
tcp_port:26379
uptime_in_seconds:511
uptime_in_days:0
hz:13
lru_clock:11626075
config_file:/Users/volkan/project/redis/redis-sentinel_26379.conf

# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
master0:name=mymaster,status=ok,address=127.0.0.1:6381,slaves=2,sentinels=2
Sentinel de eklemeler sonrası slaveleri bulup gerekli çalışmaları yapıyor;
[22338] 24 Jul 01:09:42.412 # +monitor master mymaster 127.0.0.1 6381 quorum 2
[22338] 24 Jul 01:09:42.459 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
[22338] 24 Jul 01:09:42.459 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6381
[22338] 24 Jul 01:10:31.881 * +sentinel sentinel 127.0.0.1:26380 127.0.0.1 26380 @ mymaster 127.0.0.1 6381
7. 6381 olan master'ı kapatıyoruz! Burada bizim verdiğimiz gecikme süresine göre sentinel devreye girip bir slave'i master yapıyor.
[22338] 24 Jul 01:12:55.430 # +sdown master mymaster 127.0.0.1 6381
[22338] 24 Jul 01:12:55.489 # +new-epoch 1
[22338] 24 Jul 01:12:55.489 # +vote-for-leader 5f89e827f873bb2bf7acb7f898c21f0903bd80cb 1
[22338] 24 Jul 01:12:55.522 # +odown master mymaster 127.0.0.1 6381 #quorum 2/2
[22338] 24 Jul 01:12:55.522 # Next failover delay: I will not start a failover before Fri Jul 24 01:18:55 2015
[22338] 24 Jul 01:12:56.637 # +config-update-from sentinel 127.0.0.1:26380 127.0.0.1 26380 @ mymaster 127.0.0.1 6381
[22338] 24 Jul 01:12:56.637 # +switch-master mymaster 127.0.0.1 6381 127.0.0.1 6380
[22338] 24 Jul 01:12:56.637 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
[22338] 24 Jul 01:12:56.639 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
Tekrar info komutu çalıştırdığımızda durum aşağıdaki gibi. 6381 olan port 6380 olarak değişmiş. ➜ redis git:(master) ✗ redis-cli -h localhost -p 26379 info
master0:name=mymaster,status=ok,address=127.0.0.1:6380,slaves=2,sentinels=2
8. Kalan son master 6380 redisini kapattım. Kontrol ettiğimde kendisinin master yapıldığını gördüm.
master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=2
Eğer yeni bir makine havuza ekleyecekseniz mutlaka çalışan master'a slave olarak eklemelisiniz. Sentinel bir kere bir makineyi takip etmeye başlarsa sonrasında onu doğru konuma yerleştirir. Birden fazla makine üzerinde çalışırken bir şekilde birbirlerini görmeyebilirler. Bundan emin olmak için aşağıdaki komutu bir sentinel üzerinde çalıştırıp kontrol edebilirsiniz. "protected mode no" olmalı. Ayrıca en az 3 sentinel kullanmalısınız. (Daha fazla olacaksa bu sayı tek sayı olmalı 3,5,7 gibi.)
SENTINEL ckquorum mymaster


Sonuç olarak bu harika nimeti kullanması gördüğünüz üzere oldukça kolay. credis kütüphanesi üzerinden sorgularınızı slave  makinelere dağıtık bir şekilde gönderip verimliliği artırabilirsiniz.

İyi kod yazmalar :)