先确认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了,redis只有一个启动参数,就是他的配置文件路径。
redis-server /etc/redis.conf
目录下默认的redis.conf文件的daemonize参数为no,所以redis不会在后台运行。修改为yes则为后台运行redis。另外配置文件中规定了pid文件,log文件和数据文件的地址,如果有需要先修改,默认log信息定向到stdout.
下面是redis.conf的主要配置参数的意义:
为Redis建立用户和日志目录
useradd redis mkdir -p /var/lib/redis chown redis.redis /var/lib/redis
修改数据快照的保存目录,需要修改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/lib/redis
修改log文件位置
mkdir -p /var/log/redis chown redis.redis /var/log/redis # 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/log/redis/redislog
添加用户口令, 取消注释, 将 foobared 修改为32位以上的长字符串, 因为redis的效率, 短口令很容易被破解
# requirepass foobared
命令行测试
~]$./bin/redis-cli 127.0.0.1:6379> set foo bar OK 127.0.0.1:6379> get foo "bar" 127.0.0.1:6379> exit
用于添加服务的 /etc/init.d/redis
#!/bin/bash # # redis Start up the Redis server daemon # # chkconfig: 2345 55 25 # description: # # processname: redis # pidfile: /var/run/redis.pid PATH=/usr/local/bin:/sbin:/usr/bin:/bin REDISPORT=6379 EXEC=redis-server REDIS_CLI=redis-cli PIDFILE=/var/run/redis.pid CONF="/etc/redis.conf" 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 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 ..." $REDIS_CLI -p $REDISPORT 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
集群的配置
Redis Cluster
支持多节点数据集自动分片
提供一定程度的分区可用性,部分节点挂掉或者无法连接其他节点后,服务可以正常运行
集群中的每个Redis节点需要2个TCP连接端口,如6379端口用于Client连接,16379端口用于集群数据通信
集群采用Hash Slot方案,而不是一致性哈希,共16384个Hash slot。如果有3台机器,那么NodeA在0-5500,NodeB 在5501-11000,NodeC在11001-16384.这种设计下,添加,删除新Node比较方便。
例如添加新节点D,只需移动A,B,C上的slot到节点D即可。如需移除节点A,将A上的slot迁移到B和C即可。
由于HashSlot在节点间的迁移无需停止操作,集群新增或者删除节点,改变集群内部节点占用的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"
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();