Redis的编译安装与配置


参考资料:
http://heyheymymy.net/python/install-redis-in-ubuntu-10-04
http://www.cnblogs.com/hb_cattle/archive/2011/10/22/2220907.html

Redis是一种高级key-value数据库。它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富。有字符串,链表,集合和有序集合。支持在服务器端计算集合的并,交和补集(difference)等,还支持多种排序功能。所以Redis也可以被看成是一个数据结构服务器。
Redis的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”);也可以把每一次数据变化都写入到一个append only file(aof)里面(这称为“全持久化模式”)。

1. 安装Redis Server
安装系统所需软件包
$ sudo apt-get install python-setuptools python-dev build-essential python-pip libcurl4-openssl-dev

安装libunwind库
$ wget http://download.savannah.gnu.org/releases/libunwind/libunwind-0.99-alpha.tar.gz
$ tar zxvf libunwind-0.99-alpha.tar.gz
$ cd libunwind-0.99-alpha/
$ CFLAGS=-fPIC ./configure
$ make CFLAGS=-fPIC
$ sudo make CFLAGS=-fPIC install

安装google-preftools
$ wget http://google-perftools.googlecode.com/files/google-perftools-1.8.1.tar.gz
$ tar zxvf google-perftools-1.8.1.tar.gz
$ cd google-perftools-1.8.1/
$ ./configure --disable-cpu-profiler --disable-heap-profiler --disable-heap-checker --disable-debugalloc --enable-minimal
$ sudo make && make install
$ sudo echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf
$ sudo /sbin/ldconfig

$ wget http://redis.googlecode.com/files/redis-2.4.17.tar.gz
$ tar xzf redis-2.4.17.tar.gz
$ cd redis-2.4.17
$ sudo mkdir -p /opt/redis
$ sudo make PREFIX=/opt/redis USE_TCMALLOC=yes install

$ sudo lsof -n | grep tcmalloc
redis-ser 31590 elton mem REG 8,3 1155539 4856411 /usr/local/lib/libtcmalloc_minimal.so.0.2.1

$ tree /opt/redis
/opt/redis
├── bin
├── redis-benchmark #性能测试工具,测试Redis在你的系统及你的配置下的读写性
├── redis-check-aof #更新日志检查
├── redis-check-dump #用于本地数据库检查
├── redis-cli #命令行操作工具
└── redis-server #Redis服务器的daemon启动程序

2. 创建服务管理脚本
$ sudo vim /etc/init.d/redis

#!/bin/sh

PATH="/opt/redis/bin:$PATH"
EXEC="/opt/redis/bin/redis-server"
CLIEXEC="/opt/redis/bin/redis-cli"
PIDFILE="/opt/redis/run/redis_6379.pid"
CONF="/opt/redis/etc/redis_6379.conf"
REDISPORT="6379"

case "$1" in
    start)
        if [ -f $$PIDFILE ]
        then
                echo "$PIDFILE exists, process is already running or crashed."
        else
                echo "Starting Redis server..."
                $EXEC $CONF
        fi
        ;;
    stop)
        if [ ! -f $PIDFILE ]
        then
                echo "$PIDFILE does not exist, process is not running."
        else
                PID=$(cat $PIDFILE)
                echo "Stopping ..."
                $CLIEXEC -p $REDISPORT shutdown
                while [ -x /proc/${PID} ]
                do
                    echo "Waiting for Redis to shutdown ..."
                    sleep 1
                done
                echo "Redis stopped."
        fi
        ;;
    *)    
        echo "Usage: $0 {start|stop}" >&2
        exit 1
        ;;
esac

3. 创建与修改配置文件

$ sudo mkdir -p /opt/redis/etc
$ sudo mkdir -p /opt/redis/run
$ sudo mkdir -p /opt/redis/data/6379
$ sudo mkdir -p /opt/redis/log
$ sudo cp /redis-2.4.17/redis.conf /opt/redis/etc/redis.conf
$ sudo cp /opt/redis/etc/redis.conf /opt/redis/etc/redis_6379.conf

修改配置文件:
$ sudo vim /opt/redis/etc/redis_6379.conf
daemonize yes
pidfile /opt/redis/run/redis_6379.pid
dir /opt/redis/data/6379
logfile /opt/redis/log/redis_6379.log

相关配置参数详解:

daemonize yes #是否作为守护进程运行
pidfile /opt/redis/run/redis_6379.pid #如以后台进程运行,则需指定一个pid,默认为/var/run/redis.pid
port 6379 #默认监听端口
#bind 127.0.0.1 #绑定主机IP,默认值为不绑定,即0.0.0.0
timeout 0 #客户端闲置多少秒后,断开连接,默认为0,即不断开
loglevel verbose #日志记录等级,有4个可选值,debug,verbose(默认值),notice,warning
logfile /opt/redis/log/redis_6379.log #指定日志输出的文件名,默认值为stdout,也可设为/dev/null屏蔽日志
databases 16 #可用数据库数,默认值为16,默认数据库为0
################################ SNAPSHOTTING #################################
save 900 1 #保存数据到disk的策略,当有一条Keys数据被改变是,900秒刷新到disk一次
save 300 10 #当有10条Keys数据被改变时,300秒刷新到disk一次
save 60 10000 #当有1w条keys数据被改变时,60秒刷新到disk一次
rdbcompression yes #当dump .rdb数据库的时候是否压缩数据对象
dbfilename dump.rdb #本地数据库文件名,默认值为dump.rdb
dir /opt/redis/data/6379 #本地数据库存放路径
################################# REPLICATION #################################
# slaveof <masterip> <masterport> #当本机为从服务时,设置主服务的IP及端口
# masterauth <master-password> #当本机为从服务时,设置主服务的连接密码
# requirepass foobared #连接密码
slave-serve-stale-data yes
slave-priority 100
################################### LIMITS ####################################
# maxclients 128 #最大客户端连接数,默认不限制
# maxmemory <bytes> #最大内存使用设置,达到最大内存设置后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理后,仍到达最大内存设置,将无法再进行写入操作
############################## APPEND ONLY MODE ###############################
appendonly no #是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认值为no
# appendfilename appendonly.aof #更新日志文件名,默认值为appendonly.aof
# appendfsync always #更新日志条件,共有3个可选值。no表示等操作系统进行数据缓存同步到磁盘,always表示每次更新操作后手动调用fsync()将数据写到磁盘,everysec表示每秒同步一次(默认值)
appendfsync everysec
# appendfsync no
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
################################## SLOW LOG ###################################
slowlog-log-slower-than 10000
slowlog-max-len 128
################################ VIRTUAL MEMORY ###############################
vm-enabled no #是否开启VM功能,默认值为no
vm-swap-file /tmp/redis.swap #虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
vm-max-memory 0 #将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的 (Redis的索引数据就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0
vm-page-size 32
vm-pages 134217728
vm-max-threads 4
############################### ADVANCED CONFIG ###############################
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
activerehashing yes #是否重置Hash表

注意:Redis官方文档对VM的使用提出了一些建议:
当你的key很小而value很大时,使用VM的效果会比较好。因为这样节约的内存比较大。
当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value。
最好使用linux ext3 等对稀疏文件支持比较好的文件系统保存你的swap文件。
vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数。如果设置为0,那么所有对swap文件的操作都是串行的。可能会造成比较长时间的延迟,但是对数据完整性有很好的保证。

4. 修改文件与目录属性
$ sudo adduser redis
$ sudo passwd redis
$ sudo adduser redis admin

$ sudo chmod +x /etc/init.d/redis
$ sudo chown -R redis:redis /opt/redis
$ sudo touch /opt/redis/log/redis_6379.log
$ sudo chown redis:redis /opt/redis/log/redis_6379.log

5. 启动Redis并检查运行情况
$ sudo vim /etc/sysctl.conf
Add the follow item:
vm.overcommit_memory = 1
$ sudo sysctl -p

该配置参数的含义:
/proc/sys/vm/overcommit_memory文件指定了内核针对内存分配的策略,其值可以是0、1、2。
0 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2 表示内核允许分配超过所有物理内存和交换空间总和的内存。
Redis在dump数据的时候,会fork出一个子进程,理论上child进程所占用的内存和parent是一样的,比如parent占用的内存为 8G,这个时候也要同样分配8G的内存给child, 如果内存无法负担,往往会造成redis服务器的down机或者IO负载过高,效率下降。
所以这里比较优化的内存分配策略应该设置为 1(表示内核允许分配所有的物理内存,而不管当前的内存状态如何)。

$ sudo /etc/init.d/redis start

$ ps aux | grep redis
root 13955 0.0 0.3 35932 1508 ? Ssl 22:18 0:00 /opt/redis/bin/redis-server /opt/redis/etc/redis_6379.conf

6. 安装 Redis Python Client
$ sudo pip install redis
$ sudo apt-get install ipython
$ sudo apt-get install ngrep

$ ipython
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
In [1]: import redis
In [2]: rs = redis.Redis("localhost")
In [3]: rs.set("city", "Vancouver")
Out[3]: True

7. 数据的保存与备份
因为Redis是异步写入磁盘的,如果要让内存中的数据马上写入硬盘可以执行如下命令:
$ sudo redis-cli -p 6379 save
另外,执行redis-benchmark命令式也会将内存数据写入硬盘。

8. 同步机制
Redis实现的同步机制相对简单,缺少同步机制常见的check point和校验机制。
在运行时,如果master -> slave同步请求转发被丢弃, slave将无法恢复该请求的相关信息,直到slave重启时从master全量加载数据时才能修复。因此,建议使用Redis尽量利用其key/value和value支持多种类型的特性,存储一些相对不重要的数据。

  1. #1 by mcsrainbow on 2012/09/25 - 16:01

    推荐一个很棒的Redis资料汇总专题:
    http://blog.nosqlfan.com/html/3537.html

  2. #2 by jerry on 2014/09/25 - 12:30

    博主,您好,我觉你的redis的启动脚本可以优化一个地方

    改成这样
    ...
    #CLIEXEC="/usr/local/redis/bin/redis-cli"
    ...
    #$CLIEXEC -p $REDISPORT shutdown
    kill `cat $PIDFILE`
    ...
    改的地方已经注释掉了,这样的好处是如果有人给redis加了密码,你重启redis的时候,会报如下错误
    root@jerjin-10:/usr/local/redis/bin# /etc/init.d/redis stop
    Stopping ...
    (error) NOAUTH Authentication required.
    Waiting for Redis to shutdown ...
    Waiting for Redis to shutdown ...
    Waiting for Redis to shutdown ...
    Waiting for Redis to shutdown ...

    (为什么要加密码?因为redis速度相当快,所以在一台比较好的服务器之下,一个外部的用户可以在一秒钟进行上万次的密码尝试,这意味着你需要制定非常强大的密码来防止暴力破解)

    编辑配置文件/usr/local/redis/etc/redis_6379.conf
    找到”requirepass”这一行,默认是注释掉的,去掉注释,自定义相关密码

    仅仅个人建议而已

(will not be published)
*