5、Redis Jedis实战(含Spring Boot)

本文介绍了如何在Spring Boot项目中使用Jedis,包括单机、Sentinel哨兵模式和Cluster集群模式的配置与实战。重点讲解了application.yml配置、FastJsonRedisSerializer的使用、RedisConfig和RedisUtil的设置,以及JedisConnectionFactory在不同模式下的应用。
摘要由CSDN通过智能技术生成

1、父pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.java.ashare</groupId>
  <artifactId>JavaAction</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>pom</packaging>
  <name>JavaAction</name>
  <description>JavaAction</description>
  
  <modules>
  	<!-- spring boot redis集成 -->
  	<module>SpringBootRedis</module>
  </modules>
  
  <properties>
  	<java.version>1.8</java.version>
  </properties>
  
  <!-- spring boot启动父依赖 -->
  <parent>
  	<groupId>org.springframework.boot</groupId>
   	<artifactId>spring-boot-starter-parent</artifactId>
   	<version>2.1.0.RELEASE</version>
   	<relativePath/>
  </parent>
	
  <dependencies>
  	<dependency>
    	<groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
   	</dependency>
  </dependencies>

  <build>
   	<plugins>
   		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-compiler-plugin</artifactId>
			<configuration>
				<source>${java.version}</source>
				<target>${java.version}</target>
			</configuration>
		</plugin>
    	<plugin>
        	<groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
       	</plugin>
   	</plugins>
  </build>
</project>

2、子pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.java.ashare</groupId>
    <artifactId>JavaAction</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>SpringBootRedis</artifactId>
  <name>SpringBootRedis</name>
  <description>SpringBootRedis</description>
  
  <dependencies>
	<dependency>
    	<groupId>org.springframework.boot</groupId>
      	<artifactId>spring-boot-starter-data-redis</artifactId>
      	<exclusions>
        	<exclusion>
            	<groupId>io.lettuce</groupId>
              	<artifactId>lettuce-core</artifactId>
          	</exclusion>
        </exclusions>
   	</dependency>
   	
   	<dependency>
	    <groupId>org.apache.commons</groupId>
	    <artifactId>commons-pool2</artifactId>
	</dependency>
	
	<dependency>
	  	<groupId>redis.clients</groupId>
	  	<artifactId>jedis</artifactId>
	</dependency>
	
	<dependency>
    	<groupId>com.alibaba</groupId>
		<artifactId>fastjson</artifactId>
		<version>1.2.56</version>
	</dependency>
  </dependencies>
  
  <build>
   	<plugins>
  		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-jar-plugin</artifactId>
			<version>2.6</version>
			<configuration>
			 	<archive>
			  		<manifest>
				   		<addClasspath>true</addClasspath>
				   		<classpathPrefix>lib/</classpathPrefix>
				   		<mainClass>com.java.ashare.config.client.ConfigClientApplication</mainClass>
			  		</manifest>
			 	</archive>
			</configuration>
    	</plugin>
	</plugins>
  </build>
</project>

注意:springboot2之后默认使用lettuce操作redis,所以这里需要单独引入jedis。

3、Jedis单独实战

package com.java.ashare.redis.clients.jedis;

import java.util.Date;
import java.util.HashMap;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisPubSub;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.Transaction;

/**
 * jedis入门实战
 */
public class JedisApplication {

	public static void main(String[] args) {
		
		// jedis连接池配置,JedisPoolConfig继承GenericObjectPoolConfig
		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		jedisPoolConfig.setMaxTotal(20);				// -1: 表示不限制
		jedisPoolConfig.setMaxIdle(20);
		jedisPoolConfig.setMinIdle(0);
		jedisPoolConfig.setMaxWaitMillis(60000);
		jedisPoolConfig.setTestOnBorrow(true);
		jedisPoolConfig.setTestOnReturn(true);
		jedisPoolConfig.setTestWhileIdle(true);
		
		// 创建连接池	【redis单机】
		// new JedisPool(poolConfig, host, port, timeout, password, database);
		// 提供不同构造方法满足不同情况,根据情况选择合适的构造方法
		JedisPool jedisPool = new JedisPool(jedisPoolConfig, "192.168.78.169", 6379);
		
		// 创建连接池	【redis-sentinel哨兵模式高可用】
		// 添加sentinel节点
		/*
		Set<String> sentinels = new HashSet<String>();
		sentinels.add(new HostAndPort("192.168.78.169", 26379).toString());
		sentinels.add(new HostAndPort("192.168.78.169", 26380).toString());
		sentinels.add(new HostAndPort("192.168.78.169", 26381).toString());
		JedisSentinelPool jedisSentinelPool = new JedisSentinelPool("mymaster", sentinels, jedisPoolConfig);
		Jedis jedis = jedisSentinelPool.getResource();
		*/
		
		// 创建连接池	【redis-cluster集群模式】
		// 添加所有主从节点
		/*
		Set<HostAndPort> nodes = new HashSet<HostAndPort>();
		nodes.add(new HostAndPort("192.168.78.169", 6379));
		nodes.add(new HostAndPort("192.168.78.169", 6380));
		nodes.add(new HostAndPort("192.168.78.169", 6381));
		nodes.add(new HostAndPort("192.168.78.169", 6382));
		nodes.add(new HostAndPort("192.168.78.169", 6383));
		nodes.add(new HostAndPort("192.168.78.169", 6384));
		JedisCluster jedisCluster = new JedisCluster(nodes, jedisPoolConfig);
		jedisCluster.set("key", "value");		// 直接使用jedisCluster实例操作
		*/
		
		Jedis jedis = null;
		try {
			// 获取连接
			jedis = jedisPool.getResource();
			
			// 基本操作
			jedis.del("key");
			jedis.del("key", "key1");
			jedis.expire("key", 60);
			jedis.expireAt("key", new Date().getTime());
			jedis.persist("key");						// 设置key永不过期
			jedis.exists("key");
			jedis.exists("key", "key1");
			jedis.dbSize();								// 当前数据库key个数,包含过期key
			jedis.flushDB();							// 清空当前数据库
			jedis.flushAll();							// 清空当前实例,所有库
			jedis.select(0);							// 切换数据库
			jedis.keys("pattern");						// 返回匹配pattern的有效key
			jedis.scan("cursor");						// 生成环境禁用keys,使用scan迭代
			
			// 字符串操作
			jedis.set("key", "value");
			jedis.mset("key", "value", "key1", "value1");
			jedis.setnx("key", "value");
			jedis.set("key", "value", "nx");			// nx: 当key不存在时才设置;xx: 当key存在才设置
			jedis.setex("key", 60, "value");			// 60: 设置过期时间60s
			jedis.set("key", "value", "nx", "ex", 60);	// ex: seconds秒;px: milliseconds毫秒,分布式锁场景下setnx+expire合并,保证原子性
			jedis.get("key");
			jedis.mget("key", "key1");
			jedis.incr("key");
			jedis.incrBy("key", 10);
			jedis.decr("key");
			jedis.decrBy("key", 10);
			
			// 哈希操作
			jedis.hset("key", "field", "value");
			jedis.hsetnx("key", "field", "value");
			jedis.hmset("key", new HashMap<String, String>());
			jedis.hget("key", "field");
			jedis.hmget("key", "field", "field1");
			jedis.hgetAll("key");
			jedis.hexists("key", "field");
			jedis.hdel("key", "field", "field1");
			jedis.hlen("key");
			jedis.hincrBy("key", "field", 1);
			jedis.hincrByFloat("key", "field", 1.1);
			
			// 列表操作
			jedis.lpush("key", "string", "string1");
			jedis.rpush("key", "string", "string1");
			jedis.lpop("key");
			jedis.rpop("key");
			jedis.blpop(60, "key");			// 0: 表示一直阻塞			
			jedis.brpop(60, "key");
			jedis.lrange("key", 0, 10);		// start或end为负数时表示从列表后面获取数据,如-1表示最后一个数据,-2表示倒数第二个数据
			jedis.llen("key");
			
			// 集合操作
			jedis.sadd("key", "member", "member1");
			jedis.srem("key", "member", "member1");
			jedis.smembers("key");
			jedis.scard("key");
			jedis.sismember("key", "member");
			jedis.srandmember("key");		// 随机返回1个成员
			jedis.srandmember("key", 10);	// 随机返回10个成员
			jedis.spop("key");				// 随机弹出1个成员
			jedis.spop("key", 10);			// 随机弹出10个成员
			jedis.sinter("key", "key1");
			jedis.sinterstore("dstkey", "key", "key1");
			jedis.sunion("key", "key1");
			jedis.sunionstore("dstkey", "key", "key1");
			jedis.sdiff("key", "key1");
			jedis.sdiffstore("dstkey", "key", "key1");
			
			// 有序集合操作
			jedis.zadd("key", 80, "member");
			jedis.zadd("key", new HashMap<String, Double>());
			jedis.zcard("key");
			jedis.zcount("key", 0, 100);
			jedis.zrank("key", "member");
			jedis.zrevrank("key", "member");
			jedis.zrange("key", 0, 10);
			jedis.zrevrange("key", 0, 10);
			jedis.zscore("key", "member");
			jedis.zinterstore("dstkey", "set", "set1");
			jedis.zunionstore("dstkey", "set", "set1");
			// ...等等
			
			// 事务
			jedis.watch("key", "key1");
			Transaction transaction = jedis.multi();
			transaction.exec();
			transaction.discard();
		
			// pub/sub
			jedis.subscribe(new JedisPubSub() {
				@Override
				public void onMessage(String channel, String message) {
					System.out.println("channel: " + channel + ", message: " + message);
				}
			}, "channel", "channel1");
			jedis.publish("channel", "message");
			
			// pipeline
			Pipeline pipeline = jedis.pipelined();
			for(int i = 0; i < 10000; i++) {
				pipeline.set("key", "value");
			}
			// 只执行同步但不返回结果
			pipeline.sync();
			// 同步并返回结果
			pipeline.syncAndReturnAll();
		} finally {
			if(jedis != null) {
				// 记住:关闭jedis要放在finally块中,如果使用连接池则归还连接给连接池,如果使用单实例则直接关闭连接
				jedis.close();
			}
		}
	}
}

4、Jedis+SpringBoot实战
【--------------------------------单机--------------------------------】
application.yml

spring: 
  redis: 
    host: 192.168.78.169
    port: 6379
    # password: 123456
    database: 0
    timeout: 60000
    jedis: 
      pool: 
        maxActive: 15
        maxIdle: 15
        minIdle: 0
        maxWait: 30000

FastJsonRedisSerializer.java

package com.java.ashare.redis.config;

import java.nio.charset.Charset;

import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

import com.alibaba.fastjson.JSON;

public class FastJsonRedisSerializer implements RedisSerializer<Object> {

	private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
	private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    
	@Override
	public byte[] serialize(Object t) throws SerializationException {
		
		if (t == null) {
			return null;
        }
        return JSON.toJSONStringWithDateFormat(t, DATE_FORMAT).getBytes(DEFAULT_CHARSET);
	}

	@Override
	public Object deserialize(byte[] bytes) throws SerializationException {
		
		if (bytes == null || bytes.length <= 0) {
            return null;
        }
		
		return new String(bytes, DEFAULT_CHARSET);
	}
}

RedisConfig.java

package com.java.ashare.redis.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {
	
	@Bean
	public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
	
		RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
		
        // key使用字符串序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        
        // value使用fastjson序列化,fastjson比jackson速度快
        FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer();
        redisTemplate.setValueSerializer(fastJsonRedisSerializer);
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
        
        // redisConnectionFactory为JedisConnectionFactory,自动注入进来
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
	} 
}

RedisUtil.java

package com.java.ashare.redis.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;

/**
 * 一、redis自动配置类:RedisRepositoriesAutoConfiguration,可以查看到能配置的属性以及可以使用的bean
 * 		RedisRepositoriesAutoConfiguration源码可知:
 * 			提供了RedisTemplate<Object, Object>和StringRedisTemplate两种RedisTemplate的bean
 * 			区别:
 * 			RedisTemplate<Object, Object>
 * 				keySerializer、valueSerializer、hashKeySerializer、hashValueSerializer
 * 				使用JdkSerializationRedisSerializer做序列化,用redis客户端查看key-value时显示一串十六进制的字符串,可读性很差
 * 				泛型是<Object, Object>,写代码不方便,需要写好多类型转换的代码,不推荐
 * 				
 * 			StringRedisTemplate
 * 				使用StringRedisSerializer做序列化,用redis客户端查看key-value时显示正常的字符串,缺点是key、value必须都是字符串
 * 				如果是对象的话,需要在程序中手动把对象数据转化为json字符串(fastjson)
 * 			
 * 			综上:我们可以自定义bean---RedisTemplate<String, Object>,查看config/RedisConfig
 * 
 * 
 * 二、RedisConnectionFactory实现LettuceConnectionFactory、JedisConnectionFactory
 * 		springboot1.x默认使用JedisConnectionFactory
 * 		springboot2.x默认使用LettuceConnectionFactory,可以通过debug调试查看变量可知
 */
@Component
public class RedisUtil {

	// 自定义redisTemplate
	private static RedisTemplate<String, Object> redisTemplate;
	// 使用springboot提供的stringRedisTemplate
	// private static StringRedisTemplate stringRedisTemplate;
	
	/**
	 * 通过set方法注入redisTemplate(针对静态变量)
	 */
	@Autowired
	public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
		
		RedisUtil.redisTemplate = redisTemplate;
	}
	/*@Autowired
	public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
		
		RedisUtil.stringRedisTemplate = stringRedisTemplate;
	}*/
	
	/**
	 * 获取string操作对象
	 */
	public static ValueOperations<String, Object> valueOperations() {
		
		return RedisUtil.redisTemplate.opsForValue();
	}
	
	/**
	 * 获取hash操作对象
	 */
	public static HashOperations<String, String, Object> hashOperations() {
		
		return RedisUtil.redisTemplate.opsForHash();
	}
	
	/**
	 * 获取list操作对象
	 */
	public static ListOperations<String, Object> listOperations() {
		
		return RedisUtil.redisTemplate.opsForList();
	}
	
	/**
	 * 获取set操作对象
	 */
	public static SetOperations<String, Object> setOperations() {
		
		return RedisUtil.redisTemplate.opsForSet();
	}
	
	/**
	 * 获取zset操作对象
	 */
	public static ZSetOperations<String, Object> zSetOperations() {
		
		return RedisUtil.redisTemplate.opsForZSet();
	}
}

RedisApplication.java

package com.java.ashare.redis;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.java.ashare.redis.utils.RedisUtil;

@SpringBootApplication
public class RedisApplication {

	public static void main(String[] args) {
		
		SpringApplication.run(RedisApplication.class, args);
		
		RedisUtil.valueOperations().set("k1", "v1");
		System.out.println("k1: " + RedisUtil.valueOperations().get("k1"));
	}
}

【--------------------------------sentinel哨兵模式--------------------------------】
在【单机】上做如下修改:
application.yml

spring: 
  redis: 
    database: 0
    timeout: 60000
    # password: 123456
    jedis: 
      pool: 
        maxActive: 15
        maxIdle: 15
        minIdle: 0
        maxWait: 60000
    sentinel: 
      master: mymaster
      nodes: 192.168.78.169:26379,192.168.78.169:26380,192.168.78.169:26381

RedisConfig.java

package com.java.ashare.redis.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {
	@Bean
	public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
	
		RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
		
        // key使用字符串序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        
        // value使用fastjson序列化,fastjson比jackson速度快
        FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer();
        redisTemplate.setValueSerializer(fastJsonRedisSerializer);
        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
        
        // redisConnectionFactory为JedisConnectionFactory,自动注入进来,也可以自定义@Bean(JedisConnectionFactory)覆盖springboot默认的值
        // debug查看redisTemplate中变量clientConfiguration、configuration可知yml配置信息注入进来
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
	}
}

【--------------------------------cluster集群模式--------------------------------】
在【单机】上做如下修改:
application.yml

spring: 
  redis: 
    database: 0
    timeout: 60000
    # password: 123456
    jedis: 
      pool: 
        maxActive: 15
        maxIdle: 15
        minIdle: 0
        maxWait: 60000
    cluster: 
      nodes: 
        - 192.168.78.169:6379
        - 192.168.78.169:6380
        - 192.168.78.169:6381
        - 192.168.78.169:6382
        - 192.168.78.169:6383
        - 192.168.78.169:6384

JedisConnectionFactory说明
1、可以直接使用springboot提供的默认JedisConnectionFactory;
2、自定义@Bean,可以查看JedisConnectionFactory的构造函数,针对变量RedisConfiguration有三种情况:

  1. RedisStandaloneConfiguration对应单机;
  2. RedisSentinelConfiguration对应sentinel哨兵模式;
  3. RedisClusterConfiguration对应集群模式;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值