Redis Nedir ? Yüksek Erişebilirlikli (High Availability) Redis Ortamı Nasıl Oluşturulur

Bu yazıda trendyol.com içerisinde kullandığımız Redis mimarisinden bahsedeceğiz. İlk olarak Redis hakkında kısa bir ön bilgi vermekte fayda var.

Redis Nedir ? 

*Redis NoSql bir key-value database’dir.
*Genelde cache ve benzeri işlemler için kullanılır.
*Verileri bellekte tuttuğu için yüksek performanslı bir şekilde çalışır.
*İstenildiği taktirde belli aralıklarda bellekteki veriyi disk’e yazabilir.

Yüksek Erişebilirlikli (high availability) Redis Ortamı Nasıl Yapılandırılır?

Biz trendyol.com yapısında, Redisin ön tarafına Haproxy konumlandırarak yüksek erişebilirlik, scalability ve maintenance işlemerinde kolaylık sağlıyoruz. Failover ve cluster işlemleri için Redis Sentinel ürününü kullanıyoruz.
Kurguladığımız yapının diagramı aşağıdaki gibi;
Redis_Diagram

Yapıdan kısaca bahsettik. Şimdi işin mutfak kısmına geçelim.

Redis Kurulum İşlemleri

İlk olarak işletim sisteminde performans için yapmamız gereken kernel konfigürasyonlarını yapalım ;

Redis üzerinde latency yaşamamak için bellek yönetimi ile ilgili olan transparent huge page özelliğini devre dışı bırakıyorum.
/etc/rc.local dosyasına aşağıdaki satırı ekliyorum.

# echo never > /sys/kernel/mm/transparent_hugepage/enabled

Sonrasında /etc/sysctl.conf dosyasına swap ve tcp connection için aşağıdaki parametreleri ekliyorum.

vm.overcommit_memory = 1
vm.swappiness=0
net.ipv4.tcp_sack=1
net.ipv4.tcp_timestamps=1
net.ipv4.tcp_window_scaling=1
net.ipv4.tcp_congestion_control=cubic
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_max_syn_backlog=65535
net.core.somaxconn=65535
fs.file-max=65535

Bu işlemlerden sonra sunucuyu yeniden başlatıyorum.

Şimdi Redis kurulumuna geçebiliriz, kurulumdan önce make ve gcc paketlerinin yüklü olduğundan emin olun.

İlk önce kurulum paketini indiriyorum
# wget http://download.redis.io/releases/redis-3.2.5.tar.gz

Paketi açıyoruz
# tar -xzf redis-3.2.5.tar.gz

Daha sonrasında açtığımız dizinde yükleme işlemi için make komutunu çalıştırıyoruz.

# make install

İşlem bittikten sonra aynı dizinde utils altındaki install_server.sh scriptini çalıştırıyoruz.
# utils/install_server.sh

Redis kurulumunu gerçekleştirdik. Redis için ihtiyacınıza göre konfigürasyonu kolay bir şekilde yapabilirsiniz. Bir sonraki aşamada cluster ve failover işlemleri için Sentinel’i kuruyorum.

Sentinel Nedir ? Kurulumu

Redis Sentinel, Redis sunucularını yönetmeye yardımcı olmak için tasarlanmış bir servistir. Genel anlamda üç görevi vardır. Bunlar;
Monitoring: Redis sunucularını izler.
Notification: Redis sunucularının durumlarını bizlere veya herhangi bir uygulamaya bildirir.
Automatic Failover: Master sunucunun (servisin) çalışmadığı durumlarda sentinel slave sunuculardan bir tanesini oylama yöntemi ile master yapar. Diğer slavelerin konfigürasyonunda yeni master sunucusuna göre değiştirir.

Sentinel hakkında kısa bir bilgilendirme yaptık, şimdi konfigürasyon dosyasını oluşturalım. /etc/redis/ altına sentinel_26379.conf olarak dosyayı oluşturup aşağıdaki satırları ekliyorum.
Burada önemli olan nokta master olarak kullanacağımız Redisin endpointi.

# Sentinel Config
dir "/var/lib/redis/sentinel_26379"
pidfile "/var/run/sentinel_26379.pid"
port 26379
bind 0.0.0.0
sentinel monitor redis_master master_redis_sunucusunun_endpointi 6379 2
sentinel down-after-milliseconds redis_master 3000
logfile "/var/log/sentinel_26379"
syslog-enabled no
syslog-ident "sentinel_26379"
syslog-facility user
# Generated by CONFIG REWRITE

Sonrasında config içine girdiğimiz parametrelerin dizinlerini ve dosyalarını oluşturalım.

# mkdir /var/lib/redis/sentinel_26379

Log dosyasını oluşturuyorum.

# touch /var/log/sentinel_26379

Bu işlemlerden sonra sentineli servis haline getirelim. Bunun için /etc/init.d/ altına sentinel_26379 adında bir dosya oluşturup içeriğini aşağıdaki gibi yapalım.

#!/bin/sh
#
# Redis init script for Debian-based distros
#
#
### BEGIN INIT INFO
# Provides: sentinel_26379
# Required-Start: $network $local_fs $remote_fs
# Required-Stop: $network $local_fs $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Should-Start: $syslog $named
# Should-Stop: $syslog $named
# Short-Description: Start and stop sentinel_26379
# Description: Redis Sentinel monitor
### END INIT INFO
# Source the Linux Standard Base functions
. /lib/lsb/init-functions
SENTINEL_PORT=26379
NAME="sentinel_${SENTINEL_PORT}"
DAEMON=/usr/local/bin/redis-server
PIDFILE=/var/run/sentinel_26379.pid
PIDFILE_DIR=$(dirname "${PIDFILE}")
REDIS_USER=root
CONF="/etc/redis/sentinel_${SENTINEL_PORT}.conf"
CLIEXEC="/usr/local/bin/redis-cli -p ${SENTINEL_PORT}"
if [ -r /etc/default/sentinel_${SENTINEL_PORT} ]; then
. /etc/default/sentinel_${SENTINEL_PORT}
fi
if [ -n "$REDIS_PASSWORD" ]; then
CLIEXEC="${CLIEXEC} -a ${REDIS_PASSWORD}"
fi
if [ -n "$BIND_ADDRESS" ]; then
CLIEXEC="${CLIEXEC} -h ${BIND_ADDRESS}"
fi
case "$1" in
start)
if [ -f "$PIDFILE" ]; then
status_of_proc -p "$PIDFILE" $DAEMON "$NAME process" && return 0
fi
if [ -n "$NOFILE_LIMIT" ]; then
ulimit -n $NOFILE_LIMIT
fi
if [ ! -d "$PIDFILE_DIR" ]; then
mkdir "$PIDFILE_DIR"
chown ${REDIS_USER}:${REDIS_USER} "$PIDFILE_DIR"
chmod 0755 "$PIDFILE_DIR"
fi
log_daemon_msg "Starting $NAME..."
if start-stop-daemon --start -q --oknodo -p "$PIDFILE" -c $REDIS_USER --exec $DAEMON -- $CONF --sentinel; then
log_end_msg 0
else
log_end_msg 1
fi
;;
stop)
if [ -f "$PIDFILE" ]; then
PID=$(cat "$PIDFILE")
log_daemon_msg "Stopping $NAME..."
$CLIEXEC shutdown
while [ -x /proc/${PID} ]; do
log_daemon_msg "Waiting for Redis Sentinel to shutdown ..."
sleep 1
done
log_end_msg 0
else
log_daemon_msg "$NAME is not running"
log_end_msg 0
fi
;;
status)
status_of_proc -p "$PIDFILE" $DAEMON "$NAME" && exit 0 || exit $?
;;
restart|force-reload)
${0} stop
${0} start
;;
*)
echo "Usage: /etc/init.d/$NAME {start|stop|status|restart|force-reload}" >&2
exit 1
;;
esac
exit 0

Dosyamızı kaydettikten sonra executable olabilmesi için 755 yetkisini veriyorum.

# chmod 755 /etc/init.d/sentinel_26379

Sonrasında servisleri reload ediyorum

# systemctl daemon-reload

Şimdi sentinel servisini start ediyorum;

# service sentinel_26379 start

Bu işlemlerden sonra Redis ve Sentinel’in çalıştığına emin olalım;

# netstat -tlnp

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:26379 0.0.0.0:* LISTEN 18921/redis-server
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 18539/redis-server
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1326/sshd
tcp6 0 0 :::22 :::* LISTEN 1326/sshd

Yukarıda gördüğünüz üzere Redis ve Sentinel aktif olarak portlarını dinliyorlar.
Bir sonraki adımda master dışındaki sunuculara redis-cli yardımı ile slave rolünü vermeliyiz.

Slave rollerini vermeden önce master sunucu üzerinde info komutunun çıktısı aşağıdaki gibi;
# redis-cli info

# Replication
role:master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

Şimdi slave sunucularda aşağıdaki komutu çalıştırıyorum.

# redis-cli SLAVEOF master_end_point 6379

Slave sunucularımda yukarıdaki komutu çalıştırdıktan sonra masterda tekrar info komutunu çalıştırıp slave sunucularımın eklendiğini görüyorum.

# redis-cli info

# Replication
role:master
connected_slaves:2
slave0:ip=slave1_end_point,port=6379,state=online,offset=10794,lag=1
slave1:ip=slave2_end_point,port=6379,state=online,offset=10794,lag=1

Aynı şekilde slave sunucularda info komutunu çalıştırınca aşağıdaki gibi bir çıktı alıyoruz.

# Replication
role:slave
master_host:master_host_end_point
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:176678
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0

Şimdi failover testi yapabiliriz. Master sunucuda redis servisini stop ettiğinizde sentineller oylama yaparak slave sunuculardan bir tanesini master seçecek. redis-cli ile yeni master sunucusunu görebilirsiniz.
Not: Eski master sunucuda redis servisi tekrar start olduğunda hayatına slave olarak devam edecektir 🙂

Redis kurulum ve config işlemlerini bitirdikten sonra HAProxy tarafına geçebiliriz.
*Öntarafa iki adet HAProxy koyarak vrrp ile cluster yapabilirsiniz.

Redis HAProxy Tanımları

HaProxyde tarafında yazdığımız health check ile servisin ayakta olup olmadığını ve master rolünün hangisinde olduğu gibi bilgileri öğrenip trafiği bu bilgiler doğrultusunda gönderiyoruz.
Kısaca aşağıdaki configde kullanmış olduğum mailers ve Backend tablarını açıklamaya çalışacağım;
* Mailers tabında redis up-down ve failover durumlarının haproxy tarafıdan mail atmasını sağlamak için smtp sunucusu tanımlıyorum.
* Backend tabında arkadaki redis sunucularımı, onların servisinin sağlık durmunu (up-down) ve master rolünün hangisinde olduğunu öğrenip trafiği (istekleri) ona gönderiyorum.

Config aşağıdaki gibi; /etc/haproxy/haproxy.cfg

defaults REDIS
mode tcp
timeout connect 4s
timeout server 30s
timeout client 30s

frontend redis_front
bind *:6379 name redis
default_backend redis_back

mailers smtp01
mailer smtp1 smtp_server_ip:25

backend redis_back
option tcp-check
tcp-check connect
tcp-check send PING\r\n
tcp-check expect string +PONG
tcp-check send info\ replication\r\n
tcp-check expect string role:master
tcp-check send QUIT\r\n
tcp-check expect string +OK
email-alert mailers smtp01
email-alert from redishaproxy@berkayozuygur.com
email-alert to berkay.ozuygur@outlook.com
server ProdRedis01 Redis_01_END_POINT:6379 check inter 1s
server ProdRedis02 Redis_02_END_POINT:6379 check inter 1s
server ProdRedis03 Redis_03_END_POINT:6379 check inter 1s

Redis ve HaProxy kullanarak yüksek erişebilirlikli bir ortamı bu şekilde sağlayabiliyoruz.
Biz bu işlemleri Ansible kullanarak otomatize bir duruma getirdik sizde benzeri bir araç kullanarak işlemleri otomatize edebilirsiniz. Yazıyı biraz fazla uzattım 🙂 Bir sonrakinde görüşmek üzere …

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: