Redis概述
redis是以【鍵-值】形式存儲數據的非型數據庫,相較於關係型數據庫性能更高。可以用於緩存、消息中間件等。
Redis 與其他 key - value 緩存產品有以下三個特點:
- Redis支持數據的持久化,可以將內存中的數據保存在磁盤中,重啓的時候可以再次加載進行使用。
- Redis不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。
- Redis支持數據的備份,即master-slave模式的數據備份。
Windows安裝Redis
下載地址:https://github.com/MSOpenTech/redis/releases。
把下載好的Redis-x64-xxx.zip壓縮包解壓到C:\develop文件夾下,內容如下。
接下來,把redis的安裝目錄配置到系統環境變量(參考Java環境變量配置),方便在控制檯打開。
啓動redis服務 :打開cmd窗口 ,運行如下命令。
redis-server
打開redis客戶端: 打開另一個cmd窗口,輸入命令
redis-cli
Linux安裝Redis
下載地址:http://redis.io/download,下載最新穩定版本。
$ wget http://download.redis.io/releases/redis-2.8.17.tar.gz
$ tar xzf redis-2.8.17.tar.gz
$ cd redis-2.8.17
$ make
make完後 redis-2.8.17目錄下會出現編譯後的redis服務程序redis-server,還有用於測試的客戶端程序redis-cli,兩個程序位於安裝目錄 src 目錄下:
啓動redis服務.
$ cd src
$ ./redis-server
打開redis客戶端
$ cd src
$ ./redis-cli
redis>
Ubuntu 安裝Redis
在 Ubuntu 系統安裝 Redis 可以使用以下命令:
$sudo apt-get update
$sudo apt-get install redis-server
啓動 Redis
$ redis-server
打開客戶端
$ redis-cli
Redis命令
Redis數據是以 key value 形式存儲,key全都是字符串,value有5種不同的數據結構可供選擇。
String 字符串
List 列表(類似於LinkedList)
Set 集合(類似於HashSet)
SortedSet 有序集合(類似於LinkedHashSet)
字符串(String)
1.存儲:set key value
2.獲取:get key
3.刪除:del key
哈希(Hash)
1.存儲:hset name key value
2.獲取:
hget key field 獲取指定field對應的value
hgetall key 獲取所有filed對應的value
3.刪除:hdel key field
列表(List)
可以添加一個元素到列表的頭部或者尾部
1.存儲
lpush key element //從左邊添加元素:
rpush key element //從右邊添加元素
2.獲取
lindex mylist index //通過索引獲取元素
lrange key start end //獲取指定範圍的元素
3.修改
lset key index value //通過索引修改列表中的元素
4.刪除
lpop key //刪除最左邊的元素
rpop key //刪除最右邊的元素
集合(Set)
不能存儲重複元素
1.存儲: sadd key value
2.獲取:smembers key //獲取所有元素
3.刪除:srem key value //刪除集合中某一個元素
有序集合(sorted set)
不允許元素重複,也能保證元素有序。
1.存儲:zadd key score value
2.獲取: zrange key start end
3.刪除: zrem key value
通用命令
keys * :查詢所有的鍵
type key : 獲取鍵對應值的數據類型
del key : 刪除指定的key-value
Redis持久化
Redis數據是存儲在內存的,當redis服務器重啓時,或者電腦重啓時,數據就會丟失。Redis提供了持久化機制,可以把redis的數據存儲到硬盤中。
RDB持久化
RDB是Redis的默認持久化方式,在Redis根目錄下有一個redis.windows.conf配置文件,可以用來配置持久化時機。
找到redis.windows.conf文件,用記事本打開,找到以下配置信息。
# after 900 sec (15 min) if at least 1 key changed
save 900 1
# after 300 sec (5 min) if at least 10 keys changed
save 300 10
# after 60 sec if at least 10000 keys changed
save 60 10000
使用cd命令進入redis根目錄,開啓redis服務並讀取配置文件
redis-server.exe redis.windws.conf
AOF持久化
日誌記錄的方式,可以記錄每一條命令的操作。可以每一次命令,都進行持久化。
1.使用記事本編輯redis.windows.conf文件,找到appendonly把後面的no 改爲 yes
appendonly no --> appendonly yes
2.相關配置說明
# appendsync always //每一次操作都進行持久化
appendsync everysec //每一秒進行持久化
# appendsync no //不盡興持久化
使用cd命令進入redis根目錄,開啓redis服務並讀取配置文件
redis-server.exe redis.windws.conf
Jedis使用
Jedis是一款Java語言操作Redis的工具,類似於Jdbc操作Mysql數據庫。
Jedis下載:
Jedis快速入門
//獲取連接
Jedis jedis=new Jedis("localhost",6379);
//操作
jedis.set("username","zhangsan");
//關閉資源
jedis.close();
Jedis操作String
//獲取連接
Jedis jedis=new Jedis("localhost",6379);
//添加數據
jedis.set("username","zhangsan");
jedis.set("password","123");
jedis.set("gender","男");
jedis.setex("age",5,"30"); //天就age=30,5秒後失效。
//刪除數據
jedis.del("username");
//修改數據
jedis.set("password","666");
//獲取數據
String password = jedis.get("password");
System.out.println(password);
//關閉資源
jedis.close();
Jedis操作Hash
//獲取連接
Jedis jedis = new Jedis("localhost", 6379);
//添加數據
jedis.hset("user","username","zhangsan");
jedis.hset("user","password","123");
jedis.hset("user","gender","women");
//刪除數據
jedis.hdel("user","gender");
//修改數據
jedis.hset("user","password","666");
//獲取數據
String password = jedis.hget("user","password");
System.out.println(password);
//獲取所有數據
Map<String, String> user = jedis.hgetAll("user");
System.out.println(user);
//關閉資源
jedis.close();
Jedis操作Lis
//獲取連接
Jedis jedis = new Jedis("localhost", 6379);
jedis.del("mylist");
//添加元素到list
jedis.lpush("mylist","張三","李四","王五");
jedis.lpush("mylist","趙六","周七","劉八");
//刪除元素第一個
jedis.lpop("mylist");
//刪除最後一個
jedis.rpop("mylist");
//獲取指定索引位置的元素
String name = jedis.lindex("mylist", 0);
System.out.println("0索引的元素:"+name);
//獲取所有元素
List<String> users = jedis.lrange("mylist", 0, -1);
for (String user : users) {
System.out.println(user);
}
//修改指定索引的元素
String n = jedis.lset("mylist", 2, "網吧");
System.out.println("被修改的元素:"+n);
List<String> mylist = jedis.lrange("mylist", 0, -1);
System.out.println(mylist);
//關閉資源
jedis.close();
Jedis操作Set
//獲取連接
Jedis jedis = new Jedis("localhost", 6379);
//添加元素
jedis.sadd("myset","孫悟空");
jedis.sadd("myset","豬八戒");
jedis.sadd("myset","沙和尚");
jedis.sadd("myset","唐三藏");
jedis.sadd("myset","白龍馬");
//刪除元素
jedis.srem("myset","白龍馬");
//獲取元素
Set<String> myset = jedis.smembers("myset");
System.out.println(myset);
//關閉資源
jedis.close();
Jedis操作SortedSet
//獲取連接
Jedis jedis = new Jedis("localhost", 6379);
//添加元素
jedis.zadd("sortedSet",1,"孫悟空");
jedis.zadd("sortedSet",2,"豬八戒");
jedis.zadd("sortedSet",3,"沙和尚");
jedis.zadd("sortedSet",4,"唐三藏");
jedis.zadd("sortedSet",5,"白龍馬");
//刪除元素
jedis.zrem("sortedSet","白龍馬");
//獲取元素
Set<String> myset = jedis.zrange("sortedSet",0,-1);
System.out.println(myset);
//關閉資源
jedis.close();
Jedis連接池
Jedis連接池類似於Jdbc連接池,當需要Jedis連接時從連接池獲取連接,使用完畢後再歸還給連接池。下面是jedis連接池的相關配置。
jedis配置文件
#redis服務器的IP
redis.ip=127.0.0.1
#redis服務器的Port
redis.port=6379
#最大連接數
redis.pool.maxTotal=10
#最大空閒的連接數
redis.pool.maxIdle=8
#最小空閒連接數
redis.pool.minIdle=2
#當池內沒有返回對象時,最大等待時間
redis.pool.maxWaitMillis=3000
JedisPoolUtils
爲了獲取連接方便,自定義一個Jedis連接池的工具類
package com.jedispool;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.io.IOException;
import java.util.Properties;
public class JedisPoolUtils {
static JedisPool jedisPool=null;
static {
Properties properties=new Properties();
try {
properties.load(JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties"));
} catch (IOException e) {
e.printStackTrace();
}
//獲取reids的主機地址
String ip = properties.getProperty("redis.ip");
//獲取redis的端口號
String port = properties.getProperty("redis.port");
//獲取最大活動數
String maxTotal = properties.getProperty("redis.pool.maxTotal");
String maxIdle = properties.getProperty("redis.pool.maxIdle");
String minIdle = properties.getProperty("redis.pool.minIdle");
String maxWaitMillis = properties.getProperty("redis.pool.maxWaitMillis");
//設置連接池參數
JedisPoolConfig config=new JedisPoolConfig();
config.setMaxTotal(Integer.parseInt(maxTotal));
config.setMaxIdle(Integer.parseInt(maxIdle));
config.setMinIdle(Integer.parseInt(minIdle));
config.setMaxWaitMillis(Integer.parseInt(maxWaitMillis));
jedisPool=new JedisPool(config,ip,Integer.parseInt(port));
}
//獲取Jedis連接
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
綜合案例
需求: 使用ajax訪問服務器查詢省份列表
1.先從redis緩存中獲取數據
2.存儲中有就使用緩存的,緩存沒有就從數據庫查詢
準備數據庫
-- 創建數據庫
CREATE DATABASE redis;
-- 使用數據庫
USE redis;
-- 創建表格
CREATE TABLE province(
id INT PRIMARY KEY AUTO_INCREMENT,
province VARCHAR(20) NOT NULL
);
-- 添加數據
INSERT INTO province(id,province) VALUE(1,"北京");
INSERT INTO province(id,province) VALUE(2,"上海");
INSERT INTO province(id,province) VALUE(3,"深圳");
INSERT INTO province(id,province) VALUE(4,"廣州");
INSERT INTO province(id,province) VALUE(5,"武漢");
INSERT INTO province(id,province) VALUE(6,"南京");
INSERT INTO province(id,province) VALUE(7,"長沙");
INSERT INTO province(id,province) VALUE(8,"鄭州");
INSERT INTO province(id,province) VALUE(9,"合肥");
搭建環境
把相關jar包,複製到web\WEB-INF\lib目錄下
commons-beanutils-1.8.3.jar
commons-logging-1.1.1.jar
commons-pool2-2.3.jar
druid-1.0.9.jar
jackson-annotations-2.2.3.jar
jackson-core-2.2.3.jar
jackson-databind-2.2.3.jar
javax.servlet.jsp.jstl.jar
jedis-2.7.0.jar
jstl-impl.jar
mysql-connector-java-5.1.18-bin.jar
spring-beans-4.2.4.RELEASE.jar
spring-core-4.2.4.RELEASE.jar
spring-jdbc-4.2.4.RELEASE.jar
spring-tx-4.2.4.RELEASE.jar
jedis.properties
在src目錄下創建jedis.properties配置文件,用於配置reids的相關參數。
#redis服務器的IP
redis.ip=127.0.0.1
#redis服務器的Port
redis.port=6379
#最大連接數
redis.pool.maxTotal=10
#最大空閒的連接數
redis.pool.maxIdle=8
#最小空閒連接數
redis.pool.minIdle=2
#當池內沒有返回對象時,最大等待時間
redis.pool.maxWaitMillis=3000
druid.properties
在src目錄下創建druid.properties配置文件,用戶配置數據庫的相關參數。
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/redis
username=root
password=root
# 初始化連接數量
initialSize=5
# 最大連接數
maxActive=10
# 最大等待時間
maxWait=3000
JdbcUtils.java
創建utils包,把JdbcUtis.java文件複製到utils包下
package com.itheima.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* JDBC工具類 使用Durid連接池
*/
public class JdbcUtils {
private static DataSource ds ;
static {
try {
//1.加載配置文件
Properties pro = new Properties();
//使用ClassLoader加載配置文件,獲取字節輸入流
InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//2.初始化連接池對象
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 獲取連接池對象
*/
public static DataSource getDataSource(){
return ds;
}
/**
* 獲取連接Connection對象
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
}
JedisPoolUtils.java
把JedisPoolUtils.java文件複製到utils包下
package com.itheima.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* JDBC工具類 使用Durid連接池
*/
public class JdbcUtils {
private static DataSource ds ;
static {
try {
//1.加載配置文件
Properties pro = new Properties();
//使用ClassLoader加載配置文件,獲取字節輸入流
InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//2.初始化連接池對象
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 獲取連接池對象
*/
public static DataSource getDataSource(){
return ds;
}
/**
* 獲取連接Connection對象
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
}
數據訪問層
在dao包下,創建ProvinceDaoImpl
import java.util.List;
public class ProvinceDaoImpl implements ProvinceDao {
JdbcTemplate jdbcTemplate=new JdbcTemplate(JdbcUtils.getDataSource());
@Override
public List<Province> findAllProvince() {
String sql="select * from province";
List<Province> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Province.class));
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
return list;
}
}
業務邏輯層
package com.itheima.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.dao.ProvinceDao;
import com.itheima.dao.ProvinceDaoImpl;
import com.itheima.domain.Province;
import com.itheima.utils.JedisPoolUtils;
import redis.clients.jedis.Jedis;
import java.util.List;
public class ProvinceServiceImpl implements ProvinceService{
ProvinceDao provinceDao=new ProvinceDaoImpl();
@Override
public List<Province> findAll() {
List<Province> allProvince = provinceDao.findAllProvince();
return allProvince;
}
@Override
public String findAllJson() {
//先從緩存中獲取
Jedis jedis = JedisPoolUtils.getJedis();
String province_json = jedis.get("province");
//如果緩存沒有,就查詢數據庫
if(province_json==null||province_json.length()==0){
List<Province> list = findAll();
//把list轉換爲json
ObjectMapper mapper=new ObjectMapper();
try {
province_json = mapper.writeValueAsString(list);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
//將json數據存入緩存
jedis.set("province",province_json);
}else {
System.out.println("從緩存獲取數據");
}
return province_json;
}
}
Web層
package com.itheima.web;
import com.itheima.service.ProvinceService;
import com.itheima.service.ProvinceServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/provinceServlet")
public class ProvinceServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setContentType("application/json;charset=utf-8");
ProvinceService provinceService=new ProvinceServiceImpl();
String provinceJson = provinceService.findAllJson();
resp.getWriter().write(provinceJson);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
province.html
在web目錄下創建html頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/jquery-2.1.0.min.js"></script>
<script>
$(function () {
$.get("provinceServlet",{},function (data) {
$(data).each(function () {
//{"id":3,"province":"深圳"}
$("#b1").append("<option id='"+this.id+"'>"+this.province+"</option>");
});
},"json");
})
</script>
</head>
<body>
<select id="b1">
<option>-請選擇省份-</option>
</select>
</body>
</html>