一、 redis介紹
redis是一個(gè)key-value存儲(chǔ)系統(tǒng)。和Memcached類(lèi)似,它支持存儲(chǔ)的value類(lèi)型相對(duì)更多,包括
string(字符串)、 list(鏈表)、 set(集合)、 zset(sorted set --有序集合)和hash(哈希類(lèi)型) 。 與memcached
一樣,為了保證效率,數(shù)據(jù)都是緩存在內(nèi)存中。區(qū)別的是redis會(huì)周期性的把更新的數(shù)據(jù)寫(xiě)入磁盤(pán)
或者把修改操作寫(xiě)入追加的記錄文件,并且在此基礎(chǔ)上實(shí)現(xiàn)master-slave(主從)同步。
Redis是一個(gè)高性能的key-value數(shù)據(jù)庫(kù)。 redis的出現(xiàn),很大程度補(bǔ)償了memcached這類(lèi)key/value
存儲(chǔ)的不足,在部分場(chǎng)合可以對(duì)關(guān)系數(shù)據(jù)庫(kù)起到很好的補(bǔ)充作用。它提供了Java, C/C++, C#,
PHP, JavaScript, Perl, Object-C, Python, Ruby等客戶端,使用很方便。
如果簡(jiǎn)單地比較Redis與Memcached的區(qū)別, 基本上有以下3點(diǎn):
1、 Redis不僅僅支持簡(jiǎn)單的k/v類(lèi)型的數(shù)據(jù),同時(shí)還提供list, set, zset, hash等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)。
2、 Redis支持?jǐn)?shù)據(jù)的備份,即master-slave模式的數(shù)據(jù)備份。
3、 Redis支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保持在磁盤(pán)中,重啟的時(shí)候可以再次加載進(jìn)行
使用。
在Redis中,并不是所有的數(shù)據(jù)都一直存儲(chǔ)在內(nèi)存中的。這是和Memcached相比一個(gè)最大的區(qū)別。
Redis只會(huì)緩存所有的key的信息,如果Redis發(fā)現(xiàn)內(nèi)存的使用量超過(guò)了某一個(gè)閥值,將觸發(fā)swap
的操作, Redis根據(jù)“swappability = age*log(size_in_memory)”計(jì)算出哪些key對(duì)應(yīng)的value需要swap
到磁盤(pán)。然后再將這些key對(duì)應(yīng)的value持久化到磁盤(pán)中,同時(shí)在內(nèi)存中清除。這種特性使得Redis
可以保持超過(guò)其機(jī)器本身內(nèi)存大小的數(shù)據(jù)。當(dāng)然,機(jī)器本身的內(nèi)存必須要能夠保持所有的key,
因?yàn)檫@些數(shù)據(jù)是不會(huì)進(jìn)行swap操作的。
當(dāng)從Redis中讀取數(shù)據(jù)的時(shí)候,如果讀取的key對(duì)應(yīng)的value不在內(nèi)存中, 那么Redis就需要從swap
文件中加載相應(yīng)數(shù)據(jù),然后再返回給請(qǐng)求方。
memcached和redis的比較
1、 網(wǎng)絡(luò)IO模型
Memcached是多線程,非阻塞IO復(fù)用的網(wǎng)絡(luò)模型,分為監(jiān)聽(tīng)主線程和worker子線程,監(jiān)聽(tīng)線程監(jiān)
聽(tīng)網(wǎng)絡(luò)連接,接受請(qǐng)求后,將連接描述字pipe 傳遞給worker線程,進(jìn)行讀寫(xiě)IO, 網(wǎng)絡(luò)層使用
libevent封裝的事件庫(kù),多線程模型可以發(fā)揮多核作用。
Redis使用單線程的IO復(fù)用模型,自己封裝了一個(gè)簡(jiǎn)單的AeEvent事件處理框架,主要實(shí)現(xiàn)了epoll、
kqueue和select,對(duì)于單純只有IO操作來(lái)說(shuō),單線程可以將速度優(yōu)勢(shì)發(fā)揮到最大,但是Redis也提
供了一些簡(jiǎn)單的計(jì)算功能,比如排序、聚合等,對(duì)于這些操作,單線程模型實(shí)際會(huì)嚴(yán)重影響整體
吞吐量, CPU計(jì)算過(guò)程中,整個(gè)IO調(diào)度都是被阻塞住的。
2、 內(nèi)存管理方面
Memcached使用預(yù)分配的內(nèi)存池的方式,使用slab和大小不同的chunk來(lái)管理內(nèi)存, value根據(jù)大
小選擇合適的chunk存儲(chǔ)。 Redis使用現(xiàn)場(chǎng)申請(qǐng)內(nèi)存的方式來(lái)存儲(chǔ)數(shù)據(jù)。
3、 存儲(chǔ)方式及其它方面
Memcached基本只支持簡(jiǎn)單的key-value存儲(chǔ),不支持持久化和復(fù)制等功能, Redis除key/value之外,
還支持list,set,sortedset,hash等眾多數(shù)據(jù)結(jié)構(gòu)
二、 如何保持session會(huì)話
目前,為了使web能適應(yīng)大規(guī)模的訪問(wèn),需要實(shí)現(xiàn)應(yīng)用的集群部署。集群最有效的方案就是負(fù)載
均衡,而實(shí)現(xiàn)負(fù)載均衡用戶每一個(gè)請(qǐng)求都有可能被分配到不固定的服務(wù)器上,這樣我們首先要解
決session的統(tǒng)一來(lái)保證無(wú)論用戶的請(qǐng)求被轉(zhuǎn)發(fā)到哪個(gè)服務(wù)器上都能保證用戶的正常使用,即需
要實(shí)現(xiàn)session的共享機(jī)制。
在集群系統(tǒng)下實(shí)現(xiàn)session統(tǒng)一的有如下幾種方案:
1、 請(qǐng)求精確定位: sessionsticky,例如基于訪問(wèn)ip的hash策略, 即當(dāng)前用戶的請(qǐng)求都集中定位
到一臺(tái)服務(wù)器中,這樣單臺(tái)服務(wù)器保存了用戶的session登錄信息,如果宕機(jī),則等同于單點(diǎn)部
署,會(huì)丟失, 會(huì)話不復(fù)制。
2、 session復(fù)制共享: sessionreplication,如tomcat自帶session共享, 主要是指集群環(huán)境下,
多臺(tái)應(yīng)用服務(wù)器之間同步session,使session保持一致,對(duì)外透明。 如果其中一臺(tái)服務(wù)器發(fā)生
故障,根據(jù)負(fù)載均衡的原理, 調(diào)度器會(huì)遍歷尋找可用節(jié)點(diǎn),分發(fā)請(qǐng)求,由于session已同步,故
能保證用戶的session信息不會(huì)丟失, 會(huì)話復(fù)制,。
此方案的不足之處:
必須在同一種中間件之間完成(如:tomcat-tomcat之間).
session復(fù)制帶來(lái)的性能損失會(huì)快速增加.特別是當(dāng)session中保存了較大的對(duì)象,而且對(duì)象變化
較快時(shí), 性能下降更加顯著, 會(huì)消耗系統(tǒng)性能。 這種特性使得web應(yīng)用的水平擴(kuò)展受到了限制。
Session內(nèi)容通過(guò)廣播同步給成員,會(huì)造成網(wǎng)絡(luò)流量瓶頸,即便是內(nèi)網(wǎng)瓶頸。 在大并發(fā)下表現(xiàn)并
不好
3、 基于cache DB緩存的session共享
基于memcache/redis緩存的 session 共享
即使用cacheDB存取session信息,應(yīng)用服務(wù)器接受新請(qǐng)求將session信息保存在cache DB中,當(dāng)
應(yīng)用服務(wù)器發(fā)生故障時(shí), 調(diào)度器會(huì)遍歷尋找可用節(jié)點(diǎn),分發(fā)請(qǐng)求,當(dāng)應(yīng)用服務(wù)器發(fā)現(xiàn)session不
在本機(jī)內(nèi)存時(shí),則去cache DB中查找,如果找到則復(fù)制到本機(jī),這樣實(shí)現(xiàn)session共享和高可用。
三、 nginx+tomcat+redis實(shí)現(xiàn)負(fù)載均衡、 session共享
1、實(shí)驗(yàn)環(huán)境
主機(jī) 操作系統(tǒng) 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
2、實(shí)驗(yàn)拓?fù)?br/>
在這個(gè)圖中, nginx做為反向代理,實(shí)現(xiàn)靜動(dòng)分離,將客戶動(dòng)態(tài)請(qǐng)求根據(jù)權(quán)重隨機(jī)分配給兩臺(tái)tomcat
服務(wù)器, redis做為兩臺(tái)tomcat的共享session數(shù)據(jù)服務(wù)器, mysql做為兩臺(tái)tomcat的后端數(shù)據(jù)庫(kù)。
3、 nginx安裝配置
使用Nginx作為T(mén)omcat的負(fù)載平衡器, Tomcat的會(huì)話Session數(shù)據(jù)存儲(chǔ)在Redis,能夠?qū)崿F(xiàn)零宕機(jī)的
7x24效果。因?yàn)閷?huì)話存儲(chǔ)在Redis中,因此Nginx就不必配置成stick粘貼某個(gè)Tomcat方式,這樣
才能真正實(shí)現(xiàn)后臺(tái)多個(gè)Tomcat負(fù)載平衡。
站在用戶的角度思考問(wèn)題,與客戶深入溝通,找到臨潭網(wǎng)站設(shè)計(jì)與臨潭網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類(lèi)型包括:成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名與空間、網(wǎng)站空間、企業(yè)郵箱。業(yè)務(wù)覆蓋臨潭地區(qū)。
(1) 安裝nginx
安裝nginx依賴(lài)包
yum -y install openssl-devel pcre-devel zlib-devel
編譯安裝nginx
鏈接nginx命令目錄
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
(2)配置nginx反向代理: 反向代理+負(fù)載均衡+健康探測(cè), nginx.conf文件內(nèi)容:
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 / {
# root html;
# 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;
}
50添加
(2) 開(kāi)啟nginx并查看端口
4、安裝部署tomcat應(yīng)用程序服務(wù)器(兩臺(tái)都是)
(1)安裝tomcat并開(kāi)啟,查看端口
20 tar zxf apache-tomcat-8.5.35.tar.gz
將解壓生成的文件夾移動(dòng)到/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
瀏覽器測(cè)試
好了,大家可以看到訪成功。說(shuō)明我們的tomcat安裝完成,下面我們來(lái)修改配置文件
(2)設(shè)置默認(rèn)虛擬主機(jī)
vim /usr/local/tomcat/conf/server.xml 150添加
(3)創(chuàng)建所需目錄和網(wǎng)頁(yè)
30 mkdir -p /web/webapp1
31 vim /web/webapp1/index.jsp
<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
tomcat-1
Session serviced by tomcat
Session ID
<%=session.getId() %>
<% session.setAttribute("abc","abc");%>
Created on
<%= session.getCreationTime() %>
(4)重啟tomcat
(5)瀏覽器測(cè)試
驗(yàn)證健康檢查的方法可以關(guān)掉一臺(tái)tomcat主機(jī),用客戶端瀏覽器測(cè)試訪問(wèn)。從上面的結(jié)果能看出兩次訪問(wèn), nginx把訪問(wèn)請(qǐng)求分別分發(fā)給了后端的tomcat-1和tomcat-2,客戶端的訪問(wèn)請(qǐng)求實(shí)現(xiàn)了負(fù)載均衡,但sessionid并不一樣。 所以,到這里我們準(zhǔn)備工作就全部完成了,下面我們來(lái)配置tomcat通過(guò)redis實(shí)現(xiàn)會(huì)話保持。
5、 安裝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目錄下,執(zhí)行redis初始化腳本install_server.sh
29 cd utils/
30 ./install_server.sh
31 netstat -anput | grep redis
通過(guò)上面的安裝過(guò)程,我們可以看出redis初始化后redis配置文件為
/etc/redis/6379.conf,日志文件為/var/log/redis_6379.log,數(shù)據(jù)文件dump.rdb存
放到/var/lib/redis/6379目錄下,啟動(dòng)腳本為/etc/init.d/redis_6379。
現(xiàn)在我們要使用systemd,所以在 /etc/systems/system 下創(chuàng)建一個(gè)單位文件名字
為 redis_6379.service。
(3)修改 /etc/redis/6379.conf
bind 0.0.0.0 70修改
requirepass 123.com 501去注釋設(shè)置密碼
(4)重啟一下redis并看端口
/etc/init.d/redis_6379 restart
netstat -anput | grep redis
(5)redis測(cè)試
6、 配置tomcat session redis同步 (兩臺(tái)tomcat都是)
(1)下載tomcat-redis-session-manager相應(yīng)的jar包,下載完成后拷貝到$TOMCAT_HOME/lib中
(2)修改/usr/local/tomcat/conf/context.xml 倒數(shù)第二行添加
去注釋
(3)重啟tomcat
(4)redis重啟
(5)瀏覽器測(cè)試
可以看出,分別訪問(wèn)了不同的tomcat,但是得到的session卻是相同的,說(shuō)明達(dá)到了集群的目的。
(6)redis測(cè)試
192.168.1.80 作為mysql數(shù)據(jù)庫(kù)服務(wù)器
(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配置(兩臺(tái)都是)
進(jìn)入配置教程
<1>/usr/local/tomcat/conf/context.xml 倒數(shù)第二行添加
<2>創(chuàng)建所需目錄和網(wǎng)頁(yè)
55 cd /web/webapp1/
56 mkdir WEB-INF
57 vim WEB-INF/web.xml 添加
MySQL Test App
DB Connection
jdbc/TestDB
javax.sql.DataSource
Container
<3>創(chuàng)建test.jsp網(wǎng)頁(yè)
vim /web/webapp1/test.jsp 修改
<%@ page language="java" import="java.sql.*" pageEncoding="GB2312"%>
MySQL-1
connect MySQL
<%
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("
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)瀏覽器測(cè)試