问题描述
spring开发项目的时候 每次访问时 都会查询一次数据库 对于那些不经常修改的数据 每次都查询数据库 性能差 不够优雅
1. 缓存
缓存的功能 就是提高性能 减少与数据库的交互
1.1. 缓存的思想
-
当用户第一次查询的时候 去查询数据库 查询到的内容 一方面返给页面 另外一方面做缓存(存在容器中)
-
当用户第二次查询的时候 此时缓存中 就有了 此时不用查询数据库 就能够拿到数据
-
当增删改数据库信息时 把缓存清空
核心流程
-
用户访问 先看缓存中有没有
-
如果有 则直接拿出 返回给页面
-
如果没有则查询数据库 把查询出的内容 放到缓存中
1.2. 缓存的弊端
做到数据的实时性 比较麻烦 需要在增删改的时候 清空数据
1.3. 使用Map集合作为缓存
2. 什么是Nosql数据库
NoSql,叫非关系型数据库,它的全名Not only sql。 是针对关系型数据库来说的
3. Nosql数据的分类
4. Nosql的好处
为了解决高并发、高可用、高可扩展,大数据存储等一系列问题而产生的数据库解决方案
5. Nosql和关系型数据库区别
-
区别一
-
关系型数据库是需要依赖数据库的关系的 比如说主外键 数据在硬盘上
-
非关系型数据库依赖特殊结果 比如redis是key-value的数据格式 在内存中 可以持久化
-
-
区别二
-
关系型数据库 有主外键关系
-
非关系型数据库 没有这个概念
-
-
区别三:
-
关系型数据库: 操作的是硬盘 效率低 安全性稍微高
-
非关系型数据库(redis) 操作的是内存 效率高 但是不安全 数据可能丢失
-
6. Redis
6.1. 什么是redis
Redis是使用c语言开发的一个高性能键值NoSQL数据库。Redis可以通过一些键值类型来存储数据
6.2. Redis的特点
-
高性能,持久存储,适应高并发的应用场景。
-
相比许多键值数据存储,Redis拥有一套较为丰富的数据类型
-
Redis数据库完全在内存中,使用磁盘仅用于持久性。
-
Redis可以将数据复制到任意数量的从服务器。
6.3. Redis的优势
-
异常快速:Redis的速度非常快,支持丰富的数据类型。读的速度是110000次/s,写的速度是81000次/s 。
-
操作都是原子性:所有Redis操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。
6.4. Redis的作用
-
缓存
-
存临时数据
6.5. Redis的下载
github上下载
6.6. Redis的文件介绍
6.7. Redis的启动
运行成功页面
6.8. 客户端连接
6.9. Redis的Value的取值
注意: Redis存的key-value 但是key只能是字符串 value的取值有如下几个类型
-
字符串(string)
-
散列(hash)
-
列表(list)
-
集合(set)
-
有序集合(sortedSet)
6.10. List&Set&sortSet区别
-
list类型: 有顺序 可以重复
-
set类型:没有顺序 不能重复
-
sortedSet: 有顺序 不能重复
6.11. String类型的操作
6.11.1. 存取单个数据
-
存值
set key value
-
取值
get key
6.11.2. 存取多个数据
-
存值
mset key value key value ....
-
取值
mget key1 key2
6.11.3. 删除数据
del key
6.12. hash类型操作
6.12.1. 存取单个属性值
-
存值
hset key field fieldValue
-
取值
hget key field
6.12.2. 存取多个属性值
-
存值
hmset key field1 field1Value field2 fieldValue2
-
取值
hmget key field1 field2
6.12.3 删除属性值
-
语法、
hdel key field1 field2
6.13. list集合操作
有顺序 可以重复
6.13.1. 右压栈和左弹栈
右压栈 是指 数据从头添加 数据顺序往后排 类似数据往右压 右压栈
左弹栈 是指 数据从左边弹出
-
右压栈
lpush key value1 value2 value3
-
左弹栈
lpop key (从左边弹出第一个)
6.13.2. 左压栈和右弹栈
左压栈: 表示数据从后添加
右弹栈: 表示数据从后弹出
-
左压栈
rpush key value1 value2 value3
-
右弹栈
rpop key (从右边弹出一个)
6.13.3. 查看数据
-
语法
lrange key startIndex endIndex
注意: 当endIndex=-1时 表示查询所有
6.14. 操作set集合
不能重复 没有顺序
6.14.1. 存取数据
-
存数据
sadd key value1 value2 value3
-
取数据
smembers key
6.14.2. 删除数据
-
语法
srem key value
6.15. 操作sortedSet
有序 不能重复
注意:每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
6.15.1 存取值
-
存值
zadd key score1 value1 score2 value2
-
取值
zrange key startIndex endindex
当endIndex等于-1时 表示查询所有
6.15.2. 删除值
-
语法
zrem key value
6.16. Redis的通用指令
key* 获得所有的key
key list* 获得以list开头的key
6.17. Redis的持久化
redis是把数据存在内存中的 如果我们的服务器关机 这个时候内存中的数据将不存在 所以呢要做持久化
当服务器再次启动的时候 redis就会把本地数据加载到内存中
6.17.1. RDB的方式
这种持久化的方式 是默认的 不用任何配置
-
它的规则
-
持久化文件
6.17.2. AOF的方式
每一次操作或者每一秒 都会把记录持久化到硬盘中 (费资源) 到底是每一次还是每一秒 取决于配置
-
开启方式、
6.18. java操作Redis
-
Jedis的方式
-
springdataRedis的方式
6.18.1.Jedis单独的方式
-
创建java工程
-
导入jar
commons-pool2-2.3.jar
jedis-2.7.0.jar
-
创建测试类
-
注意: junit测试包 通过idea导入
-
对String的操作
-
对hash的操作
-
对List的操作
-
对set的操作
-
sortedSet的操作
-
所有的代码
package com.shangma.cn; import org.junit.Test; import redis.clients.jedis.Jedis; import java.util.List; import java.util.Set; public class RedisTest1 { @Test public void fun() { //如果不写 域名端口 默认就是 本机 默认端口就是6379 // Jedis jedis = new Jedis(); Jedis jedis = new Jedis("localhost", 6379); jedis.set("name", "huige"); String name = jedis.get("name"); System.out.println(name); jedis.close();//释放资源 } // @Test public void fun1() { Jedis jedis = new Jedis(); jedis.hset("wife", "name", "高圆圆"); String name = jedis.hget("wife", "name"); System.out.println(name); jedis.close();//释放资源 } // @Test public void fun2() { Jedis jedis = new Jedis(); //右压栈 //jedis.lpush("s1", "aaa", "bbb", "cccc"); // 左压栈 jedis.rpush("s1", "ddd", "eee"); List<String> si = jedis.lrange("s1", 0, -1); si.forEach(System.out::println); jedis.close();//释放资源 } // @Test public void fun3() { Jedis jedis = new Jedis(); jedis.sadd("s2", "zs", "ls", "ww"); Set<String> s2 = jedis.smembers("s2"); s2.forEach(System.out::println); jedis.close();//释放资源 } // @Test public void fun4() { Jedis jedis = new Jedis(); jedis.zadd("mv",20,"如花"); Set<String> mv = jedis.zrange("mv", 0, -1); mv.forEach(System.out::println); jedis.close();//释放资源 } }
6.18.2. Jedis连接池的方式
每次操作redis都会频繁创建和关闭链接 资源浪费 并且性能不好
所以我们需要连接池 类似数据库连接一样
具体代码
/** * 连接池的使用 */ // @Test public void pool() { JedisPoolConfig config = new JedisPoolConfig(); // 最大空闲数 config.setMaxIdle(10); // 最大连接数 config.setMaxTotal(50); //通过配置类创建连接池 JedisPool pool = new JedisPool(config,"localhost",6379); // 在连接池中取出Jedis连接 Jedis jedis = pool.getResource(); jedis.set("haha","窗前明月光"); String haha = jedis.get("haha"); System.out.println(haha); }
6.18.3. 连接池的封装
-
第一步 :新建一个jedis.properties文件
host=localhost port=6379 maxIdle=10 maxTotal=50
-
第二步:编写工具类
public class JedisUtil { private static JedisPool jedisPool; static { InputStream in = JedisUtil.class.getClassLoader().getResourceAsStream("redis.properties"); Properties properties = new Properties(); try { properties.load(in); JedisPoolConfig config = new JedisPoolConfig(); // 最大空闲数 config.setMaxIdle(Integer.parseInt(properties.getProperty("maxIdle"))); // 最大连接数 config.setMaxTotal(Integer.parseInt(properties.getProperty("maxTotal"))); jedisPool = new JedisPool(config, properties.getProperty("host"), Integer.parseInt(properties.getProperty("port"))); } catch (IOException e) { throw new RuntimeException("配置文件加载失败"); } } /** * 这个是获得Jedis * * @return */ public static Jedis getJedis() { return jedisPool.getResource(); } /** * 释放资源 */ public static void release(Jedis jedis) { //这个表示当前jedis链接 放到我们链接池中 并不是关闭了 jedis.close(); } }
-
第三步 测试
@Test public void pool1() { Jedis jedis = JedisUtil.getJedis(); jedis.set("haha", "窗前明月光"); String haha = jedis.get("haha"); System.out.println(haha); JedisUtil.release(jedis); }
6.18.4. SpringDataRedis操作
//TODO:等着
6.19. Redis集群
redis的数据存在内存中 但是如果数据量比较多 内存占用很大 那么一台机器 可能无法满足需求
这个时候我们可能要搭建redis集群
6.19.1. 集群的搭建
-
复制一份配置文件
-
修改复制的配置文件
-
根据不同的配置文件分别启动2次
6.19.2. Jedis对集群的操作
@Test public void fun() { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(50); config.setMaxIdle(10); JedisShardInfo info1 = new JedisShardInfo("localhost", 6379); JedisShardInfo info2 = new JedisShardInfo("localhost", 7777); List<JedisShardInfo> list = new ArrayList<>(); list.add(info1); list.add(info2); ShardedJedisPool pool = new ShardedJedisPool(config, list); ShardedJedis jedis = pool.getResource(); for (int i = 0; i <100; i++) { jedis.set("name"+i,"huige"+i); } jedis.close(); } }
6.19.3. SpringDataRedis对集群的操作
//TODO:等着
6.20. Redis可视化工具
6.20.1. 安装
双击安装
6.20.2. 连接Redis