Redis是一个开放源代码
(BSD许可)的内存中数据结构存储,用作数据库缓存和消息代理。它支持数据结构,例如字符串
,哈希
,列表
,集合
,带范围查询的排序集合,位图,超日志,带有半径查询和流的地理空间索引。Redis具有内置的复制,Lua脚本,LRU逐出,事务和不同级别的磁盘持久性,并通过Redis Sentinel和Redis Cluster自动分区提供高可用性。 ——文献来自redis官网
某网站美少女战士对redis描述:
redis是一个key-value
存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。与memcached一样,为了保证效率,数据都是缓存在内存
中。
Redis是一个高性能的key-value数据库。redis的出现,很大程度补偿了memcached这类key/value存储的不足,可以说是memcached的升级版,在部分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby等客户端,使用很方便。
master-slave模式
的数据备份。持久化
,可以将内存中的数据保持在磁盘
中,重启的时候可以再次加载进行使用在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。Redis只会缓存所有的key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability
= age*log(size_in_memory)”计算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得Redis可以保持超过其机器本身内存大小的数据。
大概理解就是:session是一次浏览器和服务器的交互的会话,会话是啥就不用说了吧?A:吃了没? B: 吃了。 这就是一次会话,对话完成,会话就结束了。但session信息保留在服务端,也是为了保护服务器的安全,要是session会话过多,就会导致服务器响应卡顿,变慢,怎么办呢?
目前,为了使web能适应大规模的访问,需要实现应用的集群部署。集群最有效的方案就是负载均衡
,而实现负载均衡用户每一个请求都有可能被分配到不固定的服务器上,这样我们首先要解决session的统一来保证无论用户的请求被转发到哪个服务器上都能保证用户的正常使用,即
需要实现session的共享机制
,使群集服务器之间的session会话一致
此方案的不足之处:
必须在同一种中间件之间
完成(如:tomcat-tomcat之间).
session复制带来的性能损失会快速增加.特别是当session中保存了较大的对象,而且对象变化较快时, 性能下降更加显著,会消耗系统性能。这种特性使得web应用的水平扩展受到了限制。
Session内容通过广播同步给成员,会造成网络流量瓶颈,即便是内网瓶颈。在大并发下表现并不好.
实验所需全部软件包:https://pan.baidu.com/s/1oMB2dnKMiJdVS_PDvIe5Zw
提取码:fx99
实验环境:
主机 | 操作系统 | IP |
---|---|---|
nginx(1.16.x) | Centos7 | 192.168.10.2 |
tomcat1(apache-tomcat-7.0.54) | centos7 | 192.168.10.1 |
tomcat2(apache-tomcat-7.0.54) | centos7 | 192.168.10.3 |
redis(redis-5.0.6) | centos7 | 192.168.10.8 |
mysql(mysql-5.6.36) | centos7 | 192.168.10.4 |
在这个图中,nginx做为反向代理,实现静动分离,将客户动态请求根据权重随机分配给两台tomcat服务器,redis做为两台tomcat的共享session数据的缓存服务器,mysql做为两台tomcat的后端数据库。
又到了熟悉的环节,这里使用官方的yum源(阿里云也行,源码安装也行)
[root@nginx~]# cat /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1
[root@nginx ~]#
使用yum安装nginx
[root@nginx~]# yum -y install nginx
[root@nginx~]# systemctl start nginx
[root@nginx~]# systemctl enable nginx
[root@nginx ~]# nginx -v
nginx version: nginx/1.16.1
[root@localhost ~]# netstat -anput | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 2837/nginx: master
[root@localhost ~]#
配置nginx反向代理:反向代理+负载均衡
虚拟主机配置文件
[root@nginx ~]# cat /etc/nginx/conf.d/lb.conf
upstream backend_tomcat {
server 192.168.10.1:8080 weight=1 max_fails=2 fail_timeout=10s;
server 192.168.10.3:8080 weight=1 max_fails=2 fail_timeout=10s;
}
server {
listen 80;
server_name www.benet.com;
charset utf-8;
location / {
root html;
index index.html index.htm ;
}
location ~* \.(jsp|do)$ {
proxy_pass http://backend_tomcat;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
location /nginx_status {
stub_status on;
access_log off;
allow 192.168.10.0/24;
deny all;
}
}
配置防火墙规则
[root@nginx ~]# firewall-cmd --permanent --add-port=80/tcp
success
[root@nginx~]# firewall-cmd --reload
success
在tomcat-1和tomcat-2节点上安装JDK(即java)
首先检查Java环境
[root@tomcat2 ~]# java -version
openjdk version "1.8.0_102"
OpenJDK Runtime Environment (build 1.8.0_102-b14)
OpenJDK 64-Bit Server VM (build 25.102-b14, mixed mode)
没有java的,如果你的是最小化安装,自行yum安装
yum -y install java-1.8.0-openjdk*
在tomcat-1和tomcat-2节点安装配置tomcat
把apache-tomcat-7.0.54.tar.gz拷贝到两台主机
解压,无须make,make install 编译安装,移动到指定目录就好用
tar zxf apache-tomcat-7.0.54.tar.gz
mv apache-tomcat-7.0.54 /usr/local/tomcat
cd /usr/local/tomcat/
vi ./conf/server.xml
修改tomcat主配置文件,添加虚拟主机
修改默认虚拟主机,并将网站文件路径指向/web/webapp1,在host段增加context段
在host name 下面添加
<Context docBase="/web/webapp1" path="" reloadable="true"/>
增加目录和测试文件
[root@tomcat-1 ~]# mkdir -p /web/webapp1
[root@tomcat-1 ~]# cd /web/webapp1/
[root@ tomcat-1 webapp1]# vi index.jsp
index.jsp 内容如下:
<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>tomcat-1</title>
</head>
<body>
<h1><font color="red">Session serviced by tomcat</font></h1>
<table aligh="center" border="1">
<tr>
<td>Session ID</td>
<td><%=session.getId() %></td>
<% session.setAttribute("abc","abc");%>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
<html>
配置防火墙规则
[root@tomcat-1 ~]# firewall-cmd --permanent --add-port=8080/tcp
success
[root@tomcat-1 ~]# firewall-cmd --reload
success
开启tomcat服务
[root@localhost ~]# /usr/local/tomcat/bin/startup.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Tomcat started.
[root@localhost ~]# netstat -anpt | grep java
tcp6 0 0 :::8080 :::* LISTEN 4147/java
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 4147/java
tcp6 0 0 :::8009 :::* LISTEN 4147/java
tomcat1配置完并开启没有问题时,Tomcat2步骤和Tomcat1一模一样,直接把Tomcat1配置文件直接远程复制给tomcat2
在复制之前,先
在tomcat2上增加目录
[root@tomcat-2 ~]# mkdir -p /web/webapp2
[root@tomcat-2 ~]# cd /web/webapp2/
复制tomcat整个目录:
[root@ltomcat-1 ~]# scp -rp /usr/local/tomcat/ [email protected]:/usr/local/
The authenticity of host '192.168.10.3 (192.168.10.3)' can't be established.
ECDSA key fingerprint is 27:2d:ca:ff:27:6d:02:9d:7e:c1:aa:25:90:a6:15:8b.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.10.3' (ECDSA) to the list of known hosts.
[email protected]'s password:
复制index.jsp
[root@ltomcat-1 ~]# scp -rp /web/webapp1/index.jsp [email protected]:/web/webapp2/
修改:
<title>tomcat-1</title> ====》 <title>tomcat-2</title>
修改复制过去的server.xml,把网站文件的路径改为/web/webapp2
sed -i s:
启动tomcat2服务
用代理服务器192.168.10.2访问测试
再刷新有到了tomcat1,不过这时候2次访问有2个不一样session会话记录,一直刷新一直变,很占资源,Now,现在开始做本篇的重点,使他们共享session会话。
先拷贝redis的源码包到主机,解压安装make&&make install
[root@redis ~]# tar zxf redis-5.0.6.tar.gz
[root@redis ~]# mv redis-5.0.6 /usr/redis
[root@redis ~]# cd /usr/redis/
[root@redis ~]# make && make install
安装完后,切换到utils目录下,执行redis初始化脚本install_server.sh
[root@redis redis]# pwd
/usr/redis
[root@redis redis]# cd utils/
[root@redis utils]# ls
build-static-symbols.tcl hashtable redis_init_script.tpl
cluster_fail_time.tcl hyperloglog redis-sha1.rb
corrupt_rdb.c install_server.sh releasetools
create-cluster lru speed-regression.tcl
generate-command-help.rb redis-copy.rb whatisdoing.sh
graphs redis_init_script
[root@redis utils]# ./install_server.sh
Welcome to the redis service installer
This script will help you easily set up a running redis server
Please select the redis port for this instance: [6379]
Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf]
Selected default - /etc/redis/6379.conf
Please select the redis log file name [/var/log/redis_6379.log]
Selected default - /var/log/redis_6379.log
Please select the data directory for this instance [/var/lib/redis/6379]
Selected default - /var/lib/redis/6379
Please select the redis executable path [/usr/local/bin/redis-server]
Selected config:
Port : 6379
Config file : /etc/redis/6379.conf
Log file : /var/log/redis_6379.log
Data dir : /var/lib/redis/6379
Executable : /usr/local/bin/redis-server
Cli Executable : /usr/local/bin/redis-cli
Is this ok? Then press ENTER to go on or Ctrl-C to abort.
Copied /tmp/6379.conf => /etc/init.d/redis_6379
Installing service...
Successfully added to chkconfig!
Successfully added to runlevels 345!
Starting Redis server...
Installation successful!
[root@redis utils]#
通过上面的安装过程,我们可以看出redis初始化后redis配置文件为
/etc/redis/6379.conf,日志文件为/var/log/redis_6379.log,数据文件dump.rdb存放到/var/lib/redis/6379目录下,启动脚为/etc/init.d/redis_6379。
现在我们要使用systemd,所以在 /etc/systems/system 下创建一个单位文件名字为 redis_6379.service。
[root@redis redis]# cat /etc/systemd/system/redis_6379.service
[Unit]
Description=Redis on port 6379
[Service]
Type=forking
ExecStart=/etc/init.d/redis_6379 start
ExecStop=/etc/init.d/redis_6379 stop
[Install]
WantedBy=multi-user.target
[root@redis redis]#
配置redis
设置redis监听的地址,添加监听redis主机的ip
考虑到安全性,我们需要启用redis的密码验证功能requirepass参数
[root@redis ~]# vim /etc/redis/6379.conf
在最后添加一行:
requirepass 123.com
修改一行:
bind 127.0.0.1 192.168.10.8
启动redis
[root@redis ~]# systemctl daemon-reload
[root@redis ~]# systemctl enable redis_6379.service
Created symlink from /etc/systemd/system/multi-user.target.wants/redis_6379.service to /etc/systemd/system/redis_6379.service.
[root@redis ~]#
[root@redis ~]# systemctl start redis_6379.service
[root@redis ~]# netstat -anput | grep redis
tcp 0 0 192.168.10.8:6379 0.0.0.0:* LISTEN 44872/redis-server
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 44872/redis-server
使用redis来进行简单的操作
[root@redis ~]# redis-cli -h 192.168.31.106 -p 6379 -a pwd@123
192.168.31.106:6379> keys *
(empty list or set)
192.168.31.106:6379> set name lisi
OK
192.168.31.106:6379> get name
"lisi"
192.168.31.106:6379>
备注:
keys *是查看redis所有的键值对。
set namelisi添加一个键值name,内容为lisi。
get name查看name这个键值的内容。
下载tomcat-redis-session-manager相应的jar包,主要有三个(前面分享的链接里都有):
tomcat-redis-session-manage-tomcat7.jar
jedis-2.5.2.jar
commons-pool2-2.2.jar
下载完成后拷贝到$TOMCAT_HOME/lib中
[root@tomcat-1 ~]# mv jedis-2.5.2.jar commons-pool2-2.2.jar tomcat-redis-session-manage-tomcat7.jar /usr/local/tomcat/lib/
[root@tomcat-1 ~]# vim /usr/local/tomcat/conf/context.xml
修改tomcat的context.xml:
添加:
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
host="192.168.10.8"
password="123.com"
port="6379"
database="0"
maxInactiveInterval="60" /> #60s后会话过期
重启tomcat服务
先关闭服务,在开启服务
[root@localhost ~]# /usr/local/tomcat/bin/shutdown.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
[root@localhost ~]# /usr/local/tomcat/bin/startup.sh
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
Tomcat started.
[root@localhost ~]# netstat -anpt | grep java
tcp6 0 0 :::8080 :::* LISTEN 4147/java
tcp6 0 0 127.0.0.1:8005 :::* LISTEN 4147/java
tcp6 0 0 :::8009 :::* LISTEN 4147/java
这里tomcat-2和tomcat-1的操作还是一模一样的,先移动那3个文件
,在复制context.xml
,最后重启服务
[root@tomcat-1 ~]# scp -rp /usr/local/tomcat/conf/context.xml [email protected]:/usr/local/tomcat/conf/
[email protected]'s password:
context.xml 100% 1654 1.6KB/s 00:00
[root@tomcat-1 ~]#
通过浏览器访问http://192.168.10.2/index.jsp测试页(访问反向代理服务器)
可以看出,分别访问了不同的tomcat,但是得到的session却是相同的,说明达到了集群的目的;redis也实现了session共享
192.168.10.4作为集群的mysql数据库
创建数据库,给用户授权
创建表格,插入数据
[root@localhost ~]# mysql -uroot -p123.com
mysql> create database redis;
Query OK, 1 row affected (0.00 sec)
mysql> grant all on *.* to redis@'192.168.10.%' identified by '123.com';
Query OK, 0 rows affected (0.00 sec)
mysql> use redis;
Database changed
mysql> create table testdata(id int not null auto_increment primary key,foo varchar(25),bar int);
Query OK, 0 rows affected (0.03 sec)
mysql>
mysql> insert into testdata(foo,bar) values ('MongoDB','123456'),('Oracle','654321');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from testdata;
+----+---------+--------+
| id | foo | bar |
+----+---------+--------+
| 1 | MongoDB | 123456 |
| 2 | Oracle | 654321 |
+----+---------+--------+
2 rows in set (0.00 sec)
mysql防火墙配置\
firewall-cmd –-permanent –add-port=3306/tcp
firewall-cmd --reload
配置tomcat服务器连接mysql数据库(tomcat-1为例)
下载mysql-connector-java-5.1.22-bin.jar并复制到$CATALINA_HOME/lib目录下,修改context.xml
[root@tomcat-2 ~]# cp mysql-connector-java-5.1.22-bin.jar /usr/local/tomcat/lib/
[root@tomcat-2 ~]# vi /usr/local/tomcat/conf/context.xml
在<Context>中添加如下内容:
<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="redis" password="123.com" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://192.168.10.4:3306/redis"/>
保存修改并退出
web.xml可以随便命名,但是前面的WEB-INF目录
不能改动
[root@tomcat-2 ~]# mkdir /web/webapp2/WEB-INF
[root@tomcat-2 ~]# vi /web/webapp2/WEB-INF/web.xml
添加内容如下:
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<description>MySQL Test App</description>
<resource-ref>
<description>DB Connection</description>
<res-ref-name>jdbc/TestDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
保存修改并退出
在 /web/webapp2创建test.jsp测试文件
[root@tomcat-2 ~]# cat /web/webapp2/test.jsp
<%@ page language="java" import="java.sql.*" pageEncoding="GB2312"%>
<html>
<head>
<title>MySQL</title>
</head>
<body>
connect MySQL<br>
<%
String driverClass="com.mysql.jdbc.Driver";
String url="jdbc:mysql://192.168.10.4:3306/redis";
String username = "redis";
String password = "123.com";
Class.forName(driverClass);
Connection conn=DriverManager.getConnection(url, username, password);
Statement stmt=conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from testdata");
while(rs.next()){
out.println("
foo:"+rs.getString(2)+" bar:"+rs.getString(3));
}
rs.close();
stmt.close();
conn.close();
%>
</body></html>
通过浏览器访问http://192.168.10.8/test.jsp测试页
,数据库连接成功!