Jedis详解—Java通过原生API操作Redis
导入依赖
<!--导入Jedis--> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.5.1</version> </dependency> <!--导入fastjson--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency>
2
. 连接步骤
- 连接Redis服务器(指定主机+Redis服务端口号)
import redis.clients.jedis.Jedis; /** * 饿汉式单例模式建造Redis连接工具 */ public class ConnectionUtils { private static final String HOST = "localhost"; private static final Integer PORT = 6379; private final static Jedis redis = new Jedis(HOST,PORT); public static Jedis getRedis(){ return redis; } }
- 测试连接
public class JedisTest { static Jedis jedis = ConnectionUtils.getRedis(); public static void main(String[] args) { System.out.println("========添加数据==========="); addData(); System.out.println("========获取数据==========="); getData(); } private static void addData(){ //Stringl类型 jedis.set("username","guaika"); jedis.set("password","guaika0210"); //List类型 jedis.lpush("lKey","1","2","3","4"); //Set类型 jedis.sadd("sKey","s1","s2","s3","s4"); //Hash类型 Map<String,String> elements = new HashMap<>(); elements.put("k1","v1"); elements.put("k2","v2"); jedis.hset("hKey",elements); //zset类型 jedis.zadd("zKey",1,"z1"); jedis.zadd("zKey",2,"z2"); jedis.zadd("zKey",5,"z5"); } private static void getData(){ System.out.println("=======keys:"+jedis.keys("*")); System.out.println("=======String:【username:"+jedis.get("username")+"】-----【password:"+jedis.get("password")+"】"); System.out.println("=======List:【"+jedis.lrange("lKey",0,-1).toString()+"】"); System.out.println("弹出栈顶元素:"+jedis.lpop("lKey")); System.out.println("List:【"+jedis.lrange("lKey",0,-1).toString()+"】"); System.out.println("=======Set:【"+jedis.smembers("sKey").toString()+"】"); System.out.println("随机获取元素:"+jedis.srandmember("sKey",2).toString()); System.out.println("随机删除元素:"+jedis.spop("sKey")); System.out.println("Set:【"+jedis.smembers("sKey").toString()+"】"); System.out.println("=======Hash:【"+jedis.hgetAll("hKey")+"】"); System.out.println("获取哈希表中指定字段的值:"+jedis.hget("hKey","k1")); System.out.println("删除指定字段:"+jedis.hdel("hKey","k1")); System.out.println("判断字段是否存在:k1【"+jedis.hexists("hKey","k1")+"】"); System.out.println("Hash:【"+jedis.hgetAll("hKey")+"】"); System.out.println("=======Zset:【"+jedis.zrange("zKey",0,-1)+"】"); System.out.println("按照字段进行正序排序:"+jedis.zrangeByScore("zKey",Integer.MIN_VALUE,Integer.MAX_VALUE)); System.out.println("按照字段进行逆序排序:"+jedis.zrevrangeByScore("zKey",Integer.MIN_VALUE,Integer.MAX_VALUE)); } }
- 测试结果【控制台+Redis后台】
Java控制台查看
========添加数据=========== ========获取数据=========== =======keys:[sKey, lKey, password, zKey, username, num, hKey] =======String:【username:guaika】-----【password:guaika0210】 =======List:【[4, 3, 2, 1]】 弹出栈顶元素:4 List:【[3, 2, 1]】 =======Set:【[s4, s3, s1, s2]】 随机获取元素:[s4, s3] 随机删除元素:s1 Set:【[s4, s3, s2]】 =======Hash:【{k1=v1, k2=v2}】 获取哈希表中指定字段的值:v1 删除指定字段:1 判断字段是否存在:k1【false】 Hash:【{k2=v2}】 =======Zset:【[z1, z2, z5]】 按照字段进行正序排序:[z1, z2, z5] 按照字段进行逆序排序:[]
Redis后台查看
127.0.0.1:6379> keys * 1) "username" 2) "zKey" 3) "num" 4) "hKey" 5) "password" 6) "sKey" 7) "lKey"
SpringBoot整合Redis
-
Springboot通过Spring-data-redis操作Redis;
-
Springboot2.x之后,原始Jedis被替换成了lettuce
-
Jedis和Lettuce的区别
- Jedis 采用直连的方式,线程不安全,可以通过Jedis pool连接池来避免这种不安全性【BIO】
- Lettuce 底层使用netty,实例可以在多个线程中共享,不存在线程不安全的情况【NIO】
整合步骤
导入依赖【spring-data-redis lettuce-core】
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>io.lettuce</groupId> <artifactId>lettcue-core</artifactId> <version>6.0.2 RELEASE</version> </dependency>
2.
配置主机和端口号【在“application.properties”中】
#配置主机 spring.redis.host=localhost #配置端口号 spring.redis.port=6379
3.
测试连接+测试结果
Springboot通过RedisTemplate模板引擎操作Redis,需要注入redisTemplate到Springboot中。
========测试代码============= @SpringBootTest class BootRedisApplicationTests { @Autowired @Qualifier("redisTemplate") //注入redisTemplate private RedisTemplate redisTemplate; @Test void contextLoads() { redisTemplate.opsForValue().set("key1","value1"); System.out.println("测试数据:"+redisTemplate.opsForValue().get("key1")); } } ===========测试结果========== 测试数据:value1
自定义RedisTemplate
Redis一般通过JSON 字符串来传递对象,如果需要传递对象时,应该进行序列化!
======1.自定义RedisTemplate对对象进行序列化====== @Configuration public class RedisConfig { //将自定义的template注册到springboot容器中 @Bean public RedisTemplate<String, Object> template(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); //json序列化配置 Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); //String序列化 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); //key采用string的序列化方式 template.setKeySerializer(stringRedisSerializer); //hash的key采用String的序列化形式 template.setHashKeySerializer(stringRedisSerializer); //value采用json序列化形式 template.setValueSerializer(jackson2JsonRedisSerializer); //hash-value采用json序列化形式 template.setHashValueSerializer(jackson2JsonRedisSerializer); template.afterPropertiesSet(); return template; } } ========2.使用自定义的RedisTemplate======== class BootRedisApplicationTests { @Autowired @Qualifier("template") private RedisTemplate redisTemplate; @Test void contextLoads() { redisTemplate.opsForValue().set("key1","value1"); redisTemplate.opsForValue().set("user",new User("guaika",25)); System.out.println("测试数据:"+redisTemplate.opsForValue().get("key1")); System.out.println("测试数据:"+redisTemplate.opsForValue().get("user")); } } ========3.测试结果========== 测试数据:value1 测试数据:User(name=guaika, age=25)
===扩展:IO体系设计===
相关概念
阻塞和非阻塞
阻塞:调用结果返回之前,当前线程会被挂起,调用线程只有在得到结果之后才会返回。
非阻塞:在不能立刻得到结果之前,该调用不会阻塞当前线程。
同步和异步
同步:调用结果未返回之前,不能执行其他后续操作。
异步:调用结果未返回之前,可以继续执行后续操作。该调用结果通过:监听状态、通知和回调来通知调用者结果。
优势
同步:按顺序处理请求,可以避免死锁和脏读发生。
异步:发送请求不等待返回结果,可以提高运行效率,保证并发。
并行和并发(是否同时进行)
并行:(
多个处理机
)当一个
CPU
执行一个线程时,另一个
CPU
可以执行另一个线程,两个线程互不抢占
CPU
资源,可以同时进行。
并发:(
单个处理机
)
同一时间段
在
同一个处理机
上运行多个处于已启动
—
运行完毕状态之间的程序,任意时刻只有一个程序在处理机上运行。(来回切换,耗费
CPU
资源)。
三种
IO
模式
BIO
模式
:同步阻塞I/O模式—–synchronous同步、blocking阻塞
数据的读写必须阻塞在一个线程内等待完成。(
示例:一排开水壶烧开水
)
NIO
模式
:同步非阻塞I/O模式—synchronous同步,non-blocking非阻塞
数据的读写都是通过通道(channel)在缓冲区(buffer)中完成的,即是面向缓冲区的.
应用场景:各种分布式、即时通信和中间件系统中。
Dubbo
Netty:Java开源NIO框架,提供异步、事件驱动的网络应用程序框架和工具,用于快速开发高性能和高可靠性的网络服务器和客户端程序。
Zookeeper
AIO
模式
:异步非阻塞I/O模式—asynchronous异步,non-blocking非阻塞