目录
一、Jedis介绍:
1、背景:
2、Jedis连接池介绍:
二、Jedis API:
1、连接池API
2、其他常用API:
三、SpringBoot集成Jedis:
1、Redis集群模式:
(1)配置文件:配置redis、jedis属性信息
(2)Jedis连接池配置类,连接Redis:
(3)Jedis工具类:这里展示基本CRUD操作
2、Redis单机模式:
四、jedis常见应用:
1、Redis五种数据结构基本的增删改查:
2、Redis分布式锁:
(1)加锁:
(2)解锁:
(3)demo:
一、Jedis介绍:
1、背景:
Jedis是基于Java语言的Redis的客户端,Jedis = Java + Redis。Redis不仅可以使用命令来操作,现在基本上主流的语言都有API支持,比如Java、C#、C++、PHP、Node.js、Go等。在官方网站里有一些Java的客户端:Jedis、Redisson、Jredis、JDBC-Redis等,其中官方推荐使用Jedis和Redisson。简言之Jedis是Redis的Java版本API,通过使用Jedis可以操作Redis中的数据。
2、Jedis连接池介绍:
jedis连接资源的创建与销毁是很消耗程序性能,所以jedis为我们提供了jedis的连接池技术,jedis
连接池在创建时初始化一些连接对象存储到连接池中,使用jedis连接资源时不需要自己创建jedis对
象,而是从连接池中获取一个资源进行redis的操作。使用完毕后,不需要销毁该jedis连接资源,
而是将该资源归还给连接池,供其他请求使用。
二、Jedis API:
1、连接池API
JedisPoolConfig配置类 |
功能说明 |
JedisPoolConfig() |
创建一个配置对象,使用无参构造方法就可以了 |
void setMaxTotal() |
设置连接池最大的连接数 |
void setMaxWaitMillis() |
设置得到连接对象Jedis最长等待时间 |
JedisPool连接池类 |
说明 |
JedisPool(配置对象,服务器名,端口号) |
创建连接池 |
Jedis getResource() |
从连接池中得到一个Jedis连接对象 |
void close() |
连接池关闭方法,通常不关闭连接池 |
2、其他常用API:
方法 |
功能 |
new Jedis(host, port) |
创建Jedis的连接,参数:主机名,端口号 |
set(key,value) |
添加一个字符串的键和值 |
get(key) |
得到指定键的值 |
del(key) |
删除指定键和值 |
hset(key,field,value) |
添加一个hash类型的键-字段-值 |
hget(key,field) |
通过hash键-字段得到它的值 |
lpush(key,values) |
从左边添加一个list类型的键和元素 |
lpop(key) |
从左边弹出一个元素 |
rpop(key) |
从右边弹出一个元素 |
close() |
关闭连接 |
三、SpringBoot集成Jedis:
pom依赖:加上redis、jedis依赖
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
实际应用一般采用Redis集群,这里重点看下集群模式下的集成方式。
1、Redis集群模式:
(1)配置文件:配置redis、jedis属性信息
#redis配置
my.redis.server.jedis.pool.maxTotal=500
my.redis.server.jedis.pool.maxIdle=10
my.redis.server.jedis.pool.maxWaitMillis=5000
my.redis.server.jedis.pool.min-idle=5
my.redis.server.timeout=5000
#哨兵配置
my.redis.sentinel.nodes=xxx.xx.xxx.111:26379,xxx.xx.xxx.222:26379,xxx.xx.333:26379
my.redis.sentinel.password=wtyy
my.redis.sentinel.master-name=mymaster
my.redis.sentinel.database=10
my.redis.sentinel.pool.max-total=10
my.redis.sentinel.pool.max-idle=5
my.redis.sentinel.pool.min-idle=5
(2)Jedis连接池配置类,连接Redis:
@Configuration
public class JedisConfig {
private Logger logger = LoggerFactory.getLogger(JedisConfig.class);
@Value("${my.redis.server.jedis.pool.maxTotal}")
private int maxTotal;
@Value("${my.redis.server.jedis.pool.maxIdle}")
private int maxIdle;
@Value("${my.redis.server.jedis.pool.maxWaitMillis}")
private int maxWaitMillis;
@Value("${my.redis.server.timeout}")
private int timeout;
@Value("${my.redis.sentinel.nodes}")
private String redisSentinelNodes;
@Value("${my.redis.sentinel.pool.max-total}")
private int redisSentinelMaxTotal;
@Value("${my.redis.sentinel.pool.max-idle}")
private int redisSentinelMaxIdle;
@Value("${my.redis.sentinel.pool.min-idle}")
private int redisSentinelMinIdle;
@Value("${my.redis.sentinel.master-name}")
private String redisSentinelMasterName;
@Value("${my.redis.sentinel.password}")
private String redisSentinelPassword;
@Value("${my.redis.sentinel.database}")
private int dataBase;
@Bean(name = "jedisPool")
public JedisSentinelPool jedisPool() {
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(maxTotal);
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
//sentinel
String[] hosts = redisSentinelNodes.split(",");
Set<String> sentinels = new HashSet<>(Arrays.asList(hosts));
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setMaxTotal(redisSentinelMaxTotal);
poolConfig.setMaxIdle(redisSentinelMaxIdle);
poolConfig.setMinIdle(redisSentinelMinIdle);
JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(redisSentinelMasterName,
sentinels, jedisPoolConfig,timeout,redisSentinelPassword,dataBase);
return jedisSentinelPool;
}
}
(3)Jedis工具类:这里展示基本CRUD操作
@SuppressWarnings("unused")
@Component
public class RedisClient {
private static boolean BORROW = true; // 在borrow一个事例时是否提前进行validate操作
private static Logger logger = Logger.getLogger(RedisClient.class);
@Autowired
private JedisSentinelPool pool;
/**
* 获取连接
*/
public synchronized Jedis getJedis() {
try {
if (pool != null) {
return pool.getResource();
} else {
return null;
}
} catch (Exception e) {
logger.info("连接池连接异常");
return null;
}
}
/**
* @Description: 关闭连接
* @param @param jedis
* @return void 返回类型
*/
public static void getColse(Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
/**
* 格式化Key
*/
public static String format(String formatKey, String... keyValues) {
if (keyValues == null || keyValues.length == 0) {
return formatKey;
}
StringBuilder key = new StringBuilder();
char[] chars = formatKey.toCharArray();
int index = -1;
boolean inmark = false;
boolean firstinmark = false;
for (int i = 0; i < chars.length; i++) {
char ch = chars[i];
if (ch == '{') {
index++;
inmark = true;
firstinmark = true;
} else if (ch == '}') {
inmark = false;
} else if (inmark) {
if (firstinmark) {
firstinmark = false;
key.append(keyValues[index]);
}
} else {
key.append(chars[i]);
}
}
return key.toString();
}
/********************************** 针对key的操作 **************************************/
/**
* 删除一个key
*
* @param keyFormat
* key标识
* @param keyValues
* key变量
* @return 被删除的keys的数量
*/
public Long del(String keyFormat, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.del(key);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 查询一个key是否存在
*
* @param keyFormat
* key标识
* @param keyValues
* key变量
* @return key是否存在。
*/
public boolean exists(String keyFormat, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.exists(key);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 设置一个key的过期的秒数
*
* @param keyFormat
* key标识
* @param seconds
* 过期的秒数
* @param keyValues
* key变量
* @return 1表示设置成功, 0 表示设置失败或者无法被设置
*/
public Long expire(String keyFormat, int seconds, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.expire(key, seconds);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 设置一个UNIX时间戳的过期时间
*
* @param keyFormat
* key标识
* @param expireDate
* 过期时间
* @param keyValues
* key变量
* @return 1表示设置成功, 0 表示设置失败或者无法被设置
*/
public Long expireAt(String keyFormat, Date expireDate, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.pexpireAt(key, expireDate.getTime());
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 移除给定key的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。
*
* @param keyFormat
* key标识
* @param keyValues
* key变量
* @return 当生存时间移除成功时,返回 1 . 如果 key 不存在或 key 没有设置生存时间,返回 0 .
*/
public Long persist(String keyFormat, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.persist(key);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 设置一个key的过期的毫秒数
*
* <pre>
* 这个命令和 EXPIRE 命令的作用类似,但是它以毫秒为单位设置 key 的生存时间,而不像 EXPIRE 命令那样,以秒为单位。
* </pre>
*
* @param keyFormat
* key标识
* @param milliSeconds
* 过期的毫秒数
* @param keyValues
* key变量
* @return 设置成功,返回 1,不存在或设置失败,返回 0
*/
public Long pexpire(String keyFormat, long milliSeconds,
String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.pexpire(key, milliSeconds);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 获取key的有效毫秒数
*
* <pre>
* 这个命令类似于 TTL 命令,但它以毫秒为单位返回 key 的剩余生存时间,而不是像 TTL 命令那样,以秒为单位。
* </pre>
*
* @param keyFormat
* key标识
* @param keyValues
* key变量
* @return 当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。否则,以毫秒为单位,返回 key
* 的剩余生存时间。
*/
public Long pttl(String keyFormat, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.pttl(key);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 获取key的有效时间(单位:秒)
*
* <pre>
* 以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
* </pre>
*
* @param keyFormat
* key标识
* @param keyValues
* key变量
* @return 当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。否则,以秒为单位,返回 key
* 的剩余生存时间。
*/
public Long ttl(String keyFormat, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.ttl(key);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/********************************** 针对字符串(string)的操作 **************************************/
/**
* 追加一个值到key上
*
* <pre>
* 如果 key 已经存在,并且值为字符串,那么这个命令会把 value 追加到原来值(value)的结尾。
* 如果 key 不存在,那么它将首先创建一个空字符串的key,再执行追加操作,这种情况 APPEND 将类似于 SET 操作。
* </pre>
*
* @param keyFormat
* key标识
* @param value
* 要追加的值
* @param keyValues
* key变量
* @return 返回append后字符串值(value)的长度。
*/
public Long append(String keyFormat, String value, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.append(key, value);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 整数原子减1
*
* <pre>
* 对key对应的数字做减1操作。如果key不存在,那么在操作之前,这个key对应的值会被置为0。
* 如果key有一个错误类型的value或者是一个不能表示成数字的字符串,就返回错误。
* 这个操作最大支持在64位有符号的整型数字。
* </pre>
*
* @param keyFormat
* key标识
* @param keyValues
* key变量
* @return 数字:减小之后的value
*/
public Long decr(String keyFormat, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.decr(key);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 原子减指定的整数
*
* <pre>
* 将key对应的数字减decrement。如果key不存在,操作之前,key就会被置为0。
* 如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。
* 这个操作最多支持64位有符号的正型数字。
* </pre>
*
* @param keyFormat
* key标识
* @param integer
* 要减小的数值
* @param keyValues
* key变量
* @return 返回一个数字:减少之后的value值。
*/
public Long decrby(String keyFormat, long integer, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.decrBy(key, integer);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* @param keyFormat
* key标识
* @param keyValues
* key变量
* @return key对应的value,或者null(key不存在时)
*/
public String get(String keyFormat, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.get(key);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 设置一个key的value,并获取设置前的值
*
* <pre>
* 自动将key对应到value并且返回原来key对应的value。如果key存在但是对应的value不是字符串,就返回错误。
* exp:
* GETSET可以和INCR一起使用实现支持重置的计数功能。
* 举个例子:每当有事件发生的时候,一段程序都会调用INCR给key mycounter加1,但是有时我们需要获取计数器的值,并且自动将其重置为0。
* 这可以通过GETSET mycounter "0"来实现:
* </pre>
*
* @param keyFormat
* key标识
* @param value
* 要设置的值
* @param keyValues
* key变量
* @return 设置之前的值
*/
public String getSet(String keyFormat, String value, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.getSet(key, value);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 执行原子加1操作
*
* <pre>
* 对key对应的数字做加1操作。如果key不存在,那么在操作之前,这个key对应的值会被置为0。
* 如果key有一个错误类型的value或者是一个不能表示成数字的字符串,就返回错误。这个操作最大支持在64位有符号的整型数字。
* 提醒:这是一个string操作,因为Redis没有专用的数字类型。key对应的string都被解释成10进制64位有符号的整型来执行这个操作。
* Redis会用相应的整数表示方法存储整数,所以对于表示数字的字符串,没必要为了用字符串表示整型存储做额外开销。
* </pre>
*
* @param keyFormat
* key标识
* @param keyValues
* key变量
* @return 增加之后的value
*/
public Long incr(String keyFormat, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.incr(key);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 执行原子加1操作,并且设置过期时间(单位:s)
*
* <pre>
* 本操作是在{@linkplain RedisClient#incr(String, String...)}之上增加了一个设置过期时间的操作
* </pre>
*
* @param keyFormat
* key标识
* @param expireTime
* 过期时间(单位:s)
* @param keyValues
* key变量
* @return 增加之后的value
*/
public Long incr(String keyFormat, int expireTime, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
long result = jedis.incr(key);
jedis.expire(key, expireTime);
return result;
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 执行原子增加一个整数
*
* <pre>
* 将key对应的数字加increment。如果key不存在,操作之前,key就会被置为0。
* 如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。这个操作最多支持64位有符号的正型数字。
* 查看方法{@linkplain RedisClient#incr(String, String...)}了解关于增减操作的额外信息。
* </pre>
*
* @param keyFormat
* key标识
* @param increment
* 要增加的数值
* @param keyValues
* key变量
* @return 增加后的value
*/
public Long incrBy(String keyFormat, long increment, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.incrBy(key, increment);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 执行原子增加一个浮点数
*
* <pre>
* 将key对应的数字加increment。如果key不存在,操作之前,key就会被置为0。
* 如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。
* </pre>
*
* @param keyFormat
* key标识
* @param increment
* 要增加的数值
* @param keyValues
* key变量
* @return 增加后的value
*/
public Double incrByFloat(String keyFormat, double increment,
String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.incrByFloat(key, increment);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 设置一个key的value值
*
* <pre>
* 警告:如果key已经存在了,它会被覆盖,而不管它是什么类型。
* </pre>
*
* @param keyFormat
* key标识
* @param value
* 要设置的值
* @param keyValues
* key变量
*
* @return 总是"OK"
*/
public String set(String keyFormat, String value, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.set(key, value);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 设置key-value并设置过期时间(单位:秒)
*
* <pre>
* 设置key对应字符串value,并且设置key在给定的seconds时间之后超时过期。
* 该命令相当于执行了{@link #set(String, String, String...) SET} + {@link #expire(String, int, String...) EXPIRE}.并且该操作是原子的
* </pre>
*
* @param keyFormat
* key标识
* @param seconds
* 超时时间(单位:s)
* @param value
* 设置的值
* @param keyValues
* key变量
* @return 状态码
*/
public String setex(String keyFormat, int seconds, String value,
String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.setex(key, seconds, value);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 设置key-value并设置过期时间(单位:毫秒)
*
* <pre>
* 跟{@link #setex(String, int, String, String...)}效果差不多,唯一区别是超时时间是ms
* </pre>
*
* @param keyFormat
* key标识
* @param milliseconds
* 超时时间(单位:ms)
* @param value
* 设置的值
* @param keyValues
* key变量
* @return 状态码
*/
public String psetex(String keyFormat, int milliseconds, String value,
String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.psetex(key, (long) milliseconds, value);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 设置的一个关键的价值,只有当该键不存在
*
* <pre>
* 如果key不存在,就设置key对应字符串value。在这种情况下,该命令和SET一样。
* 当key已经存在时,就不做任何操作。SETNX是"SET if Not eXists"。
* </pre>
*
* @param keyFormat
* key标识
* @param value
* 设置的value
* @param keyValues
* key变量
* @return 1 如果key被set,0 如果key没有被set
*/
public Long setnx(String keyFormat, String value, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.setnx(key, value);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 设置hash里面一个字段的值
*
* @param keyFormat
* key标识
* @param field
* 字段
* @param value
* 值
* @param keyValues
* key变量
* @return 含义如下:1如果field是一个新的字段 0如果field原来在map里面已经存在
*
*/
public Long hset(String keyFormat, String field, String value,
String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.hset(key, field, value);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/******************************* SET 操作 *************************/
/**
* 添加一个元素到集合(set)里
*
* <pre>
* 添加一个指定的member元素到集合的 key中.
* 如果已经在集合key中存在则忽略.如果集合key 不存在,则新建集合key,并添加member元素到集合key中.
* 如果key 的类型不是集合则返回错误.
* </pre>
*
* @param keyFormat
* key标识
* @param value
* 元素
* @param keyValues
* key变量
* @return 返回新成功添加到集合里元素的数量,不包括已经存在于集合中的元素.
*/
public Long sadd(String keyFormat, String value, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.sadd(key, value);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 获取集合里面的元素数量
*
* @param keyFormat
* key标识
* @param keyValues
* key变量
* @return 集合的基数(元素的数量),如果key不存在,则返回 0.
*/
public Long scard(String keyFormat, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.scard(key);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 获取集合里面的所有key
*
* @param keyFormat
* key标识
* @param keyValues
* key变量
* @return 集合中的所有元素.
*/
public Set<String> smembers(String keyFormat, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.smembers(key);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 删除并获取一个集合里面的元素
*
* <pre>
* 移除并返回一个集合中的随机元素
* 该命令与 {@link #srandmember(String, String...)}相似,不同的是srandmember命令返回一个随机元素但是不移除.
* </pre>
*
* @param keyFormat
* key标识
* @param keyValues
* key变量
* @return 被移除的元素, 当key不存在的时候返回 null .
*/
public String spop(String keyFormat, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.spop(key);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**
* 从集合里删除一个元素
*
* @param keyFormat
* key标识
* @param member
* 要删除的元素
* @param keyValues
* key变量
* @return 从集合中移除元素的个数,不包括不存在的成员.
*/
public Long srem(String keyFormat, String member, String... keyValues) {
String key = format(keyFormat, keyValues);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.srem(key, member);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
/**省略 其他不常用操作**/
}
2、Redis单机模式:
配置方式有两种:
(1)代码配置Redis连接:这里省略jedis的一些属性配置
my.redis.server.host=xxx.xx.xxx
my.redis.server.port=6379
my.redis.server.password = wtyy
my.redis.server.jedis.pool.maxTotal=500
my.redis.server.jedis.pool.maxIdle=10
my.redis.server.jedis.pool.maxWaitMillis=5000
my.redis.server.jedis.pool.min-idle=5
my.redis.server.timeout=5000
@Configuration
public class JedisConfig {
private Logger logger = LoggerFactory.getLogger(JedisConfig.class);
@Value("${my.redis.server.host}")
private String host;
@Value("${my.redis.server.port}")
private int port;
@Value("${my.redis.server.password}")
private String password;
@Value("${my.redis.server.jedis.pool.maxTotal}")
private int maxTotal;
@Value("${my.redis.server.jedis.pool.maxIdle}")
private int maxIdle;
@Value("${my.redis.server.jedis.pool.maxWaitMillis}")
private int maxWaitMillis;
@Value("${my.redis.server.timeout}")
private int timeout;
@Bean(name = "jedisPool")
public JedisPool jedisPool() {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(maxTotal);
config.setMaxIdle(maxIdle);
config.setMaxWaitMillis(maxWaitMillis);
return new JedisPool(config, host, port, timeout,password);
}
}
(2)在配置文件中配置redis连接:不建议使用文章来源:https://www.toymoban.com/news/detail-821354.html
spring.redis.database=1
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=500
spring.redis.pool.min-idle=0
spring.redis.timeout=0
四、jedis常见应用:
1、Redis五种数据结构基本的增删改查:
上面的集成demo中,RedisClient演示过了jedis对于Redis的基本CRUD操作,这里不重复。文章来源地址https://www.toymoban.com/news/detail-821354.html
2、Redis分布式锁:
(1)加锁:
public class RedisTool {
private static final String LOCK_SUCCESS = "OK";
private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "PX";
/**
* 尝试获取分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @param expireTime 超期时间
* @return 是否获取成功
*/
public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (LOCK_SUCCESS.equals(result)) {
return true;
}
return false;
}
}
(2)解锁:
public class RedisTool {
private static final Long RELEASE_SUCCESS = 1L;
/**
* 释放分布式锁
* @param jedis Redis客户端
* @param lockKey 锁
* @param requestId 请求标识
* @return 是否释放成功
*/
public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
if (RELEASE_SUCCESS.equals(result)) {
return true;
}
return false;
}
}
(3)demo:
/**
*异步导出
*/
public void runTask(ExportRecord record) {
logger.info("--------导出XXX任务开始 -------------");
boolean lock = fileExportService.lockTask(record);
if (!lock) {
return;
}
//...todo...导出业务逻辑
fileExportService.finishTask(record);
logger.info("--------导出XXX任务结束 -------------");
}
FileExportCommonServiceImpl{
/**
* redis锁 最长时间 /s
*/
public static final Integer REDIS_LOCK_DOWNLOAD_MAX_TIME = 60 * 2;
@Override
public boolean lockTask(ExportRecord record) {
boolean lock = redisClient.getLock(record.getId(), record.getId(), REDIS_LOCK_DOWNLOAD_MAX_TIME);
if (!lock) {
logger.error("获取锁失败,taskId:{}", record.getId());
return lock;
}
//更新record任务状态为进行中
//todo
return lock;
}
@Override
public boolean finishTask(ExportRecord record) {
record.setTaskEndTime(new Date());
//更新task任务结束时间
//todo
return redisClient.releaseLock(record.getId(), record.getId());
}
}
@SuppressWarnings("unused")
@Component
public class RedisClient {
private final Logger logger = LoggerFactory.getLogger(RedisClient.class);
private final String SUCCESS_OK = "OK";
private final Long SUCCESS_STATUS_LONG = 1L;
// SET IF NOT EXIST,即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作
private final String SET_IF_NOT_EXIST = "NX";
// 给key加一个过期的设置,具体时间由第五个参数决定
private final String SET_WITH_EXPIRE_TIME = "PX";
@Autowired
private JedisSentinelPool jedisPool;
public JedisSentinelPool getJedisPool(){
return jedisPool;
}
/**
* 获取分布式锁
*
* @param lockKey
* key为锁
* @param requestId
* 加锁请求
* @param expireTime
* key的过期时间
* @return
*/
public boolean getLock(String lockKey, String requestId, int expireTime) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
String status = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (SUCCESS_OK.equalsIgnoreCase(status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis 获取分布式锁 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 释放分布式锁
*
* @param lockKey
* @param requestId
*/
public boolean releaseLock(String lockKey, String requestId) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
/*
* 其他请求误解锁问题 if(requestId.equals(jedis.get(lockKey))) { jedis.del(lockKey); }
*/
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object status = jedis.eval(script, Collections.singletonList(lockKey),
Collections.singletonList(requestId));
if (SUCCESS_STATUS_LONG.equals(status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis 释放分布式锁 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 序列化存入对象
*
* @param key
* @param obj
* @return
*/
public boolean set(byte[] key, Object obj) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
String status = jedis.set(key, baos.toByteArray());
if (SUCCESS_OK.equalsIgnoreCase(status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis set 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 取序列化对象
*
* @param key
* @return
*//*
public Object getObj(byte[] key) {
Object ret = null;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
byte[] rets = jedis.get(key);
try{
ByteArrayInputStream bais = new ByteArrayInputStream(rets);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
}catch (Exception e) {
logger.error("ObjectInputStream反序列化对象出错", e);
}
} catch (Exception e) {
logger.error("redis get 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}*/
/**
* hash数据类型存储对象
*
* @param key
* @param obj
* @return
*/
public boolean setHm(String key, Object obj) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
Map<String, String> hash = objToMap(obj);
String status = jedis.hmset(key, hash);
if (SUCCESS_OK.equalsIgnoreCase(status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis setHm 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 修改对象属性
*
* @param key
* @param field
* @param value
* @return
*/
public boolean setHm(String key, String field, String value) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
Long status = jedis.hset(key, field, value);
if (0L == status) {
ret = true;
}
} catch (Exception e) {
logger.error("redis setHm 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 根据fields 查询key对象属性列表
*
* @param key
* @param fields
* @return
*/
public List<String> getHm(String key, String... fields) {
List<String> ret = null;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return null;
}
ret = jedis.hmget(key, fields);
} catch (Exception e) {
logger.error("redis getHm 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 根据fields 查询key对象属性列表
*
* @param key
* @return
*/
public Long incr(String key) {
Long count = null;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return null;
}
count = jedis.incr(key);
} catch (Exception e) {
logger.error("redis incr 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return count;
}
/**
* 根据field 查询key对象属性
*
* @param key
* @param
* @return
*/
public String getHm(String key, String field) {
String ret = null;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return null;
}
ret = jedis.hget(key, field);
} catch (Exception e) {
logger.error("redis getHm 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
}
到了这里,关于Jedis(一)与Redis的关系的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!