Java集成Jedis
开始在 Java 中使用 Redis 前, 我们需要确保已经安装并启动 redis 服务及 Java redis 驱动,且你的机器上能正常使用 Java。可以通过Maven进行相关依赖包的导入
搭建工程
-
搭建普通java项目,项目名:jedis-demo
导入Jedis依赖
-
把Jedis和连接池包一起导入进来
commons-pool2-2.2.jar #连接池 jedis-2.5.2.jar #Jedis核心包
编写测试类
@Test
public void testJedis()throws Exception{
//创建连接
String host ="127.0.0.1";
//端口
int port = 6379;
//超时时间,1秒超时
int timeout = 1000;
//jedis客户端
Jedis jedis = new Jedis(host,port,timeout);
//认证
jedis.auth("123456");
//执行操作,保存值
jedis.set("username","jack");
//获取值
String result = jedis.get("username");
System.out.print(result);
//关闭连接
jedis.close();
}
连接池的使用
如果直接使用 Jedis
链接Redis会造成频繁的Jedis对象创建和销毁,对性能会有很大的影响,所以我们会选择使用连接池来链接性能。原理同Mysql连接池
-
编写测试方法,使用
JedisPool
连接池对象 -
@Test public void test()throws Exception{ //1 创建jedispool配置对象 JedisPoolConfig config = new JedisPoolConfig(); //2 做配置 //最大空闲连接数 config.setMaxIdle(2); //最大链接对象数 config.setMaxTotal(10); //链接超时时间 config.setMaxWaitMillis(1*1000); //获取连接是测试连接是否畅通 config.setTestOnBorrow(true); //3 创建jedispool连接池对戏 //参数:配置对象,redis主机地址 ,超时时间,密码 JedisPool pool = new JedisPool(config,"127.0.0.1",6379,1*1000,"123456"); //4 通过jedispool获取连接 Jedis jedis = pool.getResource(); //5 执行操作 jedis.set("age",10); String result = jedis.get("age"); System.out.println(result); // 6 释放连接 , 底层做了兼容,如果是连接池操作就是释放,如果是连接操作就是关闭 jedis.close(); // 7 摧毁连接池-如果是真正项目中它应该是一个受spring管理的单例 pool.destroy(); }
工具类封装:JedisPool应该是单例的(想想你的Mybatis的DataSource也只是创建了一个),为了方便使用,将`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 enum RedisUtils { //使用枚举实现单例 INSTANCE; //连接池对象 private static JedisPool jedisPool = null; static { //初始化链接池 //1 创建连接池配置对象 JedisPoolConfig config = new JedisPoolConfig(); //2 进行配置-四个配置 最小连接数 config.setMaxIdle(1); //最大连接数 config.setMaxTotal(11); //链接最长等待时间 config.setMaxWaitMillis(10 * 1000L); //测试连接时是否畅通 config.setTestOnBorrow(true); String host = "127.0.0.1"; int port = 6379; String password = "123456"; int timeout = 10000; //创建连接池 jedisPool = new JedisPool(config, host,port,timeout, password); } //获取连接 public Jedis getSource() { return jedisPool.getResource(); } //关闭资源 public void closeSource(Jedis jedis) { if (jedis != null) { jedis.close(); } } /** * 设置字符值 * * @param key * @param value */ public void set(String key, String value) { Jedis jedis = getSource(); jedis.set(key, value); closeSource(jedis); } /** * 设置字符值 * * @param key * @param value * @param seconds :过期时间 */ public void setex(String key,int seconds, String value) { Jedis jedis = getSource(); jedis.setex(key,seconds, value); closeSource(jedis); } /** * 设置字符值 * * @param key */ public String get(String key) { Jedis jedis = getSource(); try { return jedis.get(key); } catch (Exception e) { e.printStackTrace(); } finally { closeSource(jedis); } return null; } /** * 设置 * @param key * @param value */ public void set(byte[] key, byte[] value) { Jedis jedis = getSource(); jedis.set(key, value); closeSource(jedis); } /** * * @param key * @return */ public byte[] get(byte[] key) { Jedis jedis = getSource(); try { return jedis.get(key); } catch (Exception e) { e.printStackTrace(); } finally { closeSource(jedis); } return null; } }
Jedis的API操作
使用jedis来操作redis的key和value,而value有很多种类型,和命令操作一样。
key的操作
System.out.println(jedis.keys("*")); //查看所有的key
String的操作
System.out.println(jedis.set("name","zhangsan"));//新增 System.out.println(jedis.get("name"));//获取 System.out.println(jedis.set("name","zhangsan1"));//修改 System.out.println(jedis.get("name"));//获取 System.out.println(jedis.del("name"));//删除
List的操作
-
jedis.lpush("students1","1","2","3","5","6"); //添加数据 System.out.println(jedis.lrange("students1", 0, 3)); //获取数据
-
排序操作,对于数字元素排序不需要加
SortingParams
,对于字符串需要指定SortingParams
,并且指定使用assii值排序 -
/对数字排序 jedis.flushDB(); //添加数据 jedis.lpush("nums","1","2","3","4","8","5","3","1"); //排序 System.out.println(jedis.sort("nums")); //指定排序方式 SortingParams sortingParams1 = new SortingParams(); sortingParams1.desc(); System.out.println(jedis.sort("nums", sortingParams1)); //对字母排序 jedis.lpush("langues","java","php","c++","test","ui"); SortingParams sortingParams = new SortingParams(); sortingParams.alpha(); sortingParams.desc(); System.out.println(jedis.sort("langues",sortingParams));
Set的操作
jedis.sadd("students2","a1","b1","c1","b1"); //添加数据
System.out.println(jedis.smembers("students2")); //获取成员
Hash操作
jedis.hset("students3","student","zhangsan"); //添加数据
System.out.println(jedis.hget("students3", "student")); //获取数据
事务操作
jedis.set("name","zs");
jedis.set("age",18);
//开启事务
Transaction multi = jedis.multi();
multi.incr("name");
multi.incr("age");
//提交事务
List<Object result = multi.exec();
System.out.println(result);
//关闭连接
jedis.close();
//关闭连接池
pool.destory();
springBoot spring data redis
Spring data:spring对数据操作支持规范,但是我们的数据是多种类型,比如rdbms(msyql)、redis(Nosql)、es、mq
Spring data redis :spring操作redis
Spring data jpa :操作关系型数据库
springBoot spring data redis:简化springdata对redis的配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
<!--导入spring data redis 的jar包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
spring:
redis:
host: localhost
port: 6379
password: 123456
jedis:
pool:
max-idle: 8
max-active: 8
max-wait: 2000
Redis的持久化概念
什么是Redis持久化
因为Redis数据基于内存读写,为了防止Redis服务器关闭或者宕机造成数据丢失,我们通常需要对Redis最磁极化,即:把内从中的数据(命令)保存一份到磁盘做一个备份,当Redis服务关闭或者宕机,
在Redis服务器重启的时候会从磁盘重新加载备份的数据,不至于数据丢失。 Redis 提供了两种不同级别的持久化方式:RDB和AOF,可以通过修改redis.conf来进行配置.
开启持久配置后,对Redis进行写操作,在Redis安装目录将会看到持久文件:“appendonly.aof”和“ dump.rdb”。
Redis如何保存数据
redis为了考虑效率,保存数据在内容中.并且考虑数据安全性,还做数据持久化,如果满足保存策略,就会把内存的数据保存到数据rdb文件,还来不及保存那部分数据存放到aof更新日志中。在加载时,把两个数据做一个并集。
Redis持久化-RDB
RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照,默认开启该模式
Redis持久化-AOF
AOF 持久化记录服务器执行的所有写操作命令
,并在服务器启动时,通过重新执行这些命令来还原数据集,默认关闭该模式。
Redis持久配置
配置文件
-
见:redis.windows.conf 或者 redis.conf ,Redis 版本不一样配置文件名字不一样
-
- bind # 指定的ip才能访问
- port #默认端口
- timeout #连接超时
- loglevel #日志的级别
- logfile #日志文件输出路径
- databases #数据库数量
- save 900 1 #RDB持久方式,900 秒有一个数据修改进行持久化
- appendonly #AOF持久方式
Redis持久化配置
根据业务情况修改配置文件中的持久化配置项目即可
RDB和AOP区别
RDB
RDB持久化是指在指定的时间间隔
内将内存中的数据集快照
写入磁盘,实际操作过程是fork一个子进程
,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储 。
RDB优势如下:
1). 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件
,这对于文件备份
而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。
2). 对于灾难恢复而言,RDB是非常不错的选择
。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。
3). 性能最大化
。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。
4). 相比于AOF机制,如果数据集很大,RDB的启动效率会更高
。
RDB劣势如下:
如果你想保证数据的高可用性,即最大限度的避免数据丢失
,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时
,可能会导致整个服务器停止服务
几百毫秒,甚至是1秒钟。
AOF
AOF持久化以日志的形式记录服务器所处理的每一个写、删除
操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。
AOF优势如下:
1). 该机制可以带来更高的数据安全性
,即数据持久性。
2). 由于该机制对日志文件的写入操作采用的是append
模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容
。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。
3). 如果日志过大,Redis可以自动启用rewrite机制
。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。
4). AOF包含一个格式清晰、易于理解
的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。
AOF的劣势如下:
1). 于相同数量的数据集而言,AOF文件通常要大于RDB文件
。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
2). 根据同步策略的不同,AOF在运行效率上往往会慢于RDB
。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。
二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。不过生产环境其实更多都是二者结合使用的。
Redis的淘汰策略
淘汰策略基本概念
为什么要淘汰
Redis的数据读写基于内存,Redis虽然快,但是内存成本还是比较高的,而且基于内存Redis不适合存储太大量的数据。Redis可以使用电脑物理最大内存,当然我们通常会通过设置maxmemory
参数现在Redis内存的使用, 为了让有限的内存空间存储更多的有效数据,我们可以设置淘汰策略,让Redis自动淘汰那些老旧的,或者不怎么被使用的数据。
redis 确定驱逐某个键值对后,会删除这个数据,并将这个数据变更消息发布到本地(AOF 持久化)和从机(主从连接)。
淘汰策略有哪些
-
volatile-lru :从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
-
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
-
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
-
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
-
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
-
no-enviction(驱逐):禁止驱逐数据
淘汰策略配置
最大内存配置
-
修改配置redis.windows.conf,修改maxmemory,放开注释, 根据情况设置大小
maxmemory <bytes
淘汰策略配置
-
修改配置redis.windows.conf ,修改maxmemory-policy ,放开注释,按情况修改策略
写在最后:Redis是常用的一款中间件,在实际开发过程中运用非常广泛,本篇介绍了redis的相关知识,如若想要了解更多,博主之前也发布过一篇关于redis的相关博客,感兴趣的朋友可以前去阅读。博主小,中,大厂均有面试经历,坚持每日分享Java全栈知识,希望能够与大家一起共同进步。