一、redis的安装
redis是一个key-value的缓存工具,3.0后的版本可以搭建集群,作用强大,像新浪微博就在用redis做缓存,下面介绍redis3.0的安装步骤:
1、下载redis的源码包
2、解压源码包
tar -zxvf redis-3.2.3.tar.gz
3、安装
cd redis-3.2.3
make
make install PREFIX=/usr/local/redis
表示把redis安装在/usr/local/redis路径下
4、启动redis
(1)前端启动模式(一般不用)
cd /usr/local/redis/bin
./redis-server
(1)后端启动模式(推荐)
- 从redis的源码目录(redis3.2.3)中复制redis.conf到redis的安装目录(/usr/local/redis/bin)
- 修改配置文件 daemonize 改为yes
- 后端启动redis
./redis-server redis.conf- 查看redis的运行端口
ps aux|grep redis
redis默认是运行在6379端口,如果查看到6379端口是redis占用,则说明redis启动成功
二、redis的常用命令和数据结构
常用数据类型
String
Hash
List
Set
SortedSet
Redis常用命令
首先进入redis的端口命令:
cd /usr/local/redis/bin
./redis-cli
在redis端口上执行命令:
127.0.0.1:6379> set a 10 设置一个key
OK
127.0.0.1:6379> get a 获取一个key
“10”
127.0.0.1:6379> incr a 自增
127.0.0.1:6379> decr a 自减
127.0.0.1:6379> del a 删除一个key
127.0.0.1:6379> keys * 获取所有key
127.0.0.1:6379> expire key 1000 设置key的过期时间为1000
127.0.0.1:6379> ttl key 查看key的过期时间
三、Redis集群概念和搭建
1. redis-cluster架构图
redis-cluster把所有的物理节点映射到 [0-16383] slot(槽)上,cluster 负责维护node<->slot<->value
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点
例如:
上图中把槽分在了四个redis-server上,对于下面两个值:
Key:a
使用上面所说的算法,计算a的hash值,例如值为100,100这个槽在server1上,所以a应该放到server1.
Key:hello
Hash值:10032,此槽在server2上。Hello应该存在server2
服务器性能比较好的Server,可以分配多一点的槽,用于存放更多的key
2. redis-cluster投票:容错
(1)领着投票过程
集群中所有master参与,如果半数以上master节点与master节点通信超过(cluster-node-timeout),认为当前master节点挂掉
(2)什么时候整个集群不可用(cluster_state:fail)?
如果集群任意master挂掉,且当前master没有slave(备份集群).集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完成时进入fail状态. ps : redis-3.0.0.rc1加入cluster-require-full-coverage参数,默认关闭,打开集群兼容部分失败.
如果集群超过半数以上master挂掉,无论是否有slave集群进入fail状态.
ps:当集群不可用时,所有对集群的操作做都不可用,收到((error) CLUSTERDOWN The cluster is down)错误
3. 搭建redis集群
1. 安装ruby
yum install ruby
yum install rubygems
在源码包内,redis-trib.rb是redis集群管理工具
2. 安装redis-ruby接口
gem install redis-3.0.0.gem
3. 集群搭建(搭建6个实例的redis集群)
第一步:创建6个redis实例,端口号从7001~7006
- 把usr/local中创建目录redis-cluster
- 把usr/local/redis下的bin拷贝到redis-cluster中的redis01中
- 在redis-cluster复制redis01 5份,分别为01,02,03,04,05,06
第二步:修改redis01-redis06的redis.conf配置文件
修改端口号
redis01:7001
redis02:7002
redis03:7003
redis04:7004
redis05:7005
redis06:7006
打开cluster-enable前面的注释(vim中,可以通过底线模式/cluster-enable搜索)
第三步:把创建集群的ruby脚本redis-trib.rb复制到redis-cluster目录下
第四步:启动6个redis实例
创建startall.sh文件,执行文件,一次性打开全部redis
可以看到:7001-7006的redis实例都打开了
第五步:创建集群
[root@localhost redis-cluster]# ./redis-trib.rb create –replicas 1 192.168.172.129:7001 192.168.172.129:7002 192.168.172.129:7003 192.168.172.129:7004 192.168.172.129:7005 192.168.172.129:7006
创建过程的日志:
[root@localhost redis-cluster]# ./redis-trib.rb create –replicas 1 192.168.172.129:7001 192.168.172.129:7002 192.168.172.129:7003 192.168.172.129:7004 192.168.172.129:7005 192.168.172.129:7006
Creating cluster
Connecting to node 192.168.172.129:7001: OK
Connecting to node 192.168.172.129:7002: OK
Connecting to node 192.168.172.129:7003: OK
Connecting to node 192.168.172.129:7004: OK
Connecting to node 192.168.172.129:7005: OK
Connecting to node 192.168.172.129:7006: OK
Performing hash slots allocation on 6 nodes…
Using 3 masters:
192.168.172.129:7001
192.168.172.129:7002
192.168.172.129:7003
Adding replica 192.168.172.129:7004 to 192.168.172.129:7001
Adding replica 192.168.172.129:7005 to 192.168.172.129:7002
Adding replica 192.168.172.129:7006 to 192.168.172.129:7003
M: 7173445e703f00577bdcf09ab84aff73f289afcc 192.168.172.129:7001
slots:0-5460 (5461 slots) master
M: 4a838fbc3ec9def285d9e0984f4530ce1d27d31f 192.168.172.129:7002
slots:5461-10922 (5462 slots) master
M: e805eaee8324884cbc32bd31442ef890fc8000f0 192.168.172.129:7003
slots:10923-16383 (5461 slots) master
S: 14c27ed8835602c1cf77c548ae0847c85ca35b79 192.168.172.129:7004
replicates 7173445e703f00577bdcf09ab84aff73f289afcc
S: 0c8604f4ac89d0f783d7e6a01d88f00e17c2a733 192.168.172.129:7005
replicates 4a838fbc3ec9def285d9e0984f4530ce1d27d31f
S: dc8b4155a067c23f1b5269bdf269fd19f42bdc61 192.168.172.129:7006
replicates e805eaee8324884cbc32bd31442ef890fc8000f0
Can I set the above configuration? (type ‘yes’ to accept): yes
Nodes configuration updated
Assign a different config epoch to each node
Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join…..
Performing Cluster Check (using node 192.168.172.129:7001)
M: 7173445e703f00577bdcf09ab84aff73f289afcc 192.168.172.129:7001
slots:0-5460 (5461 slots) master
M: 4a838fbc3ec9def285d9e0984f4530ce1d27d31f 192.168.172.129:7002
slots:5461-10922 (5462 slots) master
M: e805eaee8324884cbc32bd31442ef890fc8000f0 192.168.172.129:7003
slots:10923-16383 (5461 slots) master
M: 14c27ed8835602c1cf77c548ae0847c85ca35b79 192.168.172.129:7004
slots: (0 slots) master
replicates 7173445e703f00577bdcf09ab84aff73f289afcc
M: 0c8604f4ac89d0f783d7e6a01d88f00e17c2a733 192.168.172.129:7005
slots: (0 slots) master
replicates 4a838fbc3ec9def285d9e0984f4530ce1d27d31f
M: dc8b4155a067c23f1b5269bdf269fd19f42bdc61 192.168.172.129:7006
slots: (0 slots) master
replicates e805eaee8324884cbc32bd31442ef890fc8000f0
[OK] All nodes agree about slots configuration.
Check for open slots…
Check slots coverage…
[OK] All 16384 slots covered.
到这个时候,集群就已经搭建完成
4. 测试集群
redis01/redis-cli -h 192.168.172.129 -p 7001 –c (-c代表使用集群,一定要带上)
从上图看到,进入7001端口的redis,设置一个值a = 100,然而取该值得时候是从7003取出,这是由redis集群做的事情
5. 关闭集群
./redis-cli -p 7001 shutdown
./redis-cli -p 7002 shutdown
./redis-cli -p 7003 shutdown
./redis-cli -p 7004 shutdown
./redis-cli -p 7005 shutdown
./redis-cli -p 7006 shutdown
四、用Redis Desktop Manager连接redis
刚开始连接时,无法连接
这是我第一时间想到,CentOS默认开启防火墙,可能是端口没打开,所以导致链接不上,于是把端口打开:
vim /etc/sysconfig/iptables
加上打开6379 和 7001:7006端口规则,或者直接关闭防火墙:
service iptables stop
然而关闭了防火墙,还是无法访问到该端口,这时我又想到可能是Selinux作怪,于是我连Selinux也关闭了
vim /etc/selinux/config
在 SELINUX=enforcing 前面加个#号注释掉它
然后新加一行
SELINUX=disabled
关闭了iptables和Selinux之后,这时还是无法连接到redis,这时我注意到auth身份认证问题,找了资料发现,redis是默认保护模式,只能本虚拟机访问,不允许其他ip访问,所以可以这么做:
- 注释redis.conf文件中的:bind 127.0.0.1(在一段文字之前打#号为注释)
- 在redis.conf中添加 requirepass 123,表示连接密码为123
这时便连接成功了
五、使用Jedis操作Redis
使用的是jedis-2.7.2.jar,并通过Maven添加依赖:
1. 单机版Redis
public class TestJedis {
@Test
public void testJedisSingle() {
//创建一个jedis的对象。
Jedis jedis = new Jedis("192.168.25.153", 6379);
//调用jedis对象的方法,方法名称和redis的命令一致。
jedis.set("key1", "jedis test");
String string = jedis.get("key1");
System.out.println(string);
//关闭jedis。
jedis.close();
}
/**
* 使用连接池
*/
@Test
public void testJedisPool() {
//创建jedis连接池
JedisPool pool = new JedisPool("192.168.172.129", 6379);
//从连接池中获得Jedis对象
Jedis jedis = pool.getResource();
String string = jedis.get("key1");
System.out.println(string);
//关闭jedis对象
jedis.close();
pool.close();
}
}
2. 集群版Redis
public void testJedisCluster() {
HashSet<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("192.168.172.129", 7001));
nodes.add(new HostAndPort("192.168.172.129", 7002));
nodes.add(new HostAndPort("192.168.172.129", 7003));
nodes.add(new HostAndPort("192.168.172.129", 7004));
nodes.add(new HostAndPort("192.168.172.129", 7005));
nodes.add(new HostAndPort("192.168.172.129", 7006));
JedisCluster cluster = new JedisCluster(nodes);
cluster.set("key1", "1000");
String string = cluster.get("key1");
System.out.println(string);
cluster.close();
}
六、Spring整合Redis
1. 单机版整合
<!-- 连接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最大连接数 -->
<property name="maxTotal" value="30" />
<!-- 最大空闲连接数 -->
<property name="maxIdle" value="10" />
<!-- 每次释放连接的最大数目 -->
<property name="numTestsPerEvictionRun" value="1024" />
<!-- 释放连接的扫描间隔(毫秒) -->
<property name="timeBetweenEvictionRunsMillis" value="30000" />
<!-- 连接最小空闲时间 -->
<property name="minEvictableIdleTimeMillis" value="1800000" />
<!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
<property name="softMinEvictableIdleTimeMillis" value="10000" />
<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
<property name="maxWaitMillis" value="1500" />
<!-- 在获取连接的时候检查有效性, 默认false -->
<property name="testOnBorrow" value="true" />
<!-- 在空闲时检查有效性, 默认false -->
<property name="testWhileIdle" value="true" />
<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
<property name="blockWhenExhausted" value="false" />
</bean>
<!-- jedis客户端单机版 -->
<bean id="redisClient" class="redis.clients.jedis.JedisPool">
<constructor-arg name="host" value="192.168.172.129"></constructor-arg>
<constructor-arg name="port" value="6379"></constructor-arg>
<constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
</bean>
2. 集群版整合
<!-- 连接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最大连接数 -->
<property name="maxTotal" value="30" />
<!-- 最大空闲连接数 -->
<property name="maxIdle" value="10" />
<!-- 每次释放连接的最大数目 -->
<property name="numTestsPerEvictionRun" value="1024" />
<!-- 释放连接的扫描间隔(毫秒) -->
<property name="timeBetweenEvictionRunsMillis" value="30000" />
<!-- 连接最小空闲时间 -->
<property name="minEvictableIdleTimeMillis" value="1800000" />
<!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
<property name="softMinEvictableIdleTimeMillis" value="10000" />
<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
<property name="maxWaitMillis" value="1500" />
<!-- 在获取连接的时候检查有效性, 默认false -->
<property name="testOnBorrow" value="true" />
<!-- 在空闲时检查有效性, 默认false -->
<property name="testWhileIdle" value="true" />
<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
<property name="blockWhenExhausted" value="false" />
</bean>
<bean id="redisCluster" class="redis.clients.jedis.JedisCluster">
<constructor-arg name="nodes">
<set>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.172.129"></constructor-arg>
<constructor-arg name="port" value="7001"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.172.129"></constructor-arg>
<constructor-arg name="port" value="7002"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.172.129"></constructor-arg>
<constructor-arg name="port" value="7003"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.172.129"></constructor-arg>
<constructor-arg name="port" value="7004"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.172.129"></constructor-arg>
<constructor-arg name="port" value="7005"></constructor-arg>
</bean>
<bean class="redis.clients.jedis.HostAndPort">
<constructor-arg name="host" value="192.168.172.129"></constructor-arg>
<constructor-arg name="port" value="7006"></constructor-arg>
</bean>
</set>
</constructor-arg>
<constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
</bean>