一、Redis概述
在传统的java web项目中,使用数据库进行存储数据,但是有一些致命的弊端,这些弊端主要来自性能方面。由于数据库持久化数据主要是面向磁盘,而磁盘的读/写比较慢,在一般管理系统上,由于不存在高并发,因此往往没有瞬间需要读/写大量数据的要求,这个时候使用数据库进行读/写是没有太大的问题的,但是在互联网中,往往存在大数据量的需求,比如一些商品抢购的场景,或者是主页访问量瞬间比较大的时候,一瞬间成千上万的请求就会到来,需要系统在极短的时间内完成成千上万次的读/写操作,这个时候往往不是数据库能够承受的,极其容易造成数据库系统的瘫痪,最终导致服务宕机的严重问题。
为了克服这些问题,java web项目往往就引入NoSQL技术,NoSQL工具也是一种简易的数据库,它主要是基于内存的数据库,并提供一定的持久化功能。Redis和MongoDB是当前使用最广泛的NoSQL。Redis的性能优越主要来自3个方面。首先,它是基于ANSI C语言编写的,接近于汇编语言的机器语言,运行十分快速。其次,它是基于内存的读/写,速度自然比数据库的磁盘读/写要快的多。最后,它的数据库结构只有6种数据类型,数据结构比较简单,因此规则较少,而数据库则是范式,完整性、规范性需要考虑的规则比较多,处理业务会比较复杂。所以一般而言Redis的速度是正常数据库的几倍到几十倍,如果把命中率高的数据存储在Redis上,通过Redis读/写和操作这些数据,系统的性能就会远超只使用数据库的情况,因此用好Redis对于Java互联网项目的响应速度和性能是至关重要的。
二、Redis在Java web中的应用
1.缓存
在对数据库的读/写操作中,现实的情况是读操作测次数远超写的操作,一般是1:9到3:7的比例,所以需要读的可能性是比写的可能性多的多。一般而言,存储一些常用的数据,比如用户登录的信息;一些主要的业务信息,比如银行会存储一些客户基础信息、银行卡信息、最近交易信息等。
使用Redis作为缓存的读取逻辑如下图:
从图中可以看出:当第一次读取数据的时候,读取Redis的数据就会失败,此时会触发程序读取数据库,把数据读取出来,并且写入Redis。当第二次及以后读取数据时,就直接读取Redis,读到数据后就结束流程,这样速度就大大提高了。
写操作的流程:
2.高速读/写场合
在互联网应用中,往往存在一些需要高速读写的场合,比如商品秒杀,抢红包,淘宝,京东的双十一活动或者春运抢票。这类场合在一个瞬间成千上万的请求就会到达服务器,如果使用的是数据库,一个瞬间数据库就要执行场千上万的SQL,很容易造成数据库的瓶颈,严重会到导致数据库的瘫痪,造成java web系统服务的崩溃。
在这样的场合的应对方法往往是考虑异步写入数据库,而在高速读写场合单单使用Redis去应对,把这些需要高速读写的数据库,缓存到Redis中,而在满足一定的条件下,触发这些缓存的数据写入数据库中。
三、Redis基本安装和使用
1.在Windows下安装Redis
1.1 网址:https://github.com/ServiceStack/redis-windows/tree/master/downloads
1.2为了方便,我们在这个目录新建一个文件startup.cmd
内容为:redis-server redis.windows.conf
这个命令调用redis-server.exe的命令读取redis.window.conf的内容,用来启动redis,保存好了startaup.cmd文件,双击就可以启动Redis。
2.在Linux下安装Redis
首先使用root用户登录Linux系统,然后执行以下命令。
$ cd /usr/
$ mkdir redis
$cd redis
$wget http://download.redis.io/releases/redis-3.2.4.tar.gz
$tar xzf redis-3.2.4.tar.gz
$cd redis-3.2.4
$make
其中wget是下载Redis到当前文件夹的命令,相应的下载地址可能需要改变,tar xzf 命令则是解压文件到当前文件夹。make命令则是安装Redis的命令。
linux系统会有很多命令打开,等待后在当前目录下执行以下代码
src/redis-server
最后可以看到Redis的启动信息,这样Redis就启动好了,为了方便执行Redis命令,可以打开另外一个Linux的命令行窗口,用来启动Redis提供的命令行窗口,一次执行以下命令。
$cd /usr/redis/redis/redis-3.2.4
$src /redis-cli
这样就能够启动Linux的命令行窗口了。
四、Redis的Java API
1. jar包下载位置:http://mvnrepository.com/artifact/redis.clients/jedis
2.简单的连接代码 :
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisTest {
public void testJedis() {
Jedis jedis = testPool().getResource();
// Jedis jedis = new Jedis("localhost", 6379); //连接Redis
// jedis.auth("password");//如果需密码
int i = 0;// 记录操作次数
try {
long start = System.currentTimeMillis();// 开始毫秒数
while (true) {
long end = System.currentTimeMillis();
if (end - start >= 1000) {// 当大于等于1000毫秒(相当于1秒)时,结束操作
break;
}
i++;
jedis.set("test" + i, i + "");
}
} finally {// 关闭连接
jedis.close();
}
System.out.println("redis每秒操作:" + i + "次");// 打印1秒内对Redis的操作次数
}
private JedisPool testPool() {
JedisPoolConfig poolCfg = new JedisPoolConfig();
// 最大空闲数
poolCfg.setMaxIdle(50);
// 最大连接数
poolCfg.setMaxTotal(100);
// 最大等待毫秒数
poolCfg.setMaxWaitMillis(20000);
// 使用配置创建连接池
JedisPool pool = new JedisPool(poolCfg, "localhost");
// 从连接池中获取单个连接
Jedis jedis = pool.getResource();
// 如果需密码
// jedis.auth("password");
return pool;
}
}
第一段代码可以测试redis的写入性能,第二段代码,是连接池的配置。