Redis特性
多数据库
Redis 内部自带有16个数据库,序号分别从0 - 15 。 默认我们操作的数据都是存放在 0 号数据库中
1. 切换数据库
select 1 选择1号数据库
2. 迁移数据到指定数据库
move key 1 从当前数据库中迁移 key到 1号数据库
如 : move myset 1
消息订阅&发布
订阅&发布需要多个客户端协同工作。 由A客户端订阅 指定频道消息、由B客户端发布 指定频道的消息 。 一般会在网络聊天室中出现、实际开发当中这个知识点比较少用到。
演示如下:
分别启动两个终端。
A终端使用:
subscribe cctv5 : 意思是 ,该终端在订阅频道名为 cctv5的消息。
当然也可以进行批量订阅:
subscribe cctv* 只要频道是以cctv 打头的都进行订阅。
B 终端使用
publish cctv5 'i love china...' 发布消息
一旦B终端发布消息,那么A终端就会收到消息。
事务
Redis的事务 与关系型数据库的事务还是有一点区别的。 虽然都是包含了一组操作逻辑,但是关系型数据库是 只要这一组中有一个小动作失败,那么组内的所有逻辑都以失败告终。
Redis的却是,如果有一个小动作失败了,那么剩下的动作依然可以继续往下执行。但是Redis的事务却可以保证Redis 的服务器在没有执行完事务中的所有逻辑,不会再为其他Redis的客户端服务。也就是确保了事务不会被打断或者执行到一半的时候,突然被别的客户端插进来执行。
演示如下:
set num 10
开启事务:
multi
执行逻辑1
incrby num 5
执行逻辑2
incrby num x
执行逻辑3
incrby num 10
提交事务
exec (等同于我们平常见到的 commit)
回滚事务:
discard
Redis持久化
Redis提供两种持久化方案 , 分别是 RDB 和 AOFRDB 快照 :
默认就支持的,无需配置。该机制是:在指定的时间间隔内将内存中的数据写入磁盘中。
设置持久化快照的条件
在redis.conf中修改持久化快照的条件,如下:
![03a6f2f6d8b025bcedc74c9d4a95d916.png](https://i-blog.csdnimg.cn/blog_migrate/8b6ef099a4bd4cfadaca8d3d61258744.jpeg)
![ecedf4e7cf4a58611c4af522dc09ad19.png](https://i-blog.csdnimg.cn/blog_migrate/861abec797183ad39fd94c34544ba8e5.jpeg)
在redis.conf中可以指定持久化文件存储的目录
![fe7c8bd9e46f2de25ecc4885ba815999.png](https://i-blog.csdnimg.cn/blog_migrate/30315b9be2e61591fd6c9c13947c5b2d.jpeg)
Rdb问题
一旦redis非法关闭,那么会丢失最后一次持久化之后的数据。
如果数据不重要,则不必要关心。
如果数据不能允许丢失,那么要使用aof方式。
AOF方式:
需要配置,该机制是: 以日志的方式记录服务器所处理的每一个动作。Redis服务器在启动的时候,会读取该文件来重新构建数据库,以保证启动后的数据库数据是完整的。
Redis默认是不使用该方式持久化的。Aof方式的持久化,是操作一次redis数据库,则将操作的记录存储到aof持久化文件中。
第一步:开启aof方式的持久化方案
将redis.conf中的appendonly改为yes,即开启aof方式的持久化方案。
![fd28997fd5d4ed61046d4a9e430a5ec5.png](https://i-blog.csdnimg.cn/blog_migrate/c2600489a78efd8884ab67e8a51a7da3.jpeg)
![6b3da559a20c45f5ded351d29854772e.png](https://i-blog.csdnimg.cn/blog_migrate/a883f5999d5caa63a36903acc5b69aba.jpeg)
Aof文件存储的目录和rdb方式的一样。
Aof文件存储的名称
![53bce2aecb9d462348971f0539d997dd.png](https://i-blog.csdnimg.cn/blog_migrate/a1373410f28ee6af56fae0e610ca2217.jpeg)
Redis的主从复制
持久化保证了即使redis服务重启也不会丢失数据,因为redis服务重启后会将硬盘上持久化的数据恢复到内存中,但是当redis服务器的硬盘损坏了可能会导致数据丢失,如果通过redis的主从复制机制就可以避免这种单点故障,如下图:
![675a06b428608dcca18af8ca11300dbe.png](https://i-blog.csdnimg.cn/blog_migrate/efcfd1e764bc971a0d352162ebde3ef1.jpeg)
说明:
- 主redis中的数据有两个副本(replication)即从redis1和从redis2,即使一台redis服务器宕机其它两台redis服务也可以继续提供服务。
- 主redis中的数据和从redis上的数据保持实时同步,当主redis写入数据时通过主从复制机制会复制到两个从redis服务上。
- 只有一个主redis,可以有多个从redis。
- 主从复制不会阻塞master,在同步数据时,master 可以继续处理client 请求
- 一个redis可以即是主又是从,如下图:
![1a0e4358e42bc574e17d4d8e2866dacd.png](https://i-blog.csdnimg.cn/blog_migrate/14db8ed91b67c840e21d026dcd1441aa.jpeg)
主从复制设置
主机配置
无需配置
从机配置
第一步:复制出一个从机
[root@itPX redis1]# cp bin/ bin2 –r
第二步:修改从机的redis.conf
语法:Slaveof masterip masterport
slaveof 192.168.242.137 6379
![0c75199b77e5f87c5c3a3f337f4b10a5.png](https://i-blog.csdnimg.cn/blog_migrate/37e935a49f6a28502225544556f67523.jpeg)
第三步:修改从机的port地址为6380
在redis.conf中修改
![4819b21e5d48605f2181ea52e1d8e42d.png](https://i-blog.csdnimg.cn/blog_migrate/7570f3b1348797bd934a78b1199e0778.jpeg)
第四步:清除从机中的持久化文件
[root@itPX bin2]# rm -rf appendonly.aof dump.rdb
第五步:启动从机
[root@itPX bin2]# ./redis-server redis.conf
第六步:启动6380的客户端
[root@itPX bin2]# ./redis-cli -p 6380
注意:
主机一旦发生增删改操作,那么从机会将数据同步到从机中
从机不能执行写操作
127.0.0.1:6380> set s2 222
(error) READONLY You can't write against a read only slave.
Redis集群
redis-cluster架构图
![122e5aa76d61f3f3c6e2abd97a9092d7.png](https://i-blog.csdnimg.cn/blog_migrate/f0c4d5eaf8306e11e163ca83c6349c89.jpeg)
架构细节:
- 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
- 节点的fail是通过集群中超过半数的节点检测失效时才生效.
- 客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
- redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护nodeslotvalue
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点
redis-cluster投票:容错
![4086141d8c1ca6706d4abd85327754b3.png](https://i-blog.csdnimg.cn/blog_migrate/ade3f9d769cdea838e525ee3b4e1862e.jpeg)
集群中所有master参与投票,如果半数以上master节点与其中一个master节点通信超时(cluster-node-timeout),认为该master节点挂掉.
如果集群任意master挂掉,且当前master没有slave,则集群进入fail状态。也可以理解成集群的[0-16383]slot映射不完全时进入fail状态。
如果集群超过半数以上master挂掉,无论是否有slave,集群进入fail状态。
搭建集群
安装ruby
集群管理工具(redis-trib.rb)是使用ruby脚本语言编写的。
第一步:安装ruby
[root@itPX bin2]# yum install ruby
[root@itPX bin2]# yum install rubygems
第二步:将redis-3.0.0.gem文件上传到linux系统
第三步:安装ruby和redis接口
[root@itPX ~]# gem install redis-3.0.0.gem
第四步:将redis-3.0.0包下src目录中的以下文件拷贝到redis19/redis-cluster/
[root@itPX src]# cd /usr/local/redis19/
[root@itPX redis19]# mkdir redis-cluster
[root@itPX redis19]# cd /root/redis-3.0.0/src/
[root@itPX src]# cp redis-trib.rb /usr/local/redis19/redis-cluster
第五步:查看是否拷贝成功
搭建集群最少也得需要3台主机,如果每台主机再配置一台从机的话,则最少需要6台机器。
端口设计如下:7001-7006
第一步:复制出一个7001机器
[root@itPX redis19]# cp bin ./redis-cluster/7001 –r
第二步:如果存在持久化文件,则删除
[root@itPX 7001]# rm -rf appendonly.aof dump.rdb
第三步:设置集群参数
![142d90e62a4d7f4cb20293089afc1d7f.png](https://i-blog.csdnimg.cn/blog_migrate/a1fccdcaacff442f77846acd60f830fe.jpeg)
第四步:修改端口
![e4ae5d1b1fe0d8190118606b4e13e1fa.png](https://i-blog.csdnimg.cn/blog_migrate/d574f30b59aa535a759a72cabc11e061.jpeg)
第五步:复制出7002-7006机器
[root@itPX redis-cluster]# cp 7001/ 7002 -r
[root@itPX redis-cluster]# cp 7001/ 7003 -r
[root@itPX redis-cluster]# cp 7001/ 7004 -r
[root@itPX redis-cluster]# cp 7001/ 7005 -r
[root@itPX redis-cluster]# cp 7001/ 7006 –r
第六步:修改7002-7006机器的端口
第七步:启动7001-7006这六台机器
![e2e3c4925ae030dc268b2b39d33da64f.png](https://i-blog.csdnimg.cn/blog_migrate/3a08c7a83b075ceac6700459cd36b198.jpeg)
第八步:修改start-all.sh文件的权限
[root@itPX redis-cluster]# chmod u+x start-all.sh
[root@itPX redis-cluster]# ./start-all.sh
第九步:创建集群
[root@itPX redis-cluster]# ./redis-trib.rb create --replicas 1 192.168.242.137:7001 192.168.242.137:7002 192.168.242.137:7003 192.168.242.137:7004 192.168.242.137:7005 192.168.242.137:7006
>>> Creating cluster
Connecting to node 192.168.242.137:7001: OK
Connecting to node 192.168.242.137:7002: OK
Connecting to node 192.168.242.137:7003: OK
Connecting to node 192.168.242.137:7004: OK
Connecting to node 192.168.242.137:7005: OK
Connecting to node 192.168.242.137:7006: OK
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.242.137:7001
192.168.242.137:7002
192.168.242.137:7003
Adding replica 192.168.242.137:7004 to 192.168.242.137:7001
Adding replica 192.168.242.137:7005 to 192.168.242.137:7002
Adding replica 192.168.242.137:7006 to 192.168.242.137:7003
M: 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 192.168.242.137:7001
slots:0-5460 (5461 slots) master
M: 4f52a974f64343fd9f1ee0388490b3c0647a4db7 192.168.242.137:7002
slots:5461-10922 (5462 slots) master
M: cb7c5def8f61df2016b38972396a8d1f349208c2 192.168.242.137:7003
slots:10923-16383 (5461 slots) master
S: 66adf006fed43b3b5e499ce2ff1949a756504a16 192.168.242.137:7004
replicates 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24
S: cbb0c9bc4b27dd85511a7ef2d01bec90e692793b 192.168.242.137:7005
replicates 4f52a974f64343fd9f1ee0388490b3c0647a4db7
S: a908736eadd1cd06e86fdff8b2749a6f46b38c00 192.168.242.137:7006
replicates cb7c5def8f61df2016b38972396a8d1f349208c2
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.242.137:7001)
M: 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 192.168.242.137:7001
slots:0-5460 (5461 slots) master
M: 4f52a974f64343fd9f1ee0388490b3c0647a4db7 192.168.242.137:7002
slots:5461-10922 (5462 slots) master
M: cb7c5def8f61df2016b38972396a8d1f349208c2 192.168.242.137:7003
slots:10923-16383 (5461 slots) master
M: 66adf006fed43b3b5e499ce2ff1949a756504a16 192.168.242.137:7004
slots: (0 slots) master
replicates 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24
M: cbb0c9bc4b27dd85511a7ef2d01bec90e692793b 192.168.242.137:7005
slots: (0 slots) master
replicates 4f52a974f64343fd9f1ee0388490b3c0647a4db7
M: a908736eadd1cd06e86fdff8b2749a6f46b38c00 192.168.242.137:7006
slots: (0 slots) master
replicates cb7c5def8f61df2016b38972396a8d1f349208c2
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@itPX redis-cluster]#
连接集群
[root@itPX 7001]# ./redis-cli -h 192.168.242.137 -p 7001 –c
-c:指定是集群连接
![ca2fb772c5480ae10a4023c4f279b435.png](https://i-blog.csdnimg.cn/blog_migrate/ec59a5aefacbb45185b40847e9ca892e.jpeg)
查看集群信息
192.168.242.137:7002> 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:6
cluster_my_epoch:2
cluster_stats_messages_sent:2372
cluster_stats_messages_received:2372
192.168.242.137:7002>
查看集群节点
192.168.242.137:7002> cluster nodes
8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 192.168.242.137:7001 master - 0 1451581348093 1 connected 0-5460
cb7c5def8f61df2016b38972396a8d1f349208c2 192.168.242.137:7003 master - 0 1451581344062 3 connected 10923-16383
66adf006fed43b3b5e499ce2ff1949a756504a16 192.168.242.137:7004 slave 8240cd0fe6d6f842faa42b0174fe7c5ddcf7ae24 0 1451581351115 1 connected
a908736eadd1cd06e86fdff8b2749a6f46b38c00 192.168.242.137:7006 slave cb7c5def8f61df2016b38972396a8d1f349208c2 0 1451581349101 3 connected
4f52a974f64343fd9f1ee0388490b3c0647a4db7 192.168.242.137:7002 myself,master - 0 0 2 connected 5461-10922
cbb0c9bc4b27dd85511a7ef2d01bec90e692793b 192.168.242.137:7005 slave 4f52a974f64343fd9f1ee0388490b3c0647a4db7 0 1451581350108 5 connected
jedis连接集群
设置防火墙
[root@itPX redis-cluster]# vim /etc/sysconfig/iptables
-A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 6379 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7001 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7002 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7003 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7004 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7005 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7006 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 7007 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
"/etc/sysconfig/iptables" 23L, 1146C 已写入
[root@itPX redis-cluster]# service iptables restart
iptables:清除防火墙规则: [确定]
iptables:将链设置为政策 ACCEPT:filter [确定]
iptables:正在卸载模块: [确定]
iptables:应用防火墙规则: [确定]
[root@itPX redis-cluster]#
代码
![6af5f15122a82d06b30019727e24208b.png](https://i-blog.csdnimg.cn/blog_migrate/d8e1464332a234f1b639d44272697e76.jpeg)
使用spring
配置applicationContext.xml
测试代码
private ApplicationContext applicationContext;@Beforepublic void init() {applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");}// redis集群@Testpublic void testJedisCluster() {JedisCluster jedisCluster = (JedisCluster) applicationContext.getBean("jedisCluster");jedisCluster.set("name", "zhangsan");String value = jedisCluster.get("name");System.out.println(value);}