1、 redis介紹
redis是一個key-value存儲系統。和Memcached相似,它支持存儲的value類型相對更多,包括
string(字符串)、 list(鏈表)、 set(集合)、 zset(sorted set --有序集合)和hash(哈希類型) 。 與memcached
同樣,爲了保證效率,數據都是緩存在內存中。區別的是redis會週期性的把更新的數據寫入磁盤
或者把修改操做寫入追加的記錄文件,而且在此基礎上實現master-slave(主從)同步。
Redis是一個高性能的key-value數據庫。 redis的出現,很大程度補償了memcached這類key/value
存儲的不足,在部分場合能夠對關係數據庫起到很好的補充做用。它提供了Java, C/C++, C#,
PHP, JavaScript, Perl, Object-C, Python, Ruby等客戶端,使用很方便。
若是簡單地比較Redis與Memcached的區別, 基本上有如下3點:
一、 Redis不只僅支持簡單的k/v類型的數據,同時還提供list, set, zset, hash等數據結構的存儲。
二、 Redis支持數據的備份,即master-slave模式的數據備份。
三、 Redis支持數據的持久化,能夠將內存中的數據保持在磁盤中,重啓的時候能夠再次加載進行
使用。
在Redis中,並非全部的數據都一直存儲在內存中的。這是和Memcached相比一個最大的區別。
Redis只會緩存全部的key的信息,若是Redis發現內存的使用量超過了某一個閥值,將觸發swap
的操做, Redis根據「swappability = age*log(size_in_memory)」計算出哪些key對應的value須要swap
到磁盤。而後再將這些key對應的value持久化到磁盤中,同時在內存中清除。這種特性使得Redis
能夠保持超過其機器自己內存大小的數據。固然,機器自己的內存必需要可以保持全部的key,
由於這些數據是不會進行swap操做的。
當從Redis中讀取數據的時候,若是讀取的key對應的value不在內存中, 那麼Redis就須要從swap
文件中加載相應數據,而後再返回給請求方。
memcached和redis的比較
一、 網絡IO模型
Memcached是多線程,非阻塞IO複用的網絡模型,分爲監聽主線程和worker子線程,監聽線程監
聽網絡鏈接,接受請求後,將鏈接描述字pipe 傳遞給worker線程,進行讀寫IO, 網絡層使用
libevent封裝的事件庫,多線程模型能夠發揮多核做用。
Redis使用單線程的IO複用模型,本身封裝了一個簡單的AeEvent事件處理框架,主要實現了epoll、
kqueue和select,對於單純只有IO操做來講,單線程能夠將速度優點發揮到最大,可是Redis也提
供了一些簡單的計算功能,好比排序、聚合等,對於這些操做,單線程模型實際會嚴重影響總體
吞吐量, CPU計算過程當中,整個IO調度都是被阻塞住的。
二、 內存管理方面
Memcached使用預分配的內存池的方式,使用slab和大小不一樣的chunk來管理內存, value根據大
小選擇合適的chunk存儲。 Redis使用現場申請內存的方式來存儲數據。
三、 存儲方式及其它方面
Memcached基本只支持簡單的key-value存儲,不支持持久化和複製等功能, Redis除key/value以外,
還支持list,set,sortedset,hash等衆多數據結構
2、 如何保持session會話
目前,爲了使web能適應大規模的訪問,須要實現應用的集羣部署。集羣最有效的方案就是負載
均衡,而實現負載均衡用戶每個請求都有可能被分配到不固定的服務器上,這樣咱們首先要解
決session的統一來保證不管用戶的請求被轉發到哪一個服務器上都能保證用戶的正常使用,即需
要實現session的共享機制。
在集羣系統下實現session統一的有以下幾種方案:
一、 請求精肯定位: sessionsticky,例如基於訪問ip的hash策略, 即當前用戶的請求都集中定位
到一臺服務器中,這樣單臺服務器保存了用戶的session登陸信息,若是宕機,則等同於單點部
署,會丟失, 會話不復制。
二、 session複製共享: sessionreplication,如tomcat自帶session共享, 主要是指集羣環境下,
多臺應用服務器之間同步session,使session保持一致,對外透明。 若是其中一臺服務器發生
故障,根據負載均衡的原理, 調度器會遍歷尋找可用節點,分發請求,因爲session已同步,故
能保證用戶的session信息不會丟失, 會話複製,。
此方案的不足之處:
必須在同一種中間件之間完成(如:tomcat-tomcat之間).
session複製帶來的性能損失會快速增長.特別是當session中保存了較大的對象,並且對象變化
較快時, 性能降低更加顯著, 會消耗系統性能。 這種特性使得web應用的水平擴展受到了限制。
Session內容經過廣播同步給成員,會形成網絡流量瓶頸,即使是內網瓶頸。 在大併發下表現並
很差
三、 基於cache DB緩存的session共享
基於memcache/redis緩存的 session 共享
即便用cacheDB存取session信息,應用服務器接受新請求將session信息保存在cache DB中,當
應用服務器發生故障時, 調度器會遍歷尋找可用節點,分發請求,當應用服務器發現session不
在本機內存時,則去cache DB中查找,若是找到則複製到本機,這樣實現session共享和高可用。
3、 nginx+tomcat+redis實現負載均衡、 session共享
一、實驗環境
主機 操做系統 IP地址
Nginx 192.168.1.10
Tomcat-1 192.168.1.20
Tomcat-2 Centos7.2 192.168.1.30
Mysql 192.168.1.40
Redis 192.168.1.80
二、實驗拓撲
在這個圖中, nginx作爲反向代理,實現靜動分離,將客戶動態請求根據權重隨機分配給兩臺tomcat
服務器, redis作爲兩臺tomcat的共享session數據服務器, mysql作爲兩臺tomcat的後端數據庫。
三、 nginx安裝配置
使用Nginx做爲Tomcat的負載平衡器, Tomcat的會話Session數據存儲在Redis,可以實現零宕機的
7x24效果。由於將會話存儲在Redis中,所以Nginx就沒必要配置成stick粘貼某個Tomcat方式,這樣
才能真正實現後臺多個Tomcat負載平衡。html
(1) 安裝nginx
安裝nginx依賴包
yum -y install openssl-devel pcre-devel zlib-devel
編譯安裝nginx
連接nginx命令目錄
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
(2)配置nginx反向代理: 反向代理+負載均衡+健康探測, nginx.conf文件內容:
Vim /usr/local/nginx/conf/nginx.conf 添加
20 添加
upstream backend_tomcat {
server 192.168.1.20:8080 weight=1 max_fails=2 fail_timeout=10s;
server 192.168.1.30:8080 weight=1 max_fails=2 fail_timeout=10s;
}
24添加
proxy_connect_timeout 75;
proxy_send_timeout 75;
proxy_read_timeout 75;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
48 添加
location / {java
# index index.jsp index.html index.htm; 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;mysql
}
50添加nginx
(2) 開啓nginx並查看端口web
四、安裝部署tomcat應用程序服務器(兩臺都是)
(1)安裝tomcat並開啓,查看端口redis
20 tar zxf apache-tomcat-8.5.35.tar.gz
將解壓生成的文件夾移動到/usr/local/下,並更名爲tomcat
21 mv apache-tomcat-8.5.35 /usr/local/tomcat
22 /usr/local/tomcat/bin/startup.sh
23 netstat -anpt |grep 8080
瀏覽器測試
好了,你們能夠看到訪成功。說明咱們的tomcat安裝完成,下面咱們來修改配置文件
(2)設置默認虛擬主機
vim /usr/local/tomcat/conf/server.xml 150添加
<Context docBase="/web/webapp1" path="" reloadable="true"/>
(3)建立所需目錄和網頁sql
30 mkdir -p /web/webapp1
31 vim /web/webapp1/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>
(4)重啓tomcat
(5)瀏覽器測試數據庫
驗證健康檢查的方法能夠關掉一臺tomcat主機,用客戶端瀏覽器測試訪問。從上面的結果能看出兩次訪問, nginx把訪問請求分別分發給了後端的tomcat-1和tomcat-2,客戶端的訪問請求實現了負載均衡,但sessionid並不同。 因此,到這裏咱們準備工做就所有完成了,下面咱們來配置tomcat經過redis實現會話保持。apache
五、 安裝redis
(1)編譯安裝redis
23 rz
24 tar zxf redis-4.0.14.tar.gz
25 mv redis-4.0.14 /usr/local/redis
26 cd /usr/local/redis/
27 make && make install
(2)切換到utils目錄下,執行redis初始化腳本install_server.sh
29 cd utils/
30 ./install_server.sh
31 netstat -anput | grep redis
經過上面的安裝過程,咱們能夠看出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。
(3)修改 /etc/redis/6379.conf
bind 0.0.0.0 70修改
requirepass 123.com 501去註釋設置密碼
(4)重啓一下redis並看端口
/etc/init.d/redis_6379 restart
netstat -anput | grep redis
(5)redis測試vim
六、 配置tomcat session redis同步 (兩臺tomcat都是)
(1)下載tomcat-redis-session-manager相應的jar包,下載完成後拷貝到$TOMCAT_HOME/lib中
(2)修改/usr/local/tomcat/conf/context.xml 倒數第二行添加
<Manager pathname="" /> 去註釋
<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
host="192.168.1.40"
password="123.com"
port="6379"
database="0"
maxInactiveInterval="60" />
(3)重啓tomcat
(4)redis重啓
(5)瀏覽器測試
能夠看出,分別訪問了不一樣的tomcat,可是獲得的session倒是相同的,說明達到了集羣的目的。
(6)redis測試
192.168.1.80 做爲mysql數據庫服務器
(1)mysql配置
mysql -u root -p 123
grant all on . to javauser@'192.168.1.%' identified by 'javapasswd';
create database javatest;
use javatest;
create table testdata(id int not null auto_increment primary key,foo varchar(25),bar int);
insert into testdata(foo,bar) values ('hello','123456'),('ok','654321'),('xgp','1123645');
select * from testdata;
(2)tomcat配置(兩臺都是)
進入配置教程
<1>/usr/local/tomcat/conf/context.xml 倒數第二行添加
<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
maxTotal="100" maxIdle="30" maxWaitMillis="10000"
username="javauser" password="javapasswd" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://192.168.1.80:3306/javatest"/>
<2>建立所需目錄和網頁
55 cd /web/webapp1/
56 mkdir WEB-INF
57 vim 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>
<3>建立test.jsp網頁
vim /web/webapp1/test.jsp 修改
<%@ page language="java" import="java.sql." pageEncoding="GB2312"%>
<html>
<head>
<title>MySQL-1</title>
</head>
<body>
connect MySQL<br>
<%
String driverClass="com.mysql.jdbc.Driver";
String url="jdbc:mysql://192.168.1.80:3306/javatest";
String username = "javauser";
String password = "javapasswd";
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("<br>foo:"+rs.getString(2)+"bar:"+rs.getString(3));
}
rs.close();
stmt.close();
conn.close();
%>
<4>重啓tomcat
40 /usr/local/tomcat/bin/shutdown.sh
41 /usr/local/tomcat/bin/startup.sh
(3)瀏覽器測試