文章目录

  • 一、概念
  • 1.redis介绍
  • 2.redis的常用命令
  • 3.哨兵模式
  • 二、redis部署
  • 三、redis主从复制
  • 四、redis高可用
  • 五、redis集群



一、概念

redis引入
在我们日常的Java Web开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是主页访问量瞬间较大的时候,单一使用数据库来保存数据的系统会因为面向磁盘,磁盘读/写速度比较慢的问题而存在严重的性能弊端,一瞬间成千上万的请求到来,需要系统在极短的时间内完成成千上万次的读/写操作,这个时候往往不是数据库能够承受的,极其容易造成数据库系统瘫痪,最终导致服务宕机的严重生产问题。所以在当今云计算、大数据盛行的时代,对性能有了更多的需求,主要体现在以下四个方面:

  • 低延迟的读写速度:应用快速地反应能极大地提升用户的满意度
  • 支撑海量的数据和流量:对于搜索这样大型应用而言,需要利用PB级别的数据和能应对百万级的流量
  • 大规模集群的管理:系统管理员希望分布式应用能更简单的部署和管理
  • 庞大运营成本的考量:IT部门希望在硬件成本、软件成本和人力成本能够有大幅度地降低

为了克服上述的问题,Java Web项目通常会引入NoSQL技术,这是一种基于内存的数据库,并且提供一定的持久化功能。

Redis是一个开源的、使用 C 语言编写的 NoSQL 数据库。
Redis基于内存运行并支持持久化,采用key-value(键值对)的存储形式,是目前分布式架构中不可或缺的一环。

redis和mysql的区别
1、MySQL是关系型数据库;而Redis是非关系型数据库。
2、MySQL用于持久化存储数据到硬盘,功能强大,但是速度缓慢;而Redis用于存储使用较为频繁的数据到缓存中,读取速度快。
3、MySQL的数据存放在磁盘中;而Redis的数据存放在内存中。
4、MySQL常用数据类型有数值、日期/时间、字符串;Redis常用数据类型有字符串、Hash、List、Set、Zset。
redis和memcached的区别:
Memcached 不支持数据持久化,而 Redis 支持两种数据持久化方式:RDB 快照、AOF 日志

1.redis介绍

redis是现在最受欢迎的NoSQL数据库之一,redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化的Key-Value数据库。
redis的官网地址 http://redis.cn/
redis是一种高级的key:value存储系统,其中value支持五种数据类型:
字符串(strings)、字符串列表(lists)、字符串集合(sets)、有序字符串集合(sorted sets)、哈希(hashes);
其具备如下特性:
1.基于内存运行,性能高效
2.支持分布式,理论上可以无限扩展
3.key-value存储系统
4.开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API
Redis 在 Java Web 主要有两个应用场景:
存储 缓存 用的数据;
需要高速读/写的场合使用它快速读/写;
缓存
在日常对数据库的访问中,读操作的次数远超写操作,比例大概在 1:9 到 3:7,所以需要读的可能性是比写的可能大得多的。当我们使用SQL语句去数据库进行读写操作时,数据库就会去磁盘把对应的数据索引取回来,这是一个相对较慢的过程。
如果我们把数据放在 Redis 中,也就是直接放在内存之中,让服务端直接去读取内存中的数据,那么这样速度明显就会快上不少,并且会极大减小数据库的压力,但是使用内存进行数据存储开销也是比较大的,限于成本的原因,一般我们只是使用 Redis 存储一些常用和主要的数据,比如用户登录的信息等

Redis与数据库使用 redis数据库和mysql数据库_redis

2.redis的常用命令

常用命令             含义
config get *        查看配置
select 1            选择数据库
flushdb             清空当前数据库
flushall            清空所有数据库
move key 1          移动key
del key             删除
rename oldkey newkey改名
expire key 10       设置过期时间
persist key         设置持久化
persist key         查询
persist key         判断是否存在

3.哨兵模式

介绍
主从模式下,当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这种方式并不推荐,实际生产中,我们优先考虑哨兵模式。这种模式下,master宕机,哨兵会自动选举master并将其他的slave指向新的master。
在主从模式下,redis同时提供了哨兵命令redis-sentinel,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵进程向所有的redis机器发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
哨兵可以有多个,一般为了便于决策选举,使用奇数个哨兵。哨兵可以和redis机器部署在一起,也可以部署在其他的机器上。多个哨兵构成一个哨兵集群,哨兵直接也会相互通信,检查哨兵是否正常运行,同时发现master宕机哨兵之间会进行决策选举新的master
哨兵模式的作用
通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器;
当哨兵监测到master宕机,会自动将slave切换到master,然后通过发布订阅模式通过其他的从服务器,修改配置文件,让它们切换主机;
然而一个哨兵进程对Redis服务器进行监控,也可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。

二、redis部署

编译安装
[root@server1 ~]# tar zxf redis-6.2.4.tar.gz
 [root@server1 ~]# cd redis-6.2.4/
 [root@server1 redis-6.2.4]# make
 [root@server1 redis-6.2.4]# make install
 [root@server1 redis-6.2.4]# cd utils/
 [root@server1 utils]# vim install_server.sh
注释以下行

Redis与数据库使用 redis数据库和mysql数据库_mysql_02


运行安装脚本


[root@server1 utils]# ./install_server.sh


Redis与数据库使用 redis数据库和mysql数据库_数据库_03


[root@server1 utils]# netstat -antlp|grep :6379


tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 17478/redis-server


tcp6 0 0 ::1:6379 ::😗 LISTEN 17478/redis-server


[root@server1 utils]# vim /etc/redis/6379.conf


#监听本机所有接口


bind *


Redis与数据库使用 redis数据库和mysql数据库_Redis与数据库使用_04


重启服务


[root@server1 utils]# /etc/init.d/redis_6379 restart


[root@server1 utils]# netstat -antlp|grep :6379


tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 17533/redis-server


Redis与数据库使用 redis数据库和mysql数据库_mysql_05

三、redis主从复制

Redis与数据库使用 redis数据库和mysql数据库_Redis_06


server3he server2同样的操作

创建redis实例,直接从server1上拷贝编译好的redis程序,两边都要安装rsync命令
 [root@server1 ~]# cd /usr/local/bin/
 [root@server1 bin]# yum install -y rsync(支持保留软链接)
 [root@server3 ~]# yum install -y rsync
 拷贝程序
 [root@server1 bin]# rsync -a redis-* server3:/usr/local/bin/
 [root@server1 ~]# rsync -a redis-6.2.4 server3:
 server3上完成redis部署
 [root@server3 ~]# cd /usr/local/bin/
 [root@server3 bin]# ls
 redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-sentinel redis-server
 [root@server3 ~]# cd redis-6.2.4/
 [root@server3 redis-6.2.4]# cd utils/
 [root@server3 utils]# ./install_server.sh

Redis与数据库使用 redis数据库和mysql数据库_Redis与数据库使用_07

[root@server3 utils]# vim /etc/redis/6379.conf

 …

 76行bind *

 77行replicaof 192.168.56.11 6379

 [root@server3 ~]# /etc/init.d/redis_6379 restart

测试:

master写入数据

[root@server1 ~]# redis-cli

127.0.0.1:6379> info

Redis与数据库使用 redis数据库和mysql数据库_Redis_08


127.0.0.1:6379> set name westos

查看slave端是否同步
[root@server3 ~]# redis-cli
127.0.0.1:6379> get name
“westos”

四、redis高可用

当slave发现自己的master变为FAIL状态时,便尝试进行Failover,以期成为新的master。由于挂掉的master可能会有多个slave,从而存在多个slave竞争成为master节点的过程,其过程如下:
1、slave发现自己的master变为FAIL
2、将自己记录的集群currentEpoch加1,并广播FAILOVER_AUTH_REQUEST信息
3、其他节点收到改信息,只有master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK,对每一个epoch只发送一次ack
4、尝试failover的slave收集FAILOVER_AUTH_ACK
5、其他slave投票超过半数后变成新master
6、广播通知其他集群节点此时的master。

Redis与数据库使用 redis数据库和mysql数据库_mysql_09

[root@server1 redis-6.2.4]# cp sentinel.conf /etc/redis/
 [root@server1 redis-6.2.4]# cd /etc/redis/
 [root@server1 redis]# vim sentinel.conf

Redis与数据库使用 redis数据库和mysql数据库_Redis_10

拷贝配置文件

 [root@server1 redis]# scp sentinel.conf server2:/etc/redis/

 [root@server1 redis]# scp sentinel.conf server3:/etc/redis/

 启动服务

 [root@server1 redis]# redis-sentinel /etc/redis/sentinel.conf

 [root@server2 ~]# redis-sentinel /etc/redis/sentinel.conf

 [root@server3 ~]# redis-sentinel /etc/redis/sentinel.conf

 关闭redis master

 [root@server1 ~]# redis-cli shutdown

 redis集群会自动切换master


Redis与数据库使用 redis数据库和mysql数据库_redis_11


当原来的master再次启动后,会以slave身份加入集群


[root@server1 ~]# /etc/init.d/redis_6379 start


[root@server1 ~]# redis-cli info


Redis与数据库使用 redis数据库和mysql数据库_数据库_12

master的两个slave都能正常连接,才可以写入数据,可写到master的配置文件中

Redis与数据库使用 redis数据库和mysql数据库_Redis与数据库使用_13


热生效:

Redis与数据库使用 redis数据库和mysql数据库_数据库_14


永久生效:

Redis与数据库使用 redis数据库和mysql数据库_mysql_15

五、redis集群

集群不可用:
1.16383个哈希槽不完整;
2.同一时间,集群的半数master集体down;

实验原理
Redis 的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台 Redis 服务器都存储相同的数据,很浪费内存,所以在redis3.0上加入了 Cluster 集群模式,实现了 Redis 的分布式存储,对数据进行分片,也就是说每台 Redis 节点上存储不同的内容;

Redis与数据库使用 redis数据库和mysql数据库_mysql_16


这里的6台redis两两之间并不是独立的,每个节点都会通过集群总线(cluster bus),与其他的节点进行通信。通讯时使用特殊的端口号,即对外服务端口号加10000。例如如果某个node的端口号是6379,那么它与其它nodes通信的端口号是16379。nodes之间的通信采用特殊的二进制协议。


对客户端来说,整个cluster被看做是一个整体,客户端可以连接任意一个node进行操作,就像操作单一Redis实例一样,当客户端操作的key没有分配到该node上时,Redis会返回转向指令,指向正确的node,这有点儿像浏览器页面的302 redirect跳转。


根据官方推荐,集群部署至少要 3 台以上的master节点,最好使用 3 主 3 从六个节点的模式。测试时,也可以在一台机器上部署这六个实例,通过端口区分出来。

[root@server1 redis-6.2.4]# cd utils/
[root@server1 utils]# cd create-cluster/
[root@server1 create-cluster]# ./create-cluster start
Starting 30001
Starting 30002
Starting 30003
Starting 30004
Starting 30005
Starting 30006


[root@server1 create-cluster]# ./create-cluster create
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:30005 to 127.0.0.1:30001
Adding replica 127.0.0.1:30006 to 127.0.0.1:30002
Adding replica 127.0.0.1:30004 to 127.0.0.1:30003
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 97659fdbb23eb6885d5b8332be4732757859abe9 127.0.0.1:30001
   slots:[0-5460] (5461 slots) master
M: 61a153651897aadf57ed62e0e27789db52f4549b 127.0.0.1:30002
   slots:[5461-10922] (5462 slots) master
M: 258d4258594f6c7f81f8bc18000e24aa45b08ac4 127.0.0.1:30003
   slots:[10923-16383] (5461 slots) master
S: 60e4a9a86c6cea09703e7aa45cc363f142101876 127.0.0.1:30004
   replicates 97659fdbb23eb6885d5b8332be4732757859abe9
S: 73083399d7e8f6374a50aaef208dd7f17b2ebde1 127.0.0.1:30005
   replicates 61a153651897aadf57ed62e0e27789db52f4549b
S: d4743d579d365f335a5abead72f618212ec700d4 127.0.0.1:30006
   replicates 258d4258594f6c7f81f8bc18000e24aa45b08ac4
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 127.0.0.1:30001)
M: 97659fdbb23eb6885d5b8332be4732757859abe9 127.0.0.1:30001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: d4743d579d365f335a5abead72f618212ec700d4 127.0.0.1:30006
   slots: (0 slots) slave
   replicates 258d4258594f6c7f81f8bc18000e24aa45b08ac4
M: 61a153651897aadf57ed62e0e27789db52f4549b 127.0.0.1:30002
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: 258d4258594f6c7f81f8bc18000e24aa45b08ac4 127.0.0.1:30003
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 60e4a9a86c6cea09703e7aa45cc363f142101876 127.0.0.1:30004
   slots: (0 slots) slave
   replicates 97659fdbb23eb6885d5b8332be4732757859abe9
S: 73083399d7e8f6374a50aaef208dd7f17b2ebde1 127.0.0.1:30005
   slots: (0 slots) slave
   replicates 61a153651897aadf57ed62e0e27789db52f4549b
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
查看命令帮助
[root@server1 create-cluster]# redis-cli --cluster help
获取集群状态
[root@server1 create-cluster]# redis-cli --cluster check 127.0.0.1:30001
127.0.0.1:30001 (97659fdb...) -> 0 keys | 5461 slots | 1 slaves.
127.0.0.1:30002 (61a15365...) -> 0 keys | 5462 slots | 1 slaves.
127.0.0.1:30003 (258d4258...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 127.0.0.1:30001)
M: 97659fdbb23eb6885d5b8332be4732757859abe9 127.0.0.1:30001
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: d4743d579d365f335a5abead72f618212ec700d4 127.0.0.1:30006
   slots: (0 slots) slave
   replicates 258d4258594f6c7f81f8bc18000e24aa45b08ac4
M: 61a153651897aadf57ed62e0e27789db52f4549b 127.0.0.1:30002
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: 258d4258594f6c7f81f8bc18000e24aa45b08ac4 127.0.0.1:30003
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 60e4a9a86c6cea09703e7aa45cc363f142101876 127.0.0.1:30004
   slots: (0 slots) slave
   replicates 97659fdbb23eb6885d5b8332be4732757859abe9
S: 73083399d7e8f6374a50aaef208dd7f17b2ebde1 127.0.0.1:30005
   slots: (0 slots) slave
   replicates 61a153651897aadf57ed62e0e27789db52f4549b
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
连接集群
[root@server1 create-cluster]# redis-cli -c -p 30001 info

[root@server1 create-cluster]# redis-cli -c -p 30004
127.0.0.1:30004> set name wxh
-> Redirected to slot [5798] located at 127.0.0.1:30002【重定向至30002,体现无中心化】
OK

关闭redis实例,集群自动切换
[root@server1 create-cluster]# redis-cli -c -p 30002 shutdown【30002的slave变成master】

启动redis实例
[root@server1 create-cluster]# ./create-cluster  start      【重新拉起】
Starting 30001
Starting 30002
Starting 30003
Starting 30004
Starting 30005
Starting 30006

数据完好
[root@server1 create-cluster]# redis-cli -c -p 30001 get name
"wxh"

Redis与数据库使用 redis数据库和mysql数据库_mysql_17

再启动两个redis实例
[root@server1 create-cluster]# vim create-cluster

Redis与数据库使用 redis数据库和mysql数据库_Redis_18

[root@server1 create-cluster]# ./create-cluster start

 Starting 30001

 Starting 30002

 Starting 30003

 Starting 30004

 Starting 30005

 Starting 30006

 Starting 30007

 Starting 30008

添加集群节点


[root@server1 create-cluster]# redis-cli --cluster add-node 127.0.0.1:30007 127.0.0.1:30001


Redis与数据库使用 redis数据库和mysql数据库_redis_19

新添加的节点没有hash槽,角色是master

Redis与数据库使用 redis数据库和mysql数据库_Redis与数据库使用_20


添加slave节点

[root@server1 create-cluster]# redis-cli --cluster add-node 127.0.0.1:30008 127.0.0.1:30001 --cluster-slave --cluster-master-id 2cfe812f247254aa593f07bcc5e15291b77ecef6

Redis与数据库使用 redis数据库和mysql数据库_redis_21


Redis与数据库使用 redis数据库和mysql数据库_Redis与数据库使用_22

迁移hash槽
 [root@server1 create-cluster]# redis-cli --cluster reshard 127.0.0.1:30001
 Performing Cluster Check (using node 127.0.0.1:30001)
 M: 97659fdbb23eb6885d5b8332be4732757859abe9 127.0.0.1:30001
 slots:[0-5460] (5461 slots) master
 1 additional replica(s)
 S: d4743d579d365f335a5abead72f618212ec700d4 127.0.0.1:30006
 slots: (0 slots) slave
 replicates 258d4258594f6c7f81f8bc18000e24aa45b08ac4
 S: 61a153651897aadf57ed62e0e27789db52f4549b 127.0.0.1:30002
 slots: (0 slots) slave
 replicates 73083399d7e8f6374a50aaef208dd7f17b2ebde1
 M: 2cfe812f247254aa593f07bcc5e15291b77ecef6 127.0.0.1:30007
 slots: (0 slots) master
 1 additional replica(s)
 M: 258d4258594f6c7f81f8bc18000e24aa45b08ac4 127.0.0.1:30003
 slots:[10923-16383] (5461 slots) master
 1 additional replica(s)
 S: 60e4a9a86c6cea09703e7aa45cc363f142101876 127.0.0.1:30004
 slots: (0 slots) slave
 replicates 97659fdbb23eb6885d5b8332be4732757859abe9
 S: 2cc38329498a358c6e7486bb4621017261a63db3 127.0.0.1:30008
 slots: (0 slots) slave
 replicates 2cfe812f247254aa593f07bcc5e15291b77ecef6
 M: 73083399d7e8f6374a50aaef208dd7f17b2ebde1 127.0.0.1:30005
 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.
 How many slots do you want to move (from 1 to 16384)? 3000
 What is the receiving node ID? 2cfe812f247254aa593f07bcc5e15291b77ecef6
 Please enter all the source node IDs.
 Type ‘all’ to use all the nodes as source nodes for the hash slots.
 Type ‘done’ once you entered all the source nodes IDs.
 Source node #1: all
 Ready to move 3000 slots.
 Source nodes:
 M: 97659fdbb23eb6885d5b8332be4732757859abe9 127.0.0.1:30001
 slots:[0-5460] (5461 slots) master
 1 additional replica(s)
 M: 258d4258594f6c7f81f8bc18000e24aa45b08ac4 127.0.0.1:30003
 slots:[10923-16383] (5461 slots) master
 1 additional replica(s)
 M: 73083399d7e8f6374a50aaef208dd7f17b2ebde1 127.0.0.1:30005
 slots:[5461-10922] (5462 slots) master
 1 additional replica(s)
 Destination node:
 M: 2cfe812f247254aa593f07bcc5e15291b77ecef6 127.0.0.1:30007
 slots: (0 slots) master
 1 additional replica(s)

Redis与数据库使用 redis数据库和mysql数据库_mysql_23