Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。
Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、
set(集合)、zset(sorted set --有序集合)和hash(哈希类型即Map)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。
这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。
Redis 3.0的最重要特征是对Redis集群的支持,此外,该版本相对于2.8版本在性能、稳定性等方面都有了重大提高。
官网: http://redis.io 有安装说明。
官方下载地址: http://redis.io/download
安装redis:
#下载
$ wget http://download.redis.io/releases/redis-3.0.1.tar.gz
#解压,自己先拷贝到自己想放的地方
$ tar xzf redis-3.0.1.tar.gz
#到redis解压目录下去
$ cd redis-3.0.1
#编译
$ make
#到redis下src目录下去启动redis服务
$ src/redis-server
#启动客户端去操作
$ src/redis-cli
redis> set foo bar
OK
redis> get foo
"bar"
#测试成功
官网集群说明参考: http://redis.io/topics/cluster-tutorial
http://redis.io/topics/cluster-tutorial
注意:redis2.x的版本不支持集群模式。
官网说明文档集群需要六个节点。要让集群正常工作至少需要3个主节点,在这里我们要创建6个redis节点,其中三个为主节点,三个为从节点。
详细说明:
cd software/
#创建目录
mkdir redis_cluster
cd redis_cluster/
#创建6个目录,在同一机器跑6个redis在不同端口
mkdir 7000 7001 7002 7003 7004 7005
#复制配置文件
cp /home/liang/software/redis-3.0.1/src/redis.conf ../redis_cluster/
每个目录放一个redis.conf,以7000目录为例
port 7000 每个目录名作为一个端口
vim redis.conf
port 7000
daemonize yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize yes 是否以后台方式运行, 默认daemonize参数为no,所以redis不会在后台运行,退出终端,则会退出redis服务,这时要测试,我们需要重新开一个终端
修改完redis.conf配置文件中的这些配置项之后,把这个配置文件分别拷贝到7000/ 7001/ 7002/ 7003/ 7004/ 7005/目录下面
注意:拷贝完成之后要修改7001/7002/7003/7004/7005目录下面redis.conf文件中的port端口参数,分别改为对应的文件夹的名称
cp redis.conf 7000/
cp redis.conf 7001/
cp redis.conf 7002/
cp redis.conf 7003/
cp redis.conf 7004/
cp redis.conf 7005/
启动 分别进入每一个目录启动redis
cd 7000/
../../redis-3.0.1/src/redis-server redis.conf
cd ../7001/
../../redis-3.0.1/src/redis-server redis.conf
......
cd ../7005/
../../redis-3.0.1/src/redis-server redis.conf
启动之后使用命令查看redis的启动情况
ps -ef|grep redis
创建集群:默认前三台为主节点,后三台为从节点.
选项 --replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
注意:这里最好使用ip地址,不要用127.0.0.1(因为用远程环境其他服务器,远程连接时会出现问题,本机使用客户端./redis-cli -h 172.17.20.16 -c -p 7000 连接后获取数据自动跳到127.0.0.1:7000,就是因为创建集群时使用的是127.0.0.1的原因,而且使用java项目连接时会报错误:Too many Cluster redirections)
./redis-trib.rb create --replicas 1 172.17.20.16:7000 172.17.20.16:7001 172.17.20.16:7002 172.17.20.16:7003 172.17.20.16:7004 172.17.20.16:7005
执行上面的命令的时候可能会报错,创建集群需要一些环境:根据提示一个一个的安装。
执行的是ruby的脚本,需要ruby的环境。提示缺少rubygems组件。不能加载redis,是因为缺少redis和ruby的接口。
sudo gem install redis
因为国内的网络限制,要或着手动下载安装。
sudo apt-get install ruby
sudo apt-get install rubygems
sudo gem install redis
环境安装好,再次执行创建命令,正常执行,输入yes 创建成功
#检查集群有没有成功
./redis-trib.rb check 172.17.20.16:7000
#客户端连接,注意-c参数,查找时不在本端口,会自动切换到有数据的那个端口下查询。
redis-cli -c -p 7000
127.0.0.1:7000> cluster nodes
7a6121a5d8c87fc5345f6812e41c83f5163f2db6 127.0.0.1:7002 master - 0 1458546962094 3 connected 10923-16383
9939a801cf27710cd3ecbcde33b0f1d15b4af834 127.0.0.1:7000 myself,master - 0 0 1 connected 0-5460
1e60c2a340fc70a812392f098eec97c20557954b 127.0.0.1:7001 master - 0 1458546961593 2 connected 5461-10922
4af9487baf21d763d7872436677af3404ba5dccd 127.0.0.1:7004 slave 1e60c2a340fc70a812392f098eec97c20557954b 0 1458546961092 5 connected
011d4c450f6f21d05ed655f6b57020ad284e9cf8 127.0.0.1:7003 slave 9939a801cf27710cd3ecbcde33b0f1d15b4af834 0 1458546960592 4 connected
e6a251b28ad454dbea3bd972cb7d128403c0415e 127.0.0.1:7005 slave 7a6121a5d8c87fc5345f6812e41c83f5163f2db6 0 1458546961593 6 connected
#用于查看当前Redis节点 所属的Redis集群中的所有节点。
#master表示主节点,slave表示从节点,slave后的id对应主节点的id。myself表示在当前那一台。
#查看当前的集群状态,以数组形式展示。
127.0.0.1:7000> cluster slots
1) 1) (integer) 10923
2) (integer) 16383
3) 1) "127.0.0.1"
2) (integer) 7002
4) 1) "127.0.0.1"
2) (integer) 7005
2) 1) (integer) 0
2) (integer) 5460
3) 1) "127.0.0.1"
2) (integer) 7000
4) 1) "127.0.0.1"
2) (integer) 7003
3) 1) (integer) 5461
2) (integer) 10922
3) 1) "127.0.0.1"
2) (integer) 7001
4) 1) "127.0.0.1"
2) (integer) 7004
#用于查看当前Redis节点所属的Redis集群的整体状态。
127.0.0.1:7000> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:7
cluster_my_epoch:3
cluster_stats_messages_sent:26914
cluster_stats_messages_received:26281
例:
#会自动保存到一个节点,并切换到对应节点 如:7001
set beyond "aaa"
#会自动去查找,找到返回数据并跳到对应端口下
get beyond
#没有找到返回(nil)
get abc
从上面知道:7001是主,7004是从,我把7001停止后,在查找beyond数据仍然能找到(这时7004是主节点了),7004也停止后,则找不到beyond数据了。
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
<version>2.7.0version>
dependency>
package com.beyond;
import java.util.HashSet;
import java.util.Set;
import org.junit.Test;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
public class TestJedisCluster{
private static JedisCluster jc;
static {
//只给集群里一个实例就可以
Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7000));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7001));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7002));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7003));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7004));
jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7005));
jc = new JedisCluster(jedisClusterNodes);
}
@Test
public void testredis() {
//jc.set("foo", "bar");
String value = jc.get("foo");
System.out.println(value);
System.out.println(jc.get("beyond"));
}
}
Maven pom.xml配置
<dependency>
<groupId>org.springframework.datagroupId>
<artifactId>spring-data-redisartifactId>
<version>1.7.1.RELEASEversion>
dependency>
spring xml配置
<bean id="clusterRedisNodes0" class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg value="127.0.0.1" />
<constructor-arg value="7000" type="int" />
bean>
<bean id="clusterRedisNodes1" class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg value="127.0.0.1" />
<constructor-arg value="7001" type="int" />
bean>
..............
<bean id="clusterRedisNodes5" class="org.springframework.data.redis.connection.RedisNode">
<constructor-arg value="127.0.0.1" />
<constructor-arg value="7005" type="int" />
bean>
<bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
<property name="clusterNodes">
<set>
<ref bean="clusterRedisNodes0"/>
................
<ref bean="clusterRedisNodes5"/>
set>
property>
bean>
<bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:use-pool="true">
<constructor-arg ref="redisClusterConfiguration" />
bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnFactory" >
<property name="keySerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
property>
<property name="valueSerializer">
<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
property>
bean>
java 代码中使用
@Resource
private RedisTemplate<String, String> redisTemplate;
redisTemplate.opsForValue().set("test", "test");
当集群的redis内存不够用时,需要新增加节点
新增加一台7006,配置与上面的一样,启动后,执行下面命令加入集群
#在集群中新增加一台节点,默认为主节点
./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000
#也可以让它成为从节点,7fec61c9df3e7d739916d63a5d1172a23d169c72(需要做为它的从节点的节点ID)
127.0.0.1:7006>cluster replicate 7fec61c9df3e7d739916d63a5d1172a23d169c72
新增加的节点是无法使用的,因为哈希槽为0,需要分片分配哈希槽(看特别说明)
./redis-trib.rb reshard 127.0.0.1:7000
How many slots do you want to move (from 1 to 16384)? 4096
需要输入分给7006的哈希槽区间,这里我们4个主节点平均分配就是4096
What is the receiving node ID? 0d1f9c979684e0bffc8230c7bb6c7c0d37d8a5a9(这个是移动到7006的id)
询问重新分片的源节点 即:要从哪个节点中取出 4096 个哈希槽, 并将这些槽移动到目标节点7006上面。
如果我们不打算从特定的节点上取出指定数量的哈希槽, 那么可以向 redis-trib 输入 all
Source node #1:all
输入 all 并按下回车之后, redis-trib 将打印出哈希槽的移动计划,
如果你觉得没问题的话, 就可以输入 yes 并再次按下回车
Do you want to proceed with the proposed reshard plan (yes/no)? yes
重新分片操作, 将指定的哈希槽从源节点一个个地移动到目标节点上面
数据也会跟着移动的
说明:Redis集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现:一个 Redis集群包含16384个哈希槽(hash slot), 数据库中的每个键都属于这16384个哈希槽的其中一个,集群使用公式CRC16(key)%16384来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。
集群中的每个节点负责处理一部分哈希槽。 举个例子,一个集群可以有三个哈希槽, 其中:
节点 A 负责处理 0 号至 5500 号哈希槽。
节点 B 负责处理 5501 号至 11000 号哈希槽。
节点 C 负责处理 11001 号至 16384 号哈希槽。
这种将哈希槽分布到不同节点的做法使得用户可以很容易地向集群中添加或者删除节点。 比如说:
如果用户将新节点 D 添加到集群中, 那么集群只需要将节点 A 、B 、 C 中的某些槽移动到节点 D 就可以了。
与此类似, 如果用户要从集群中移除节点 A , 那么集群只需要将节点 A 中的所有哈希槽移动到节点 B 和节点 C , 然后再移除空白(不包含任何哈希槽)的节点 A 就可以了。
因为将一个哈希槽从一个节点移动到另一个节点不会造成节点阻塞, 所以无论是添加新节点还是移除已存在节点, 又或者改变某个节点包含的哈希槽数量, 都不会造成集群下线。
注意:比如A B C是主节点,它们每台都有一个从节点。
当B出问题了,它的从节点会自动成为主节点,如果B主节点从节点都出问题了,B 负责处理 5501 号至 11000 号哈希槽就处理不了,整个集群就出问题了。
想移除B节点之前,先备份它的哈希槽到其他节点之后在移除。
从服务器20.16 直接插入120万到 redis服务器 20.18
test1 redis1200000总的时间:264s
从服务器20.16 开三线程执行120万到 redis服务器 20.18
test2 redis的时间:94s
test2 redis的时间:94s
test2 redis的时间:94s
从服务器20.13 直接插入120万到 redis服务器 20.16 集群
test1 redis1200000总的时间:309s
从服务器20.13 开三线程执行120万到 redis服务器 20.16 集群
test2 redis的时间:109s
test2 redis的时间:109s
test2 redis的时间:109s
redis安装,命令,集群,伪集群等相关详细资料请查看:网盘里Af目录下redis资料。