问题描述
spring开发项目的时候 每次访问时 都会查询一次数据库 对于那些不经常修改的数据 每次都查询数据库 性能差 不够优雅
缓存的功能 就是提高性能 减少与数据库的交互
当用户第一次查询的时候 去查询数据库 查询到的内容 一方面返给页面 另外一方面做缓存(存在容器中)
当用户第二次查询的时候 此时缓存中 就有了 此时不用查询数据库 就能够拿到数据
当增删改数据库信息时 把缓存清空
核心流程
用户访问 先看缓存中有没有
如果有 则直接拿出 返回给页面
如果没有则查询数据库 把查询出的内容 放到缓存中
做到数据的实时性 比较麻烦 需要在增删改的时候 清空数据
NoSql,叫非关系型数据库,它的全名Not only sql。 是针对关系型数据库来说的
为了解决高并发、高可用、高可扩展,大数据存储等一系列问题而产生的数据库解决方案
区别一
关系型数据库是需要依赖数据库的关系的 比如说主外键 数据在硬盘上
非关系型数据库依赖特殊结果 比如redis是key-value的数据格式 在内存中 可以持久化
区别二
关系型数据库 有主外键关系
非关系型数据库 没有这个概念
区别三:
关系型数据库: 操作的是硬盘 效率低 安全性稍微高
非关系型数据库(redis) 操作的是内存 效率高 但是不安全 数据可能丢失
Redis是使用c语言开发的一个高性能键值NoSQL数据库。Redis可以通过一些键值类型来存储数据
高性能,持久存储,适应高并发的应用场景。
相比许多键值数据存储,Redis拥有一套较为丰富的数据类型
Redis数据库完全在内存中,使用磁盘仅用于持久性。
Redis可以将数据复制到任意数量的从服务器。
异常快速:Redis的速度非常快,支持丰富的数据类型。读的速度是110000次/s,写的速度是81000次/s 。
操作都是原子性:所有Redis操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。
缓存
存临时数据
github上下载
运行成功页面
注意: Redis存的key-value 但是key只能是字符串 value的取值有如下几个类型
字符串(string)
散列(hash)
列表(list)
集合(set)
有序集合(sortedSet)
list类型: 有顺序 可以重复
set类型:没有顺序 不能重复
sortedSet: 有顺序 不能重复
存值
set key value
取值
get key
存值
mset key value key value ....
取值
mget key1 key2
del key
存值
hset key field fieldValue
取值
hget key field
存值
hmset key field1 field1Value field2 fieldValue2
取值
hmget key field1 field2
语法、
hdel key field1 field2
有顺序 可以重复
右压栈 是指 数据从头添加 数据顺序往后排 类似数据往右压 右压栈
左弹栈 是指 数据从左边弹出
右压栈
lpush key value1 value2 value3
左弹栈
lpop key (从左边弹出第一个)
左压栈: 表示数据从后添加
右弹栈: 表示数据从后弹出
左压栈
rpush key value1 value2 value3
右弹栈
rpop key (从右边弹出一个)
语法
lrange key startIndex endIndex
注意: 当endIndex=-1时 表示查询所有
不能重复 没有顺序
存数据
sadd key value1 value2 value3
取数据
smembers key
语法
srem key value
有序 不能重复
注意:每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
存值
zadd key score1 value1 score2 value2
取值
zrange key startIndex endindex
当endIndex等于-1时 表示查询所有
语法
zrem key value
key* 获得所有的key
key list* 获得以list开头的key
redis是把数据存在内存中的 如果我们的服务器关机 这个时候内存中的数据将不存在 所以呢要做持久化
当服务器再次启动的时候 redis就会把本地数据加载到内存中
这种持久化的方式 是默认的 不用任何配置
它的规则
持久化文件
每一次操作或者每一秒 都会把记录持久化到硬盘中 (费资源) 到底是每一次还是每一秒 取决于配置
开启方式、
Jedis的方式
springdataRedis的方式
创建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();//释放资源 } }
每次操作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); }
第一步 :新建一个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); }
//TODO:等着
redis的数据存在内存中 但是如果数据量比较多 内存占用很大 那么一台机器 可能无法满足需求
这个时候我们可能要搭建redis集群
复制一份配置文件
修改复制的配置文件
根据不同的配置文件分别启动2次
@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(); } }
//TODO:等着
双击安装