2015/2/16

如何在 Centos 6 安裝 redis

以下簡述如何在 Centos 6 安裝 redis

編譯 redis 2.8.19

目前 redis stable 版本為 2.8.19,如果是直接用 yum 安裝,版本是 2.4,但我們需要測試內建的 Sentinel 功能,所以就自行編譯。

tar zxvf redis-2.8.19.tar.gz
cd redis-2.8.19
make
make install

src 目錄中會出現 5 個 執行檔,分別是

  1. redis-server
    主要的 redis server

  2. redis-sentinel
    監控 redis server 的 sentinel 執行檔

  3. redis-cli
    redis CLI 界面

  4. redis-benchmark
    用來檢查 redis 效能

  5. redis-check-aof and redis-check-dump
    檢查壞掉的 data

在 make install 之後,所有執行檔都會被複製到 /usr/local/bin/ 目錄中。

設定 redis service

mkdir /etc/redis
mkdir /var/redis
mkdir /var/redis/6379

編輯 redis service,redis 提供的 script 沒辦法直接在 centos 中使用,必須自己編輯一個

vi /etc/init.d/redis

#!/bin/sh
#
# redis - this script starts and stops the redis-server daemon
#
# chkconfig:   - 85 15 
# description:  Redis is a persistent key-value database
# processname: redis-server
# config:      /etc/redis/6379.conf
# pidfile:     /var/run/redis_6379.pid

REDISPORT=6379
EXEC=/usr/local/bin/redis-server
CLIEXEC=/usr/local/bin/redis-cli

PIDFILE=/var/run/redis_${REDISPORT}.pid
CONF="/etc/redis/${REDISPORT}.conf"

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0

prog=$(basename $EXEC)

lockfile=/var/lock/subsys/redis_${REDISPORT}

start() {
    [ -x $redis ] || exit 5
    [ -f $REDIS_CONF_FILE ] || exit 6
    echo -n $"Starting $prog: "
    daemon $EXEC $CONF
    retval=$?
    echo
    [ $retval -eq 0 ] && touch $lockfile
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "
    killproc $prog -QUIT
    retval=$?
    echo
    [ $retval -eq 0 ] && rm -f $lockfile
    return $retval
}

restart() {
    stop
    start
}

reload() {
    echo -n $"Reloading $prog: "
    killproc $EXEC -HUP
    RETVAL=$?
    echo
}

force_reload() {
    restart
}

rh_status() {
    status $prog
}

rh_status_q() {
    rh_status >/dev/null 2>&1
}

case "$1" in
    start)
        rh_status_q && exit 0
        $1
        ;;
    stop)
        rh_status_q || exit 0
        $1
        ;;
    restart|configtest)
        $1
        ;;
    reload)
        rh_status_q || exit 7
        $1
        ;;
    force-reload)
        force_reload
        ;;
    status)
        rh_status
        ;;
    condrestart|try-restart)
        rh_status_q || exit 0
        ;;
    *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
        exit 2
esac

編輯 redis 設定檔

cp redis.conf /etc/redis/6379.conf

vi /etc/redis/6379.conf

daemonize yes
    因為是 redis damone service,要改成 yes
pidfile /var/run/redis_6379.pid
    設定 process id 檔案
port 6379
    redis 預設使用 TCP Port 6379,如果要使用多個 redis daemon,必須修改 port number
loglevel notice
    設定 loglevel
logfile "/var/log/redis_6379.log"
    設定 log file
dir /var/redis/6379
    這個設定很重要,這是存放redis資料的目錄

啟動redis

chkconfig --level 345 redis on
service redis start

修正啟動發生的錯誤

overcommit_memory

如果在 log file 裡面看到

WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.

修正方法為

echo "vm.overcommit_memory = 1" >> /etc/sysctl.conf
sysctl vm.overcommit_memory=1
service redis-server start

overcommit_memory 的說明

  1. 記憶體配置策略
    /proc/sys/vm/overcommit_memory 裡面的設定值有三種
    0: 表示kernel將檢查是否有足夠的可用記憶體供process使用;如果有足夠的可用記憶體,記憶體申請允許;否則,記憶體申請失敗,並把錯誤返回給process。
    1: 表示kernel允許分配所有的記憶體,而不管當前的記憶體狀態如何。
    2: 表示kernel允許分配超過所有物理記憶體和交換空間總和的記憶體

  2. Overcommit
    在Unix中,當一個user process使用malloc()函數申請記憶體時,假如返回值是NULL,則這個process知道目前沒有可用記憶體空間,就會做相應的處理工作。許多process會列印錯誤訊息並退出。

  3. OOM (out-of-memory)
    Linux使用另外一種處理方式叫做Overcommit,它對大部分申請記憶體的請求都回覆"yes",以便能跑更多更大的程序。因為申請記憶體後,並不會馬上使用記憶體。

    當記憶體真的不足的時候,就會發生OOM killer(OOM=out-of-memory)。它會選擇殺死一些 user process,以便釋放記憶體。

  4. Overcommit的三種方式
    Linux下overcommit有三種策略(Documentation/vm/overcommit-accounting):
    0: 啟發式策略。合理的overcommit會被接受,不合理的overcommit會被拒絕。
    1: 任何overcommit都會被接受。
    2: 當系統分配的記憶體超過swap+N%*物理RAM(N%由vm.overcommit_ratio決定)時,會拒絕commit。

    overcommit的策略通過vm.overcommit_memory設置。
    overcommit的百分比由vm.overcommit_ratio設置。

    範例

     # echo 2 > /proc/sys/vm/overcommit_memory
     # echo 80 > /proc/sys/vm/overcommit_ratio
    

    當oom-killer發生時,linux會選擇殺死哪些process,選擇process的函數是oom_badness函數(在mm/oom_kill.c中),該函數會計算每個進程的點數(0~1000)。點數越高,這個process越有可能被殺死。每個進程的點數跟oom_score_adj有關,而且oom_score_adj可以被設置(-1000最低,1000最高)。

TCP backlog

如果在 log file 裡面看到

WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

解決方式如下

echo 511 > /proc/sys/net/core/somaxconn
service redis restart

如果這個設定要能夠在 reboot 之後還能持續生效,必須修改 /etc/sysctl.conf,在裡面增加一行設定,然後 reboot 機器。

vi /etc/sysctl.conf
net.core.somaxconn = 511

/proc/sys/net/core/somaxconn 是個全域參數,定義了每一個Tcp Port最大的監聽 queue 的長度

Transparent Huge Pages (THP)

如果在 log file 裡面看到

# WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.

解決方式如下

echo never > /sys/kernel/mm/transparent_hugepage/enabled
service redis restart

如果這個設定要能夠在 reboot 之後還能持續生效,必須修改 /etc/grub.conf,在kernel 參數的最後面增加一段設定 transparent_hugepage=never ,然後 reboot 機器。

kernel /vmlinuz-2.6.32-431.el6.x86_64 ...... transparent_hugepage=never

測試

利用 redis-clie 進行測試

redis-cli
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> get hello
"world"

遠端存取的測試

redis-cli -h 192.168.1.16 -p 6379
192.168.1.16:6379> get hello
"world"

redis.conf(6379.conf) 設定檔

設定檔可以用這樣的語法,引入其他的設定檔,如果要設定為單台機器,多個 redis daemon 的環境,可以利用這個方式,將通用設定與獨立的 process 設定分離。

# include /path/to/local.conf
# include /path/to/other.conf
# 預設值 no 是不以 daemon 的方式啟動,正式環境建議改為yes 
daemonize no

# 紀錄 process id 的檔案
pidfile /var/run/redis.pid

# redis 監聽埠號
port 6379

# 預設為不設定,代表監聽此機器所有 IP
# bind 192.168.1.16 127.0.0.1

# 指定用來接受 tcp 連線的 unix socket
# unixsocket /tmp/redis.sock
# unixsocketperm 700

# client 連線 idle timeout 的時間 N seconds (預設值 0 代表 disable)
timeout 0

# 非 0 時,就是使用 TCP ACKs 的 SO_KEEPALIVE 來偵測 client 連線的狀態 (1) 可偵測 dead peer (2) 讓此 TCP 連線不被中間的 router 中斷
# 需要兩倍的時間,才能確定此連線已經中斷了
# 合理的設定值為 60 seconds
tcp-keepalive 0

# debug, verbose, notice, warning
# 越後面,log的資料越精簡
loglevel notice

# log file 位置,空字串代表將 log 輸出到 stdout
logfile "/var/log/redis_6379.log"

# 將 log 寫入 system logger,通常保持為 no
# syslog-enabled no

# 指定 syslog id
# syslog-ident redis

# 指定 syslog facility,必須為 USER 或 LOCAL0-LOCAL7
# syslog-facility local0

# 預設為 dbid 為 0
databases 16

##################

# RDB snapshot 將資料儲存到 disk 的策略
# save <seconds> <changes>
# 例如 save 900 1 代表 900 sec(15min) 之後,至少有一個 key 更動了 value,就會啟動 save to disk
# 可以移除這些策略,就不會啟動 save to disk
save 900 1
save 300 10
save 60 10000

# 當 RDB snapshot 啟動時,redis 預設會停止接受寫入資料,所以 bgsave 會 failed。當 redis 允許寫入時,background save 會再度啟動。
# 如果有設定 redis monitor 機制,就可以將這個設定值 disabled,這樣即使遇到 disk erro,也可以正常繼續工作
stop-writes-on-bgsave-error yes

# dump .rdb database 時,以 LZF 壓縮 string objects,需要消耗一些 CPU resource
rdbcompression yes

# version 5 of RDB 在檔案最後面加上了 CRC64 checksum
rdbchecksum yes

# dump DB 的檔名
dbfilename dump.rdb

# dump DB 的目錄
dir /var/redis/6379


########### replication
# Master-Slave replication, redis replication 是非同步的
# slaveof <masterip> <masterport>

# 如果 master 有設定 requirepass,就需要填寫密碼
# masterauth <master-password>

# 當 master 無法工作,slave 接手處理 client 的 requests
slave-serve-stale-data yes

# redis 2.6 之後,slaves 預設為 read-only
slave-read-only yes


############ LIMITS

# 最大 clients 連線數量上限
# maxclients 10000

# 最多使用多少記憶體,預設為使用所有的記憶體
# 建議應該設定此值,保留一些記憶體給系統及其他 process 使用
# maxmemory <bytes>

# memory policy: 達到 maxmemory 時,要進行什麼處置
# (1) volatile-lru: 以 LRU algorithm 移除有標記為 expire 的 key
# (2) allkeys-lru: 以 LRU algorithm,移除任意的 key
# (3) volatile-random: 移除有標記為 expire 的 random key
# (4) allkeys-random: 移除 randon key
# (5) volatile-ttl: 移除有著最接近的 expire time(較小的 TTL)的 key
# (6) noeviction: 不移除, 直接回應寫入錯誤
# maxmemory-policy volatile-lru

# LRU and minimal TTL algorithms 並不是最精確的找出 key 的方式,為節省 memory 消耗,這是 approximated algorithms
# maxmemory-samples 3

參考資料

Redis Quick Start

Redis 啟動警告錯誤解決

各種不同程式語言的 redis clients

Linux之TCPIP內核參數優化