Redis 是一款高性能的 NOSQL 系列的非关系型数据库
key:value
(例如:name:张三
age:23
)
应用场景:对于客户端、服务器、数据库三个方面
客户端向服务器端发出请求:查询一些不太经常发生变化的数据,然后服务器端进行数据库查询,操作关系型数据库非常耗时,(例如:user 表中的几亿条数据)
使用缓存思想(在内存区域开辟一块缓存区域)解决耗时问题:
- 从缓存中获取数据
- 有数据
- 直接返回
- 没有数据
- 从数据库查询
- 将数据放入缓存(使用 Redis 做缓存)
- 返回数据
NoSQL(NoSQL = Not only SQL),意即 “不仅仅是SQL”,是一项全新的数据库理念,泛指非关系型的数据库。
随着互联网 Web2.0 网站的兴起,传统的关系数据库在应付 Web2.0 网站,特别是超大规模和高并发的 SNS 类型的 Web2.0 纯动态网站已经显得力不从心,暴露了很多难以克服的问题,而非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NOSQL 数据库的产就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。
key,value
形式、文档形式、图片形式等等,所以可以存储基础类型以及对象或者是集合等各种格式,而数据库则只支持基础类型。Redis 官网(Linux 版本)
Redis 中文官网
Redis (Windows 版本)GitHub 下载
解压直接可以使用,找到文件:
要先开启服务器端,才能开启客户端
set key value
get key
del key
hset key field value
hget key field
:获取指定的 field 对应的值hgetall key
:获取所有的 field 和 valuehdel key field
lpush key value
:将元素加入列表左边rpush key value
:将元素加入列表右边lrange key start end
:范围获取(如果获取范围是 0 到 -1 ,则就是获取所有)lpop key
:删除列表最左边的元素,并将元素返回rpop key
:删除列表最右边的元素,并将元素返回sadd key value
smembers key
:获取 Set 集合种所有元素srem key value
:删除 Set 集合中的某个元素zadd key score value
zrange key start end
zrem key value
keys *
:查询所有的键type key
:获取键对应的 value 的类型del key
:删除指定的 key valueRedis 是一个内存数据库,当 Redis 服务器重启后,或者电脑重启后,数据会丢失,可以将 Redis 内存中的数据持久化保存到硬盘的文件中。
save 900 1
save 300 10
save 10 5
cd /d 文件夹路径
),客户端依旧双击打开盘符:\存放目录\redis 版本号>redis-server.exe redis.windows.conf
dump.rdb
文件进行存储数据AOF :日志记录的方式,可以记录每一条命令的操作,可以在每一次命令操作后,持久化数据
appendonly no
(默认关闭 aof) → appendonly yes
(开启 aof)(使用时依旧需要重新启动 Redis 服务器,并指定配置文件名称,使用命令行(Windows + R 键输入 cmd,之后打开后输入 cd /d 文件夹路径
),客户端依旧双击打开,进行操作后生成持久化文件:appendonly.aof
)(这种操作对性能影响较大)
# appendfsync always
:(默认被注释)每一次操作都进行持久化appendfsync everysec
:(默认开启)每隔一秒进行一次持久化# appendfsync no
:(默认被注释)不进行持久化Java 客户端 Jedis
Jedis :一款 Java 操作 Redis 数据库的工具’
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-lang3artifactId>
<version>3.3.2version>
dependency>
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
<version>2.7.1version>
dependency>
@Test
public void test01(){
// 1. 获取连接
Jedis jedis = new Jedis("localhost", 6379);
// 2. 操作
jedis.set("username","zhangsan");
// 3. 关闭连接
jedis.close();
}
keys *
查看,使用 get
进行取值 @Test
public void test02(){
// 1. 获取连接
// 如果使用空参构造,默认值“localhost”,6379端口
Jedis jedis = new Jedis();
// 2. 操作
// 存储
jedis.set("username","zhangsan");
// 获取
String username = jedis.get("username");
System.out.println(username);
// 可以使用 setex() 方法存储可以指定过期时间的 key value
jedis.setex("activecode",20,"value"); // 将 activecode:value 键值存入 redis,并且20秒后自动删除该键值对
// 可以存储有时效的激活码,验证码等
// 3. 关闭连接
jedis.close();
}
@Test
public void test03(){
// 1. 获取连接
// 如果使用空参构造,默认值“localhost”,6379端口
Jedis jedis = new Jedis();
// 2. 操作
// 存储 Hash
jedis.hset("user","name","lisi");
jedis.hset("user","age","23");
jedis.hset("user","gender","male");
// 获取 Hash
String name=jedis.hget("user","name");
System.out.println(name);
// 获取 Hash 的所有 map 中的数据
Map<String, String> user = jedis.hgetAll("user");
Set<String> keySet = user.keySet();
for (String key :
keySet) {
// 获取 value
String value = user.get(key);
System.out.println(key+":"+value);
}
// 3. 关闭连接
jedis.close();
}
@Test
public void test04(){
// 1. 获取连接
// 如果使用空参构造,默认值“localhost”,6379端口
Jedis jedis = new Jedis();
// 2. 操作
// List 存储
jedis.lpush("mylist","a","b","c"); // 从左边存
jedis.rpush("mylist","a","b","c"); // 从右边存
// List 范围获取
List<String> mylist = jedis.lrange("mylist", 0, -1);
System.out.println(mylist);
// List 弹出
String element01 = jedis.lpop("mylist"); // c
System.out.println(element01);
String element02 = jedis.rpop("mylist"); // c
System.out.println(element02);
// List 范围获取
List<String> newMylist = jedis.lrange("mylist", 0, -1);
System.out.println(newMylist);
// 3. 关闭连接
jedis.close();
}
@Test
public void test05(){
// 1. 获取连接
// 如果使用空参构造,默认值“localhost”,6379端口
Jedis jedis = new Jedis();
// 2. 操作
// Set 存储
jedis.sadd("myset","java","php","c++");
// Set 获取
Set<String> myset = jedis.smembers("myset");
System.out.println(myset);
// 3. 关闭连接
jedis.close();
}
@Test
public void test06(){
// 1. 获取连接
// 如果使用空参构造,默认值“localhost”,6379端口
Jedis jedis = new Jedis();
// 2. 操作
// sorted set 存储
jedis.zadd("mysortedset",85,"张三");
jedis.zadd("mysortedset",70,"李四");
jedis.zadd("mysortedset",90,"王五");
// sorted set 获取
Set<String> mysortedset = jedis.zrange("mysortedset", 0, -1);
System.out.println(mysortedset);
// 3. 关闭连接
jedis.close();
}
getResource()
方法获取 Jedis 连接 @Test
public void test07(){
// 创建一个配置对象
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(50);
config.setMaxIdle(10);
// 1. 创建 Jedis 连接池对象
JedisPool jedisPool = new JedisPool(config,"localhost",6379);
// 2. 获取连接
Jedis jedis = jedisPool.getResource();
// 3. 使用
jedis.set("key","value");
// 4. 关闭,归还到连接池中
jedis.close();
}
jedis.properties
资源包,内容如下:host=127.0.0.1
port=6379
maxTotal=50
maxIdle=10
public class JedisPoolUtils {
/**
* JedisPool 工具类
* 加载配置文件,配置连接池的参数
* 提供获取连接的方法
*/
private static JedisPool jedisPool;
static {
// 读取配置文件
InputStream inputStream = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties");
// 创建 Properties 对象
Properties properties = new Properties();
// 关联文件
try {
properties.load(inputStream);
}catch (IOException e){
e.printStackTrace();
}
// 获取数据,设置 JedisPoolConfig 中
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(Integer.parseInt((properties.getProperty("maxTotal"))));
config.setMaxIdle(Integer.parseInt((properties.getProperty("maxIdle"))));
// 初始化 JedisPool
jedisPool = new JedisPool(config, properties.getProperty("host"), Integer.parseInt(properties.getProperty("port")));
}
// 获取连接方法
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
@Test
public void test08(){
// 通过连接池工具类获取
Jedis jedis = JedisPoolUtils.getJedis();
// 使用
jedis.set("key","value");
// 关闭,归还到连接池中
jedis.close();
}
案例需求:
- 提供 index.html 页面,页面中有一个省份,下拉列表
- 当页面加载完成后,发送 AJAX 请求,加载所有的省份
index.html
页面进行定义FindProvinceSevlet
服务类:
List
ProvinceService
服务类ProvinceDao
操作数据库的类create table province(
id int primary key auto_increment,
name varchar(20) not null
);
insert into province values (null,'北京');
insert into province values (null,'上海');
insert into province values (null,'广州');
insert into province values (null,'深圳');
druid.properties
数据库连接池资源包文件driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///test
username=root
password=123456
initialSize=5
maxActive=10
maxWait=3000
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>选择title>
<script src="js/jquery-3.6.1.js">script>
<script>
$(function () {
// 发送 AJAX 请求,加载所有省份数据
$.get("provinceServlet",{},function (data) {
// 1. 获取 select
var province=$("#province");
// 2. 遍历 JSON 数组
$(data).each(function () {
// 3. 创建
var option="+this.name+"";
// 4. 调用 select 的 append 追加 option
province.append(option);
})
})
})
script>
head>
<body>
<select id="province">
<option>--请选择省份--option>
select>
body>
html>
public class Province {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public interface ProvinceDao {
public List<Province> findAll();
}
public class ProvinceDaoImpl implements ProvinceDao {
// 声明成员变量 JdbcTemplate
private JdbcTemplate template=new JdbcTemplate(JDBCUtils.getDataSource());
@Override
public List<Province> findAll() {
// 定义 SQL
String sql="select * from province";
// 执行 SQL
List<Province> list = template.query(sql, new BeanPropertyRowMapper<>(Province.class));
return list;
}
}
public interface ProvinceService {
public List<Province> findAll();
public String findAllJson();
}
public class ProvinceServiceImpl implements ProvinceService {
// 声明 dao
private ProvinceDao dao=new ProvinceDaoImpl();
@Override
public List<Province> findAll() {
return dao.findAll();
}
@Override
public String findAllJson() {
// 1. 先从 Redis 中查询数据
// 获取 Redis 客户端连接
Jedis jedis = JedisPoolUtils.getJedis();
String province_json = jedis.get("province");
// 2. 判断 province_json 数据是否为 null
if (province_json==null||province_json.length()==0){
// Redis 中没有数据
System.out.println("Redis 中没有数据,查询数据库。");
// 从数据中查询
List<Province> ps = dao.findAll();
// 将 List 序列化为 JSON
ObjectMapper mapper = new ObjectMapper();
try {
province_json= mapper.writeValueAsString(ps);
}catch (JsonProcessingException e){
e.printStackTrace();
}
// 将 JSON 数据存入 Redis
jedis.set("province",province_json);
// 归还链接
jedis.close();
}else {
System.out.println("Redis 中有数据,查询缓存。");
}
return province_json;
}
}
public class JDBCUtils {
private static DataSource dataSource;
static {
try {
// 加载配置文件
Properties properties = new Properties();
// 使用 ClassLoader 加载配置文件,获取字节输入流
InputStream inputStream = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
properties.load(inputStream);
// 初始化连接池对象
dataSource= DruidDataSourceFactory.createDataSource(properties);
}catch (IOException e){
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
}
/*
获取连接池对象
*/
public static DataSource getDataSource(){return dataSource;}
/*
获取连接 Connection 对象
*/
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
}
@WebServlet("/provinceServlet")
public class ProvinceServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// // 1. 调用 service 查询
// ProvinceServiceImpl service = new ProvinceServiceImpl();
// List list = service.findAll();
// // 2. 序列化 List 为 JSON
// ObjectMapper mapper = new ObjectMapper();
// String json = mapper.writeValueAsString(list);
// 使用 Redis 缓存后的调用 service 查询
ProvinceServiceImpl service = new ProvinceServiceImpl();
String json = service.findAllJson();
System.out.println(json);
// 3. 响应结果
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(json);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}