zoukankan      html  css  js  c++  java
  • Centos6 安装 Redis 和集群配置

    Redis安装

    先确认gcc和tcl已经安装

    sudo yum install gcc-c++
    sudo yum install tcl

    解压, 编译和安装

    tar zxvf redis-3.0.5.tar.gz
    sudo mv redis-3.0.5 /usr/src/
    cd /usr/src/redis-3.0.5/
    
    sudo make
    sudo make test
    sudo make install
    
    # 如果不想安装到 /usr/local/bin, 用这个语句会安装到/opt/redis/redis-3.0.5/bin下, 然后再到/usr/bin去建好软链
    sudo make PREFIX=/opt/redis/redis-3.0.5 install

    安装很自由, 在哪里编译都可以, 有用的就是最后生成的那几个binary. Redis 由四个可执行文件:redis-benchmark、redis-cli、redis-server、redis-stat 这四个文件,加上一个redis.conf就构成了整个redis的最终可用包。它们的作用如下:

    • redis-server:Redis服务器的daemon启动程序
    • redis-cli:Redis命令行操作工具。当然,你也可以用telnet根据其纯文本协议来操作
    • redis-benchmark:Redis性能测试工具,测试Redis在你的系统及你的配置下的读写性能
    • redis-stat:Redis状态检测工具,可以检测Redis当前状态参数及延迟状况

    现在就可以启动redis了,redis只有一个启动参数,就是他的配置文件路径。源码中提供了一个redis.conf作为参考

    redis-server /etc/redis.conf

    目录下默认的redis.conf文件的daemonize参数为no,所以redis不会在后台运行。修改为yes则为后台运行redis。另外配置文件中规定了pid文件,log文件和数据文件的地址,如果有需要先修改,默认log信息定向到stdout.

    下面是redis.conf的主要配置参数的意义:

    • daemonize:是否以后台daemon方式运行
    • pidfile:pid文件位置
    • port:监听的端口号
    • timeout:请求超时时间
    • loglevel:log信息级别
    • logfile:log文件位置
    • databases:开启数据库的数量
    • save * *:保存快照的频率,第一个*表示多长时间,第三个*表示执行多少次写操作。在一定时间内执行一定数量的写操作时,自动保存快照。可设置多个条件。
    • rdbcompression:是否使用压缩
    • dbfilename:数据快照文件名(只是文件名,不包括目录)
    • dir:数据快照的保存目录(这个是目录)
    • appendonly:是否开启appendonlylog,开启的话每次写操作会记一条log,这会提高数据抗风险能力,但影响效率。
    • appendfsync:appendonlylog如何同步到磁盘(三个选项,分别是每次写都强制调用fsync、每秒启用一次fsync、不调用fsync等待系统自己同步)

    为Redis建立用户和日志目录

    shell> groupadd redis
    shell> useradd -g redis -s /bin/bash redis
    mkdir -p /var/redis/data chown redis:redis /var/redis/data

    修改数据快照的保存目录,需要修改redis.conf

    # The working directory.
    #
    # The DB will be written inside this directory, with the filename specified
    # above using the 'dbfilename' configuration directive.
    #
    # Also the Append Only File will be created inside this directory.
    #
    # Note that you must specify a directory here, not a file name.
    dir /var/redis/data

    修改log文件位置

    mkdir -p /var/redis/log
    chown redis:redis /var/redis/log
    
    # Specify the log file name. Also 'stdout' can be used to force
    # Redis to log on the standard output. Note that if you use standard
    # output for logging but daemonize, logs will be sent to /dev/null
    logfile /var/redis/log/redislog

    添加用户口令, 取消注释, 将 foobared 修改为32位以上的长字符串, 因为redis的效率, 短口令很容易被破解

    # requirepass foobared

    命令行测试

    ~]$./bin/redis-cli
    127.0.0.1:6379> auth foobared 
    OK
    127.0.0.1:6379> set foo bar OK 127.0.0.1:6379> get foo "bar" 127.0.0.1:6379> exit

    命令行中, 亦可使用 -a 参数, 如 redis-cli -a foobared

    性能测试

    /opt/redis/redis-3.2.6/bin/redis-benchmark -l -p 6379 -a foobared

    使用-l参数会循环运行性能测试样例

    日志中的warning

    3477:M 10 Nov 00:30:57.460 # WARNING: The TCP backlog setting of 511 cannot be e
    nforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
    3477:M 10 Nov 00:30:57.460 # Server initialized
    3477:M 10 Nov 00:30:57.460 # WARNING overcommit_memory is set to 0! Background s
    ave may fail under low memory condition. To fix this issue add 'vm.overcommit_me
    mory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.over
    commit_memory=1' for this to take effect.
    3477:M 10 Nov 00:30:57.460 # WARNING you have Transparent Huge Pages (THP) suppo
    rt 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/transpare
    nt_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retai
    n the setting after a reboot. Redis must be restarted after THP is disabled.

    解决方法: 在/etc/sysctl.conf 中增加

    net.core.somaxconn = 32768
    vm.overcommit_memory = 1

    然后sysctl -p

    对于transparent_hugepage的warning

    只有64位系统才有transparent_hugepage功能。从rhel6开始系统将默认对所有程序开启transparent_hugepage, linux内核将尽可能的尝试分配2M的页大小给程序使用,内核空间在内存中自身是2M对齐的,目的是减少内核TLB(现代CPU使用一小块关联内存,用来缓存最近访问的虚拟页的PTE。这块内存称为translation lookaside buffer)的压力,增大page大小自然会减少TLB大小。如果内存没有2M连续大小的空间可分配,内核会回退到分配4KB页的方案。THP页也是可以换出的,这是通过把2M的大页分割成4KB的普通页实现的。内核通过增加一个khugepaged内核线程,来不停的寻找连续的足够大的尽量对其的内存区域来满足内存分配请求。这个线程会偶尔尝试使用大的内存分配来替换连续的小内存页以最大化THP 的使用。数据库应用不建议开启Transparent HugePages. ORACLE, mongodb和Redis都不建议开启THP, THP在运行时动态分配内存, 可能会带来运行时内存分配的延误.

    查询系统是否开启了THP命令

    [root@middle ~]# cat /sys/kernel/mm/transparent_hugepage/enabled
    [always] madvise never
    [root@middle ~]# cat /sys/kernel/mm/transparent_hugepage/defrag
    [always] madvise never

    实时生效

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

    加入启动, 重启后自动生效

    # 在/etc/rc.local中增加如下内容
    
    if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
    echo never > /sys/kernel/mm/transparent_hugepage/enabled
    fi
    
    if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
    echo never > /sys/kernel/mm/transparent_hugepage/defrag
    fi

    用于添加服务的 /etc/init.d/redis.
    Update 2017-11-10 在redis-4.0.2的源代码中有init.d例子, 位于 utils/redis_init_script

    #!/bin/bash
    #
    # redis          Start up the Redis server daemon
    #
    # chkconfig: 2345 55 25
    # description: 
    #
    # processname: /opt/redis/redis-3.2.6/bin/redis-server
    # pidfile: /var/redis/redis.pid
    
    PATH=/sbin:/bin:/usr/bin:/usr/sbin
    
    USER=redis
    REDISPORT=16379
    EXEC=/opt/redis/redis-3.2.6/bin/redis-server
    REDIS_CLI=/opt/redis/redis-3.2.6/bin/redis-cli
    SECURE=foobar
    
    PIDFILE=/var/redis/redis.pid
    CONF=/opt/redis/redis-3.2.6/conf/redis.conf
    
    case "$1" in
      start)
    if [ -d /sys/kernel/mm/transparent_hugepage ]; then
          echo 'never' > /sys/kernel/mm/transparent_hugepage/enabled
          echo 'never' > /sys/kernel/mm/transparent_hugepage/defrag
        elif [ -d /sys/kernel/mm/redhat_transparent_hugepage ]; then
          echo 'never' > /sys/kernel/mm/transparent_hugepage/enabled
          echo 'never' > /sys/kernel/mm/transparent_hugepage/defrag
        fi
    if [ -f $PIDFILE ] then echo "$PIDFILE exists, process is already running or crashed" else echo "Starting Redis server..." su - $USER -c "$EXEC $CONF" fi if [ "$?"="0" ] then echo "Redis is running..." fi ;; stop) if [ ! -f $PIDFILE ] then echo "$PIDFILE does not exist, process is not running" else PID=$(cat $PIDFILE) echo "Stopping ..." su - $USER -c "$REDIS_CLI -p $REDISPORT -a $SECURE SHUTDOWN" while [ -x ${PIDFILE} ] do echo "Waiting for Redis to shutdown ..." sleep 1 done echo "Redis stopped" fi ;; restart|force-reload) ${0} stop ${0} start ;; *) echo "Usage: /etc/init.d/redis {start|stop|restart|force-reload}" >&2 exit 1 esac

    Ubuntu16.04下的/etc/init.d/redis

    #!/bin/sh
    #
    ### BEGIN INIT INFO
    # Provides:          redis
    # Required-Start:    $remote_fs $syslog
    # Required-Stop:     $remote_fs $syslog
    # Should-Start:      $network $time
    # Should-Stop:       $network $time
    # Default-Start:     2 3 4 5
    # Default-Stop:      0 1 6
    # Short-Description: Start/ Stop Redis Server daemon
    # Description:       This service script facilitates startup and shutdown of
    #                    redis daemon
    ### END INIT INFO
    #
    # Simple Redis init.d script conceived to work on Linux systems
    # as it does use of the /proc filesystem.
    
    REDISPORT=6034
    EXEC=/opt/redis/redis-4.0.2/bin/redis-server
    CLIEXEC=/opt/redis/redis-4.0.2/bin/redis-cli
    
    PIDFILE=/var/run/redis_${REDISPORT}.pid
    CONF="/opt/redis/redis-4.0.2/conf/${REDISPORT}.conf"
    SECURE=biggbang
    
    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 -a $SECURE shutdown
                    while [ -x /proc/${PID} ]
                    do
                        echo "Waiting for Redis to shutdown ..."
                        sleep 1
                    done
                    echo "Redis stopped"
            fi
            ;;
        *)
            echo "Please use start or stop as first argument"
            ;;
    esac

    添加入ubuntu的系统服务:

    sudo update-rc.d redis defaults 
    # 如果需要删除则使用
    sudo update-rc.d redis remove

    加入服务后, 可以用 start, stop, status 查看服务状态

    Redis Cluster 集群的配置

    Redis集群支持多节点数据集自动分片, 提供一定程度的分区可用性, 部分节点挂掉或者无法连接其他节点后, 服务可以正常运行.
    集群中的每个Redis节点需要2个TCP连接端口,如6379端口用于Client连接,16379端口用于集群数据通信.

    集群的实现机制
    集群采用Hash Slot方案, 而不是一致性哈希. Redis使用的是16384个Hash slot (16x32x32, 即2的14次方, 214). 每个key通过CRC16校验后对16384取模来决定放置哪个slot. 集群的每个节点负责一部分hash slot.  如果有3台机器, 那么Node A 负责 0-5500, Node B 负责 5501-11000, Node C 负责 11001-16384. 这种设计下, 添加, 删除新Node比较方便. 例如:

    添加新节点D, 只需移动A, B, C上的slot到节点D即可.
    移除节点A, 将A上的slot迁移到B和C即可

    由于Hash slot在节点间的迁移无需停止操作, 集群新增或者删除节点, 改变集群内部节点占用的Slot比例等都可在线完成. 

    Redis Cluster Master-Slave Model
    为保证某些节点挂掉或无法连接其他节点的情况下可正常提供服务,Redis Cluster提供了主从模式的数据副本机制,每个Hash Slot都可以设置1-N个从节点。
    由A,B,C三节点组成的集群中,可以设置A1,B1,C1分别为A,B,C的从节点,如B挂掉后,原B1从节点被提升为主节点,从而保证集群服务正常。

    集群在一致性方面的问题, 可能存在写数据丢失情况发生, 如:
    - Client写入数据到NodeA
    - NodeA答复Client写入成功
    - NodeA在写入从节点A1时蹦溃掉了
    - A1被提升为Master节点后,但是数据丢失

    为解决这个问题,Redis集群提供了同步写支持

    集群配置参数
    所有的集群配置参数都存在于redis.conf中,主要几个如下:

    Cluster-enabled:是否开启集群模式
    Cluster-config-file:集群配置变更后会自动写入改文件
    Cluster-node-timeout:节点超时时间,超过该时间无法连接主要Master节点后,会停止接受查询服务
    Cluster-slave-validity-factor:控制从节点FailOver相关的设置. 设为0, 从节点会一直尝试启动FailOver;设为正数, 则失联大于一定时间(factor*节点TimeOut)后不再进行FailOver
    Cluster-migration-barrier:最小从节点连接数
    Cluster-require-full-coverage:默认为Yes, 丢失一定比例Key后(可能Node无法连接或者挂掉)集群停止接受写操作; 设置为No, 集群丢失Key的情况下仍提供查询服务

    搭建方式一

    集群环境至少需要3个节点, 推荐使用6个节点配置, 即3个主节点3个从节点, 首先启动6个独立Redis节点, 然后进行集群关联配置,

    最小化的Redis配置文件, 实际使用中, 需要指定不同的数据文件名和日志文件名

    port 7000
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    appendonly yes

    创建6个空的文件夹

    mkdir cluster-test  
    cd cluster-test  
    mkdir 7000 7001 7002 7003 7004 7005

    分别创建配置文件并启动6个单点服务

    cd 7000
    ../redis-server ./redis.conf

    启动后会看到以下日志信息,提示Node.conf不存在,并且每个节点创建了一个NodeID

    [82462] 26 Nov 11:56:55.329 * No cluster configuration found, I'm 97a3a64667477371c4479320d683e4c8db5858b1

    组建集群配置
    源码src文件下提供了一个叫做redis-trib.rb的脚本文件,是一个Ruby脚本用于创建集群,检测及重新分片等

    ./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
    # create表示创建一个新的集群
    # replicas 1表示指定集群中每个节点的副本个数为1  

    出现以下消息,表示只有一个主节点完成了HashSlot的初始化并可以提供服务

    [OK] All 16384 slots covered  


    搭建方式二
    使用Create-Cluster脚本, 脚本位于utils/create-cluster目录西,执行以下命令

    create-cluster start
    create-cluster create

    启动后默认第一个节点端口为30001,完成后执行以下命令  

    create-cluster stop

    验证集群是否搭建成功

    $ redis-cli -c -p 7000
    redis 127.0.0.1:7000> set foo bar
    -> Redirected to slot [12182] located at 127.0.0.1:7002
    OK
    redis 127.0.0.1:7002> set hello world
    -> Redirected to slot [866] located at 127.0.0.1:7000
    OK
    redis 127.0.0.1:7000> get foo
    -> Redirected to slot [12182] located at 127.0.0.1:7002
    "bar"
    redis 127.0.0.1:7000> get hello
    -> Redirected to slot [866] located at 127.0.0.1:7000
    "world"

    对Redis Cluster的操作

    添加一个新的主节点 Adding a new node

    添加一个新节点基本上就是添加一个空节点, 然后将一些数据移动到其中, 在这种情况下它是一个新的master. 或者你明确的设置它作为副本, 那么这种情况下它就是一个slave. 

    [root@ecs-d6b3-0002 cluster-test]# cp -R 7005 7006
    [root@ecs-d6b3-0002 cluster-test]# vi 7006/redis.conf
    [root@ecs-d6b3-0002 cluster-test]# cd 7006
    [root@ecs-d6b3-0002 7006]# ../redis-server redis.conf
    # 用redis-trib来添加一个节点到已存在的集群
    ./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000

    第一个地址是新节点地址, 第二个地址是集群中任意节点地址.

    添加一个新的从节点 Adding a new node as a replica

    ./redis-trib.rb add-node --slave 127.0.0.1:7006 127.0.0.1:7000

    删除一个节点Removing a node

    ./redis-trib del-node 127.0.0.1:7000 `<node-id>`
    ./redis-trib.rb del-node 127.0.0.1:7006 7c7b7f68bc56bf24cbb36b599d2e2d97b26c5540

    重新分片(Resharding the cluster)

    ./redis-trib.rb reshard 127.0.0.1:7000
    # --from 的参数是node id, 可以有多个, 用逗号隔开, 也可以是all; --to 目的节点的node id, 只能填一个
    ./redis-trib.rb reshard --from <node-id> --to <node-id> --slots <number of slots> --yes <host>:<port>

    在删除节点前, 必须通过reshard将节点数据清空, 执行上面的第一条命令, 会进入交互式的命令行操作, 第二个是直接执行的命令格式, 下面是一个执行的命令行记录

    $ruby redis-trib.rb reshard --from all --to 80b661ecca260c89e3d8ea9b98f77edaeef43dcd --slots 11 10.180.157.199:6379
    >>> Performing Cluster Check (using node 10.180.157.199:6379)
    S: b2506515b38e6bbd3034d540599f4cd2a5279ad1 10.180.157.199:6379
       slots: (0 slots) slave
       replicates 460b3a11e296aafb2615043291b7dd98274bb351
    S: d376aaf80de0e01dde1f8cd4647d5ac3317a8641 10.180.157.205:6379
       slots: (0 slots) slave
       replicates e36c46dbe90960f30861af00786d4c2064e63df2
    M: 15126fb33796c2c26ea89e553418946f7443d5a5 10.180.157.201:6379
       slots:10923-16383 (5461 slots) master
       1 additional replica(s)
    S: 59fa6ee455f58a5076f6d6f83ddd74161fd7fb55 10.180.157.208:6379
       slots: (0 slots) slave
       replicates 15126fb33796c2c26ea89e553418946f7443d5a5
    M: 460b3a11e296aafb2615043291b7dd98274bb351 10.180.157.202:6379
       slots:0-5460 (5461 slots) master
       1 additional replica(s)
    M: 80b661ecca260c89e3d8ea9b98f77edaeef43dcd 10.180.157.200:6380
       slots: (0 slots) master
       0 additional replica(s)
    M: e36c46dbe90960f30861af00786d4c2064e63df2 10.180.157.200:6379
       slots:5461-10922 (5462 slots) master
       1 additional replica(s)
    [OK] All nodes agree about slots configuration.
    >>> Check for open slots...
    >>> Check slots coverage...
    [OK] All 16384 slots covered.
    
    Ready to move 11 slots.
      Source nodes:
        M: 15126fb33796c2c26ea89e553418946f7443d5a5 10.180.157.201:6379
       slots:10923-16383 (5461 slots) master
       1 additional replica(s)
        M: 460b3a11e296aafb2615043291b7dd98274bb351 10.180.157.202:6379
       slots:0-5460 (5461 slots) master
       1 additional replica(s)
        M: e36c46dbe90960f30861af00786d4c2064e63df2 10.180.157.200:6379
       slots:5461-10922 (5462 slots) master
       1 additional replica(s)
      Destination node:
        M: 80b661ecca260c89e3d8ea9b98f77edaeef43dcd 10.180.157.200:6380
       slots: (0 slots) master
       0 additional replica(s)
      Resharding plan:
        Moving slot 5461 from e36c46dbe90960f30861af00786d4c2064e63df2
        Moving slot 5462 from e36c46dbe90960f30861af00786d4c2064e63df2
        Moving slot 5463 from e36c46dbe90960f30861af00786d4c2064e63df2
        Moving slot 5464 from e36c46dbe90960f30861af00786d4c2064e63df2
        Moving slot 0 from 460b3a11e296aafb2615043291b7dd98274bb351
        Moving slot 1 from 460b3a11e296aafb2615043291b7dd98274bb351
        Moving slot 2 from 460b3a11e296aafb2615043291b7dd98274bb351
        Moving slot 10923 from 15126fb33796c2c26ea89e553418946f7443d5a5
        Moving slot 10924 from 15126fb33796c2c26ea89e553418946f7443d5a5
        Moving slot 10925 from 15126fb33796c2c26ea89e553418946f7443d5a5
    Do you want to proceed with the proposed reshard plan (yes/no)? yes
    Moving slot 5461 from 10.180.157.200:6379 to 10.180.157.200:6380:
    Moving slot 5462 from 10.180.157.200:6379 to 10.180.157.200:6380:
    Moving slot 5463 from 10.180.157.200:6379 to 10.180.157.200:6380:
    Moving slot 5464 from 10.180.157.200:6379 to 10.180.157.200:6380:
    Moving slot 0 from 10.180.157.202:6379 to 10.180.157.200:6380:
    Moving slot 1 from 10.180.157.202:6379 to 10.180.157.200:6380:
    Moving slot 2 from 10.180.157.202:6379 to 10.180.157.200:6380:
    Moving slot 10923 from 10.180.157.201:6379 to 10.180.157.200:6380:
    Moving slot 10924 from 10.180.157.201:6379 to 10.180.157.200:6380:
    Moving slot 10925 from 10.180.157.201:6379 to 10.180.157.200:6380:

    使用Java连接Redis集群

    Jedis连接Redis集群

    JedisPoolConfig config = new JedisPoolConfig();
    config.setMaxTotal(20);
    config.setMaxIdle(2);
    
    # 可以只添加一两个主节点, 不必添加所有的节点 HostAndPort hp0 = new HostAndPort("localhost", 7000); HostAndPort hp1 = new HostAndPort("localhost", 7001); HostAndPort hp2 = new HostAndPort("localhost", 7002); HostAndPort hp3 = new HostAndPort("localhost", 7003); HostAndPort hp4 = new HostAndPort("localhost", 7004); HostAndPort hp5 = new HostAndPort("localhost", 7005); Set<HostAndPort> hps = new HashSet<HostAndPort>(); hps.add(hp0); hps.add(hp1); hps.add(hp2); hps.add(hp3); hps.add(hp4); hps.add(hp5); JedisCluster jedisCluster = new JedisCluster(hps, 5000, 10, config); long start = System.currentTimeMillis(); for (int i = 0; i < 100; i++) { jedisCluster.set("sn" + i, "n" + i); } long end = System.currentTimeMillis(); System.out.println("Time : " + (end - start) / 10000); for (int i = 0; i < 1000; i++) { System.out.println(jedisCluster.get("sn" + i)); } jedisCluster.close();
  • 相关阅读:
    Kaldi的data目录解析
    Kaldi的nnet3
    Kaldi中的Chain模型
    Karel版本的nnet1
    Dan版本的nnet2
    MFCC/Filter Bank的提取流程
    【算法专题】工欲善其事必先利其器—— C++ STL中vector(向量/不定长数组)的常用方法总结
    App 设计技巧
    js判断是否在微信浏览器中打开
    WebApi 跨域
  • 原文地址:https://www.cnblogs.com/milton/p/5042184.html
Copyright © 2011-2022 走看看