当前位置:   article > 正文

Redis客户端之Jedis(一)介绍_redis和jedis

redis和jedis

目录

一、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依赖

  1. <!-- redis -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-data-redis</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>redis.clients</groupId>
  8. <artifactId>jedis</artifactId>
  9. </dependency>

实际应用一般采用Redis集群,这里重点看下集群模式下的集成方式。

1、Redis集群模式:
(1)配置文件:配置redis、jedis属性信息
  1. #redis配置
  2. my.redis.server.jedis.pool.maxTotal=500
  3. my.redis.server.jedis.pool.maxIdle=10
  4. my.redis.server.jedis.pool.maxWaitMillis=5000
  5. my.redis.server.jedis.pool.min-idle=5
  6. my.redis.server.timeout=5000
  7. #哨兵配置
  8. my.redis.sentinel.nodes=xxx.xx.xxx.111:26379,xxx.xx.xxx.222:26379,xxx.xx.333:26379
  9. my.redis.sentinel.password=wtyy
  10. my.redis.sentinel.master-name=mymaster
  11. my.redis.sentinel.database=10
  12. my.redis.sentinel.pool.max-total=10
  13. my.redis.sentinel.pool.max-idle=5
  14. my.redis.sentinel.pool.min-idle=5
(2)Jedis连接池配置类,连接Redis:
  1. @Configuration
  2. public class JedisConfig {
  3. private Logger logger = LoggerFactory.getLogger(JedisConfig.class);
  4. @Value("${my.redis.server.jedis.pool.maxTotal}")
  5. private int maxTotal;
  6. @Value("${my.redis.server.jedis.pool.maxIdle}")
  7. private int maxIdle;
  8. @Value("${my.redis.server.jedis.pool.maxWaitMillis}")
  9. private int maxWaitMillis;
  10. @Value("${my.redis.server.timeout}")
  11. private int timeout;
  12. @Value("${my.redis.sentinel.nodes}")
  13. private String redisSentinelNodes;
  14. @Value("${my.redis.sentinel.pool.max-total}")
  15. private int redisSentinelMaxTotal;
  16. @Value("${my.redis.sentinel.pool.max-idle}")
  17. private int redisSentinelMaxIdle;
  18. @Value("${my.redis.sentinel.pool.min-idle}")
  19. private int redisSentinelMinIdle;
  20. @Value("${my.redis.sentinel.master-name}")
  21. private String redisSentinelMasterName;
  22. @Value("${my.redis.sentinel.password}")
  23. private String redisSentinelPassword;
  24. @Value("${my.redis.sentinel.database}")
  25. private int dataBase;
  26. @Bean(name = "jedisPool")
  27. public JedisSentinelPool jedisPool() {
  28. JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
  29. jedisPoolConfig.setMaxTotal(maxTotal);
  30. jedisPoolConfig.setMaxIdle(maxIdle);
  31. jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
  32. //sentinel
  33. String[] hosts = redisSentinelNodes.split(",");
  34. Set<String> sentinels = new HashSet<>(Arrays.asList(hosts));
  35. GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
  36. poolConfig.setMaxTotal(redisSentinelMaxTotal);
  37. poolConfig.setMaxIdle(redisSentinelMaxIdle);
  38. poolConfig.setMinIdle(redisSentinelMinIdle);
  39. JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(redisSentinelMasterName,
  40. sentinels, jedisPoolConfig,timeout,redisSentinelPassword,dataBase);
  41. return jedisSentinelPool;
  42. }
  43. }
(3)Jedis工具类:这里展示基本CRUD操作
  1. @SuppressWarnings("unused")
  2. @Component
  3. public class RedisClient {
  4. private static boolean BORROW = true; // 在borrow一个事例时是否提前进行validate操作
  5. private static Logger logger = Logger.getLogger(RedisClient.class);
  6. @Autowired
  7. private JedisSentinelPool pool;
  8. /**
  9. * 获取连接
  10. */
  11. public synchronized Jedis getJedis() {
  12. try {
  13. if (pool != null) {
  14. return pool.getResource();
  15. } else {
  16. return null;
  17. }
  18. } catch (Exception e) {
  19. logger.info("连接池连接异常");
  20. return null;
  21. }
  22. }
  23. /**
  24. * @Description: 关闭连接
  25. * @param @param jedis
  26. * @return void 返回类型
  27. */
  28. public static void getColse(Jedis jedis) {
  29. if (jedis != null) {
  30. jedis.close();
  31. }
  32. }
  33. /**
  34. * 格式化Key
  35. */
  36. public static String format(String formatKey, String... keyValues) {
  37. if (keyValues == null || keyValues.length == 0) {
  38. return formatKey;
  39. }
  40. StringBuilder key = new StringBuilder();
  41. char[] chars = formatKey.toCharArray();
  42. int index = -1;
  43. boolean inmark = false;
  44. boolean firstinmark = false;
  45. for (int i = 0; i < chars.length; i++) {
  46. char ch = chars[i];
  47. if (ch == '{') {
  48. index++;
  49. inmark = true;
  50. firstinmark = true;
  51. } else if (ch == '}') {
  52. inmark = false;
  53. } else if (inmark) {
  54. if (firstinmark) {
  55. firstinmark = false;
  56. key.append(keyValues[index]);
  57. }
  58. } else {
  59. key.append(chars[i]);
  60. }
  61. }
  62. return key.toString();
  63. }
  64. /********************************** 针对key的操作 **************************************/
  65. /**
  66. * 删除一个key
  67. *
  68. * @param keyFormat
  69. * key标识
  70. * @param keyValues
  71. * key变量
  72. * @return 被删除的keys的数量
  73. */
  74. public Long del(String keyFormat, String... keyValues) {
  75. String key = format(keyFormat, keyValues);
  76. Jedis jedis = null;
  77. try {
  78. jedis = getJedis();
  79. return jedis.del(key);
  80. } finally {
  81. if (jedis != null) {
  82. jedis.close();
  83. }
  84. }
  85. }
  86. /**
  87. * 查询一个key是否存在
  88. *
  89. * @param keyFormat
  90. * key标识
  91. * @param keyValues
  92. * key变量
  93. * @return key是否存在。
  94. */
  95. public boolean exists(String keyFormat, String... keyValues) {
  96. String key = format(keyFormat, keyValues);
  97. Jedis jedis = null;
  98. try {
  99. jedis = getJedis();
  100. return jedis.exists(key);
  101. } finally {
  102. if (jedis != null) {
  103. jedis.close();
  104. }
  105. }
  106. }
  107. /**
  108. * 设置一个key的过期的秒数
  109. *
  110. * @param keyFormat
  111. * key标识
  112. * @param seconds
  113. * 过期的秒数
  114. * @param keyValues
  115. * key变量
  116. * @return 1表示设置成功, 0 表示设置失败或者无法被设置
  117. */
  118. public Long expire(String keyFormat, int seconds, String... keyValues) {
  119. String key = format(keyFormat, keyValues);
  120. Jedis jedis = null;
  121. try {
  122. jedis = getJedis();
  123. return jedis.expire(key, seconds);
  124. } finally {
  125. if (jedis != null) {
  126. jedis.close();
  127. }
  128. }
  129. }
  130. /**
  131. * 设置一个UNIX时间戳的过期时间
  132. *
  133. * @param keyFormat
  134. * key标识
  135. * @param expireDate
  136. * 过期时间
  137. * @param keyValues
  138. * key变量
  139. * @return 1表示设置成功, 0 表示设置失败或者无法被设置
  140. */
  141. public Long expireAt(String keyFormat, Date expireDate, String... keyValues) {
  142. String key = format(keyFormat, keyValues);
  143. Jedis jedis = null;
  144. try {
  145. jedis = getJedis();
  146. return jedis.pexpireAt(key, expireDate.getTime());
  147. } finally {
  148. if (jedis != null) {
  149. jedis.close();
  150. }
  151. }
  152. }
  153. /**
  154. * 移除给定key的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。
  155. *
  156. * @param keyFormat
  157. * key标识
  158. * @param keyValues
  159. * key变量
  160. * @return 当生存时间移除成功时,返回 1 . 如果 key 不存在或 key 没有设置生存时间,返回 0 .
  161. */
  162. public Long persist(String keyFormat, String... keyValues) {
  163. String key = format(keyFormat, keyValues);
  164. Jedis jedis = null;
  165. try {
  166. jedis = getJedis();
  167. return jedis.persist(key);
  168. } finally {
  169. if (jedis != null) {
  170. jedis.close();
  171. }
  172. }
  173. }
  174. /**
  175. * 设置一个key的过期的毫秒数
  176. *
  177. * <pre>
  178. * 这个命令和 EXPIRE 命令的作用类似,但是它以毫秒为单位设置 key 的生存时间,而不像 EXPIRE 命令那样,以秒为单位。
  179. * </pre>
  180. *
  181. * @param keyFormat
  182. * key标识
  183. * @param milliSeconds
  184. * 过期的毫秒数
  185. * @param keyValues
  186. * key变量
  187. * @return 设置成功,返回 1,不存在或设置失败,返回 0
  188. */
  189. public Long pexpire(String keyFormat, long milliSeconds,
  190. String... keyValues) {
  191. String key = format(keyFormat, keyValues);
  192. Jedis jedis = null;
  193. try {
  194. jedis = getJedis();
  195. return jedis.pexpire(key, milliSeconds);
  196. } finally {
  197. if (jedis != null) {
  198. jedis.close();
  199. }
  200. }
  201. }
  202. /**
  203. * 获取key的有效毫秒数
  204. *
  205. * <pre>
  206. * 这个命令类似于 TTL 命令,但它以毫秒为单位返回 key 的剩余生存时间,而不是像 TTL 命令那样,以秒为单位。
  207. * </pre>
  208. *
  209. * @param keyFormat
  210. * key标识
  211. * @param keyValues
  212. * key变量
  213. * @return 当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。否则,以毫秒为单位,返回 key
  214. * 的剩余生存时间。
  215. */
  216. public Long pttl(String keyFormat, String... keyValues) {
  217. String key = format(keyFormat, keyValues);
  218. Jedis jedis = null;
  219. try {
  220. jedis = getJedis();
  221. return jedis.pttl(key);
  222. } finally {
  223. if (jedis != null) {
  224. jedis.close();
  225. }
  226. }
  227. }
  228. /**
  229. * 获取key的有效时间(单位:秒)
  230. *
  231. * <pre>
  232. * 以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
  233. * </pre>
  234. *
  235. * @param keyFormat
  236. * key标识
  237. * @param keyValues
  238. * key变量
  239. * @return 当 key 不存在时,返回 -2 。当 key 存在但没有设置剩余生存时间时,返回 -1 。否则,以秒为单位,返回 key
  240. * 的剩余生存时间。
  241. */
  242. public Long ttl(String keyFormat, String... keyValues) {
  243. String key = format(keyFormat, keyValues);
  244. Jedis jedis = null;
  245. try {
  246. jedis = getJedis();
  247. return jedis.ttl(key);
  248. } finally {
  249. if (jedis != null) {
  250. jedis.close();
  251. }
  252. }
  253. }
  254. /********************************** 针对字符串(string)的操作 **************************************/
  255. /**
  256. * 追加一个值到key上
  257. *
  258. * <pre>
  259. * 如果 key 已经存在,并且值为字符串,那么这个命令会把 value 追加到原来值(value)的结尾。
  260. * 如果 key 不存在,那么它将首先创建一个空字符串的key,再执行追加操作,这种情况 APPEND 将类似于 SET 操作。
  261. * </pre>
  262. *
  263. * @param keyFormat
  264. * key标识
  265. * @param value
  266. * 要追加的值
  267. * @param keyValues
  268. * key变量
  269. * @return 返回append后字符串值(value)的长度。
  270. */
  271. public Long append(String keyFormat, String value, String... keyValues) {
  272. String key = format(keyFormat, keyValues);
  273. Jedis jedis = null;
  274. try {
  275. jedis = getJedis();
  276. return jedis.append(key, value);
  277. } finally {
  278. if (jedis != null) {
  279. jedis.close();
  280. }
  281. }
  282. }
  283. /**
  284. * 整数原子减1
  285. *
  286. * <pre>
  287. * 对key对应的数字做减1操作。如果key不存在,那么在操作之前,这个key对应的值会被置为0。
  288. * 如果key有一个错误类型的value或者是一个不能表示成数字的字符串,就返回错误。
  289. * 这个操作最大支持在64位有符号的整型数字。
  290. * </pre>
  291. *
  292. * @param keyFormat
  293. * key标识
  294. * @param keyValues
  295. * key变量
  296. * @return 数字:减小之后的value
  297. */
  298. public Long decr(String keyFormat, String... keyValues) {
  299. String key = format(keyFormat, keyValues);
  300. Jedis jedis = null;
  301. try {
  302. jedis = getJedis();
  303. return jedis.decr(key);
  304. } finally {
  305. if (jedis != null) {
  306. jedis.close();
  307. }
  308. }
  309. }
  310. /**
  311. * 原子减指定的整数
  312. *
  313. * <pre>
  314. * 将key对应的数字减decrement。如果key不存在,操作之前,key就会被置为0。
  315. * 如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。
  316. * 这个操作最多支持64位有符号的正型数字。
  317. * </pre>
  318. *
  319. * @param keyFormat
  320. * key标识
  321. * @param integer
  322. * 要减小的数值
  323. * @param keyValues
  324. * key变量
  325. * @return 返回一个数字:减少之后的value值。
  326. */
  327. public Long decrby(String keyFormat, long integer, String... keyValues) {
  328. String key = format(keyFormat, keyValues);
  329. Jedis jedis = null;
  330. try {
  331. jedis = getJedis();
  332. return jedis.decrBy(key, integer);
  333. } finally {
  334. if (jedis != null) {
  335. jedis.close();
  336. }
  337. }
  338. }
  339. /**
  340. * @param keyFormat
  341. * key标识
  342. * @param keyValues
  343. * key变量
  344. * @return key对应的value,或者null(key不存在时)
  345. */
  346. public String get(String keyFormat, String... keyValues) {
  347. String key = format(keyFormat, keyValues);
  348. Jedis jedis = null;
  349. try {
  350. jedis = getJedis();
  351. return jedis.get(key);
  352. } finally {
  353. if (jedis != null) {
  354. jedis.close();
  355. }
  356. }
  357. }
  358. /**
  359. * 设置一个key的value,并获取设置前的值
  360. *
  361. * <pre>
  362. * 自动将key对应到value并且返回原来key对应的value。如果key存在但是对应的value不是字符串,就返回错误。
  363. * exp:
  364. * GETSET可以和INCR一起使用实现支持重置的计数功能。
  365. * 举个例子:每当有事件发生的时候,一段程序都会调用INCR给key mycounter加1,但是有时我们需要获取计数器的值,并且自动将其重置为0。
  366. * 这可以通过GETSET mycounter "0"来实现:
  367. * </pre>
  368. *
  369. * @param keyFormat
  370. * key标识
  371. * @param value
  372. * 要设置的值
  373. * @param keyValues
  374. * key变量
  375. * @return 设置之前的值
  376. */
  377. public String getSet(String keyFormat, String value, String... keyValues) {
  378. String key = format(keyFormat, keyValues);
  379. Jedis jedis = null;
  380. try {
  381. jedis = getJedis();
  382. return jedis.getSet(key, value);
  383. } finally {
  384. if (jedis != null) {
  385. jedis.close();
  386. }
  387. }
  388. }
  389. /**
  390. * 执行原子加1操作
  391. *
  392. * <pre>
  393. * 对key对应的数字做加1操作。如果key不存在,那么在操作之前,这个key对应的值会被置为0。
  394. * 如果key有一个错误类型的value或者是一个不能表示成数字的字符串,就返回错误。这个操作最大支持在64位有符号的整型数字。
  395. * 提醒:这是一个string操作,因为Redis没有专用的数字类型。key对应的string都被解释成10进制64位有符号的整型来执行这个操作。
  396. * Redis会用相应的整数表示方法存储整数,所以对于表示数字的字符串,没必要为了用字符串表示整型存储做额外开销。
  397. * </pre>
  398. *
  399. * @param keyFormat
  400. * key标识
  401. * @param keyValues
  402. * key变量
  403. * @return 增加之后的value
  404. */
  405. public Long incr(String keyFormat, String... keyValues) {
  406. String key = format(keyFormat, keyValues);
  407. Jedis jedis = null;
  408. try {
  409. jedis = getJedis();
  410. return jedis.incr(key);
  411. } finally {
  412. if (jedis != null) {
  413. jedis.close();
  414. }
  415. }
  416. }
  417. /**
  418. * 执行原子加1操作,并且设置过期时间(单位:s)
  419. *
  420. * <pre>
  421. * 本操作是在{@linkplain RedisClient#incr(String, String...)}之上增加了一个设置过期时间的操作
  422. * </pre>
  423. *
  424. * @param keyFormat
  425. * key标识
  426. * @param expireTime
  427. * 过期时间(单位:s)
  428. * @param keyValues
  429. * key变量
  430. * @return 增加之后的value
  431. */
  432. public Long incr(String keyFormat, int expireTime, String... keyValues) {
  433. String key = format(keyFormat, keyValues);
  434. Jedis jedis = null;
  435. try {
  436. jedis = getJedis();
  437. long result = jedis.incr(key);
  438. jedis.expire(key, expireTime);
  439. return result;
  440. } finally {
  441. if (jedis != null) {
  442. jedis.close();
  443. }
  444. }
  445. }
  446. /**
  447. * 执行原子增加一个整数
  448. *
  449. * <pre>
  450. * 将key对应的数字加increment。如果key不存在,操作之前,key就会被置为0。
  451. * 如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。这个操作最多支持64位有符号的正型数字。
  452. * 查看方法{@linkplain RedisClient#incr(String, String...)}了解关于增减操作的额外信息。
  453. * </pre>
  454. *
  455. * @param keyFormat
  456. * key标识
  457. * @param increment
  458. * 要增加的数值
  459. * @param keyValues
  460. * key变量
  461. * @return 增加后的value
  462. */
  463. public Long incrBy(String keyFormat, long increment, String... keyValues) {
  464. String key = format(keyFormat, keyValues);
  465. Jedis jedis = null;
  466. try {
  467. jedis = getJedis();
  468. return jedis.incrBy(key, increment);
  469. } finally {
  470. if (jedis != null) {
  471. jedis.close();
  472. }
  473. }
  474. }
  475. /**
  476. * 执行原子增加一个浮点数
  477. *
  478. * <pre>
  479. * 将key对应的数字加increment。如果key不存在,操作之前,key就会被置为0。
  480. * 如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。
  481. * </pre>
  482. *
  483. * @param keyFormat
  484. * key标识
  485. * @param increment
  486. * 要增加的数值
  487. * @param keyValues
  488. * key变量
  489. * @return 增加后的value
  490. */
  491. public Double incrByFloat(String keyFormat, double increment,
  492. String... keyValues) {
  493. String key = format(keyFormat, keyValues);
  494. Jedis jedis = null;
  495. try {
  496. jedis = getJedis();
  497. return jedis.incrByFloat(key, increment);
  498. } finally {
  499. if (jedis != null) {
  500. jedis.close();
  501. }
  502. }
  503. }
  504. /**
  505. * 设置一个key的value值
  506. *
  507. * <pre>
  508. * 警告:如果key已经存在了,它会被覆盖,而不管它是什么类型。
  509. * </pre>
  510. *
  511. * @param keyFormat
  512. * key标识
  513. * @param value
  514. * 要设置的值
  515. * @param keyValues
  516. * key变量
  517. *
  518. * @return 总是"OK"
  519. */
  520. public String set(String keyFormat, String value, String... keyValues) {
  521. String key = format(keyFormat, keyValues);
  522. Jedis jedis = null;
  523. try {
  524. jedis = getJedis();
  525. return jedis.set(key, value);
  526. } finally {
  527. if (jedis != null) {
  528. jedis.close();
  529. }
  530. }
  531. }
  532. /**
  533. * 设置key-value并设置过期时间(单位:秒)
  534. *
  535. * <pre>
  536. * 设置key对应字符串value,并且设置key在给定的seconds时间之后超时过期。
  537. * 该命令相当于执行了{@link #set(String, String, String...) SET} + {@link #expire(String, int, String...) EXPIRE}.并且该操作是原子的
  538. * </pre>
  539. *
  540. * @param keyFormat
  541. * key标识
  542. * @param seconds
  543. * 超时时间(单位:s)
  544. * @param value
  545. * 设置的值
  546. * @param keyValues
  547. * key变量
  548. * @return 状态码
  549. */
  550. public String setex(String keyFormat, int seconds, String value,
  551. String... keyValues) {
  552. String key = format(keyFormat, keyValues);
  553. Jedis jedis = null;
  554. try {
  555. jedis = getJedis();
  556. return jedis.setex(key, seconds, value);
  557. } finally {
  558. if (jedis != null) {
  559. jedis.close();
  560. }
  561. }
  562. }
  563. /**
  564. * 设置key-value并设置过期时间(单位:毫秒)
  565. *
  566. * <pre>
  567. * 跟{@link #setex(String, int, String, String...)}效果差不多,唯一区别是超时时间是ms
  568. * </pre>
  569. *
  570. * @param keyFormat
  571. * key标识
  572. * @param milliseconds
  573. * 超时时间(单位:ms)
  574. * @param value
  575. * 设置的值
  576. * @param keyValues
  577. * key变量
  578. * @return 状态码
  579. */
  580. public String psetex(String keyFormat, int milliseconds, String value,
  581. String... keyValues) {
  582. String key = format(keyFormat, keyValues);
  583. Jedis jedis = null;
  584. try {
  585. jedis = getJedis();
  586. return jedis.psetex(key, (long) milliseconds, value);
  587. } finally {
  588. if (jedis != null) {
  589. jedis.close();
  590. }
  591. }
  592. }
  593. /**
  594. * 设置的一个关键的价值,只有当该键不存在
  595. *
  596. * <pre>
  597. * 如果key不存在,就设置key对应字符串value。在这种情况下,该命令和SET一样。
  598. * 当key已经存在时,就不做任何操作。SETNX是"SET if Not eXists"。
  599. * </pre>
  600. *
  601. * @param keyFormat
  602. * key标识
  603. * @param value
  604. * 设置的value
  605. * @param keyValues
  606. * key变量
  607. * @return 1 如果key被set,0 如果key没有被set
  608. */
  609. public Long setnx(String keyFormat, String value, String... keyValues) {
  610. String key = format(keyFormat, keyValues);
  611. Jedis jedis = null;
  612. try {
  613. jedis = getJedis();
  614. return jedis.setnx(key, value);
  615. } finally {
  616. if (jedis != null) {
  617. jedis.close();
  618. }
  619. }
  620. }
  621. /**
  622. * 设置hash里面一个字段的值
  623. *
  624. * @param keyFormat
  625. * key标识
  626. * @param field
  627. * 字段
  628. * @param value
  629. * 值
  630. * @param keyValues
  631. * key变量
  632. * @return 含义如下:1如果field是一个新的字段 0如果field原来在map里面已经存在
  633. *
  634. */
  635. public Long hset(String keyFormat, String field, String value,
  636. String... keyValues) {
  637. String key = format(keyFormat, keyValues);
  638. Jedis jedis = null;
  639. try {
  640. jedis = getJedis();
  641. return jedis.hset(key, field, value);
  642. } finally {
  643. if (jedis != null) {
  644. jedis.close();
  645. }
  646. }
  647. }
  648. /******************************* SET 操作 *************************/
  649. /**
  650. * 添加一个元素到集合(set)里
  651. *
  652. * <pre>
  653. * 添加一个指定的member元素到集合的 key中.
  654. * 如果已经在集合key中存在则忽略.如果集合key 不存在,则新建集合key,并添加member元素到集合key中.
  655. * 如果key 的类型不是集合则返回错误.
  656. * </pre>
  657. *
  658. * @param keyFormat
  659. * key标识
  660. * @param value
  661. * 元素
  662. * @param keyValues
  663. * key变量
  664. * @return 返回新成功添加到集合里元素的数量,不包括已经存在于集合中的元素.
  665. */
  666. public Long sadd(String keyFormat, String value, String... keyValues) {
  667. String key = format(keyFormat, keyValues);
  668. Jedis jedis = null;
  669. try {
  670. jedis = getJedis();
  671. return jedis.sadd(key, value);
  672. } finally {
  673. if (jedis != null) {
  674. jedis.close();
  675. }
  676. }
  677. }
  678. /**
  679. * 获取集合里面的元素数量
  680. *
  681. * @param keyFormat
  682. * key标识
  683. * @param keyValues
  684. * key变量
  685. * @return 集合的基数(元素的数量),如果key不存在,则返回 0.
  686. */
  687. public Long scard(String keyFormat, String... keyValues) {
  688. String key = format(keyFormat, keyValues);
  689. Jedis jedis = null;
  690. try {
  691. jedis = getJedis();
  692. return jedis.scard(key);
  693. } finally {
  694. if (jedis != null) {
  695. jedis.close();
  696. }
  697. }
  698. }
  699. /**
  700. * 获取集合里面的所有key
  701. *
  702. * @param keyFormat
  703. * key标识
  704. * @param keyValues
  705. * key变量
  706. * @return 集合中的所有元素.
  707. */
  708. public Set<String> smembers(String keyFormat, String... keyValues) {
  709. String key = format(keyFormat, keyValues);
  710. Jedis jedis = null;
  711. try {
  712. jedis = getJedis();
  713. return jedis.smembers(key);
  714. } finally {
  715. if (jedis != null) {
  716. jedis.close();
  717. }
  718. }
  719. }
  720. /**
  721. * 删除并获取一个集合里面的元素
  722. *
  723. * <pre>
  724. * 移除并返回一个集合中的随机元素
  725. * 该命令与 {@link #srandmember(String, String...)}相似,不同的是srandmember命令返回一个随机元素但是不移除.
  726. * </pre>
  727. *
  728. * @param keyFormat
  729. * key标识
  730. * @param keyValues
  731. * key变量
  732. * @return 被移除的元素, 当key不存在的时候返回 null .
  733. */
  734. public String spop(String keyFormat, String... keyValues) {
  735. String key = format(keyFormat, keyValues);
  736. Jedis jedis = null;
  737. try {
  738. jedis = getJedis();
  739. return jedis.spop(key);
  740. } finally {
  741. if (jedis != null) {
  742. jedis.close();
  743. }
  744. }
  745. }
  746. /**
  747. * 从集合里删除一个元素
  748. *
  749. * @param keyFormat
  750. * key标识
  751. * @param member
  752. * 要删除的元素
  753. * @param keyValues
  754. * key变量
  755. * @return 从集合中移除元素的个数,不包括不存在的成员.
  756. */
  757. public Long srem(String keyFormat, String member, String... keyValues) {
  758. String key = format(keyFormat, keyValues);
  759. Jedis jedis = null;
  760. try {
  761. jedis = getJedis();
  762. return jedis.srem(key, member);
  763. } finally {
  764. if (jedis != null) {
  765. jedis.close();
  766. }
  767. }
  768. }
  769. /**省略 其他不常用操作**/
  770. }
2、Redis单机模式:

配置方式有两种:

(1)代码配置Redis连接:这里省略jedis的一些属性配置

  1. my.redis.server.host=xxx.xx.xxx
  2. my.redis.server.port=6379
  3. my.redis.server.password = wtyy
  4. my.redis.server.jedis.pool.maxTotal=500
  5. my.redis.server.jedis.pool.maxIdle=10
  6. my.redis.server.jedis.pool.maxWaitMillis=5000
  7. my.redis.server.jedis.pool.min-idle=5
  8. my.redis.server.timeout=5000
  1. @Configuration
  2. public class JedisConfig {
  3. private Logger logger = LoggerFactory.getLogger(JedisConfig.class);
  4. @Value("${my.redis.server.host}")
  5. private String host;
  6. @Value("${my.redis.server.port}")
  7. private int port;
  8. @Value("${my.redis.server.password}")
  9. private String password;
  10. @Value("${my.redis.server.jedis.pool.maxTotal}")
  11. private int maxTotal;
  12. @Value("${my.redis.server.jedis.pool.maxIdle}")
  13. private int maxIdle;
  14. @Value("${my.redis.server.jedis.pool.maxWaitMillis}")
  15. private int maxWaitMillis;
  16. @Value("${my.redis.server.timeout}")
  17. private int timeout;
  18. @Bean(name = "jedisPool")
  19. public JedisPool jedisPool() {
  20. JedisPoolConfig config = new JedisPoolConfig();
  21. config.setMaxTotal(maxTotal);
  22. config.setMaxIdle(maxIdle);
  23. config.setMaxWaitMillis(maxWaitMillis);
  24. return new JedisPool(config, host, port, timeout,password);
  25. }
  26. }

(2)在配置文件中配置redis连接:不建议使用

  1. spring.redis.database=1
  2. spring.redis.pool.max-active=8
  3. spring.redis.pool.max-wait=-1
  4. spring.redis.pool.max-idle=500
  5. spring.redis.pool.min-idle=0
  6. spring.redis.timeout=0
四、jedis常见应用:
1、Redis五种数据结构基本的增删改查:

上面的集成demo中,RedisClient演示过了jedis对于Redis的基本CRUD操作,这里不重复。

2、Redis分布式锁:
(1)加锁:
  1. public class RedisTool {
  2. private static final String LOCK_SUCCESS = "OK";
  3. private static final String SET_IF_NOT_EXIST = "NX";
  4. private static final String SET_WITH_EXPIRE_TIME = "PX";
  5. /**
  6. * 尝试获取分布式锁
  7. * @param jedis Redis客户端
  8. * @param lockKey 锁
  9. * @param requestId 请求标识
  10. * @param expireTime 超期时间
  11. * @return 是否获取成功
  12. */
  13. public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
  14. String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
  15. if (LOCK_SUCCESS.equals(result)) {
  16. return true;
  17. }
  18. return false;
  19. }
  20. }
(2)解锁:
  1. public class RedisTool {
  2. private static final Long RELEASE_SUCCESS = 1L;
  3. /**
  4. * 释放分布式锁
  5. * @param jedis Redis客户端
  6. * @param lockKey 锁
  7. * @param requestId 请求标识
  8. * @return 是否释放成功
  9. */
  10. public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {
  11. String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
  12. Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
  13. if (RELEASE_SUCCESS.equals(result)) {
  14. return true;
  15. }
  16. return false;
  17. }
  18. }
(3)demo:
  1. /**
  2. *异步导出
  3. */
  4. public void runTask(ExportRecord record) {
  5. logger.info("--------导出XXX任务开始 -------------");
  6. boolean lock = fileExportService.lockTask(record);
  7. if (!lock) {
  8. return;
  9. }
  10. //...todo...导出业务逻辑
  11. fileExportService.finishTask(record);
  12. logger.info("--------导出XXX任务结束 -------------");
  13. }
  14. FileExportCommonServiceImpl{
  15. /**
  16. * redis锁 最长时间 /s
  17. */
  18. public static final Integer REDIS_LOCK_DOWNLOAD_MAX_TIME = 60 * 2;
  19. @Override
  20. public boolean lockTask(ExportRecord record) {
  21. boolean lock = redisClient.getLock(record.getId(), record.getId(), REDIS_LOCK_DOWNLOAD_MAX_TIME);
  22. if (!lock) {
  23. logger.error("获取锁失败,taskId:{}", record.getId());
  24. return lock;
  25. }
  26. //更新record任务状态为进行中
  27. //todo
  28. return lock;
  29. }
  30. @Override
  31. public boolean finishTask(ExportRecord record) {
  32. record.setTaskEndTime(new Date());
  33. //更新task任务结束时间
  34. //todo
  35. return redisClient.releaseLock(record.getId(), record.getId());
  36. }
  37. }
  1. @SuppressWarnings("unused")
  2. @Component
  3. public class RedisClient {
  4. private final Logger logger = LoggerFactory.getLogger(RedisClient.class);
  5. private final String SUCCESS_OK = "OK";
  6. private final Long SUCCESS_STATUS_LONG = 1L;
  7. // SET IF NOT EXIST,即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作
  8. private final String SET_IF_NOT_EXIST = "NX";
  9. //key加一个过期的设置,具体时间由第五个参数决定
  10. private final String SET_WITH_EXPIRE_TIME = "PX";
  11. @Autowired
  12. private JedisSentinelPool jedisPool;
  13. public JedisSentinelPool getJedisPool(){
  14. return jedisPool;
  15. }
  16. /**
  17. * 获取分布式锁
  18. *
  19. * @param lockKey
  20. * key为锁
  21. * @param requestId
  22. * 加锁请求
  23. * @param expireTime
  24. * key的过期时间
  25. * @return
  26. */
  27. public boolean getLock(String lockKey, String requestId, int expireTime) {
  28. boolean ret = false;
  29. Jedis jedis = null;
  30. try {
  31. jedis = jedisPool.getResource();
  32. if (jedis == null) {
  33. return ret;
  34. }
  35. String status = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
  36. if (SUCCESS_OK.equalsIgnoreCase(status)) {
  37. ret = true;
  38. }
  39. } catch (Exception e) {
  40. logger.error("redis 获取分布式锁 出错", e);
  41. jedisPool.returnBrokenResource(jedis);
  42. } finally {
  43. if (null != jedis) {
  44. jedisPool.returnResource(jedis);
  45. }
  46. }
  47. return ret;
  48. }
  49. /**
  50. * 释放分布式锁
  51. *
  52. * @param lockKey
  53. * @param requestId
  54. */
  55. public boolean releaseLock(String lockKey, String requestId) {
  56. boolean ret = false;
  57. Jedis jedis = null;
  58. try {
  59. jedis = jedisPool.getResource();
  60. if (jedis == null) {
  61. return ret;
  62. }
  63. /*
  64. * 其他请求误解锁问题 if(requestId.equals(jedis.get(lockKey))) { jedis.del(lockKey); }
  65. */
  66. String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
  67. Object status = jedis.eval(script, Collections.singletonList(lockKey),
  68. Collections.singletonList(requestId));
  69. if (SUCCESS_STATUS_LONG.equals(status)) {
  70. ret = true;
  71. }
  72. } catch (Exception e) {
  73. logger.error("redis 释放分布式锁 出错", e);
  74. jedisPool.returnBrokenResource(jedis);
  75. } finally {
  76. if (null != jedis) {
  77. jedisPool.returnResource(jedis);
  78. }
  79. }
  80. return ret;
  81. }
  82. /**
  83. * 序列化存入对象
  84. *
  85. * @param key
  86. * @param obj
  87. * @return
  88. */
  89. public boolean set(byte[] key, Object obj) {
  90. boolean ret = false;
  91. Jedis jedis = null;
  92. try {
  93. jedis = jedisPool.getResource();
  94. if (jedis == null) {
  95. return ret;
  96. }
  97. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  98. ObjectOutputStream oos = new ObjectOutputStream(baos);
  99. oos.writeObject(obj);
  100. String status = jedis.set(key, baos.toByteArray());
  101. if (SUCCESS_OK.equalsIgnoreCase(status)) {
  102. ret = true;
  103. }
  104. } catch (Exception e) {
  105. logger.error("redis set 出错", e);
  106. jedisPool.returnBrokenResource(jedis);
  107. } finally {
  108. if (null != jedis) {
  109. jedisPool.returnResource(jedis);
  110. }
  111. }
  112. return ret;
  113. }
  114. /**
  115. * 取序列化对象
  116. *
  117. * @param key
  118. * @return
  119. *//*
  120. public Object getObj(byte[] key) {
  121. Object ret = null;
  122. Jedis jedis = null;
  123. try {
  124. jedis = jedisPool.getResource();
  125. if (jedis == null) {
  126. return ret;
  127. }
  128. byte[] rets = jedis.get(key);
  129. try{
  130. ByteArrayInputStream bais = new ByteArrayInputStream(rets);
  131. ObjectInputStream ois = new ObjectInputStream(bais);
  132. return ois.readObject();
  133. }catch (Exception e) {
  134. logger.error("ObjectInputStream反序列化对象出错", e);
  135. }
  136. } catch (Exception e) {
  137. logger.error("redis get 出错", e);
  138. jedisPool.returnBrokenResource(jedis);
  139. } finally {
  140. if (null != jedis) {
  141. jedisPool.returnResource(jedis);
  142. }
  143. }
  144. return ret;
  145. }*/
  146. /**
  147. * hash数据类型存储对象
  148. *
  149. * @param key
  150. * @param obj
  151. * @return
  152. */
  153. public boolean setHm(String key, Object obj) {
  154. boolean ret = false;
  155. Jedis jedis = null;
  156. try {
  157. jedis = jedisPool.getResource();
  158. if (jedis == null) {
  159. return ret;
  160. }
  161. Map<String, String> hash = objToMap(obj);
  162. String status = jedis.hmset(key, hash);
  163. if (SUCCESS_OK.equalsIgnoreCase(status)) {
  164. ret = true;
  165. }
  166. } catch (Exception e) {
  167. logger.error("redis setHm 出错", e);
  168. jedisPool.returnBrokenResource(jedis);
  169. } finally {
  170. if (null != jedis) {
  171. jedisPool.returnResource(jedis);
  172. }
  173. }
  174. return ret;
  175. }
  176. /**
  177. * 修改对象属性
  178. *
  179. * @param key
  180. * @param field
  181. * @param value
  182. * @return
  183. */
  184. public boolean setHm(String key, String field, String value) {
  185. boolean ret = false;
  186. Jedis jedis = null;
  187. try {
  188. jedis = jedisPool.getResource();
  189. if (jedis == null) {
  190. return ret;
  191. }
  192. Long status = jedis.hset(key, field, value);
  193. if (0L == status) {
  194. ret = true;
  195. }
  196. } catch (Exception e) {
  197. logger.error("redis setHm 出错", e);
  198. jedisPool.returnBrokenResource(jedis);
  199. } finally {
  200. if (null != jedis) {
  201. jedisPool.returnResource(jedis);
  202. }
  203. }
  204. return ret;
  205. }
  206. /**
  207. * 根据fields 查询key对象属性列表
  208. *
  209. * @param key
  210. * @param fields
  211. * @return
  212. */
  213. public List<String> getHm(String key, String... fields) {
  214. List<String> ret = null;
  215. Jedis jedis = null;
  216. try {
  217. jedis = jedisPool.getResource();
  218. if (jedis == null) {
  219. return null;
  220. }
  221. ret = jedis.hmget(key, fields);
  222. } catch (Exception e) {
  223. logger.error("redis getHm 出错", e);
  224. jedisPool.returnBrokenResource(jedis);
  225. } finally {
  226. if (null != jedis) {
  227. jedisPool.returnResource(jedis);
  228. }
  229. }
  230. return ret;
  231. }
  232. /**
  233. * 根据fields 查询key对象属性列表
  234. *
  235. * @param key
  236. * @return
  237. */
  238. public Long incr(String key) {
  239. Long count = null;
  240. Jedis jedis = null;
  241. try {
  242. jedis = jedisPool.getResource();
  243. if (jedis == null) {
  244. return null;
  245. }
  246. count = jedis.incr(key);
  247. } catch (Exception e) {
  248. logger.error("redis incr 出错", e);
  249. jedisPool.returnBrokenResource(jedis);
  250. } finally {
  251. if (null != jedis) {
  252. jedisPool.returnResource(jedis);
  253. }
  254. }
  255. return count;
  256. }
  257. /**
  258. * 根据field 查询key对象属性
  259. *
  260. * @param key
  261. * @param
  262. * @return
  263. */
  264. public String getHm(String key, String field) {
  265. String ret = null;
  266. Jedis jedis = null;
  267. try {
  268. jedis = jedisPool.getResource();
  269. if (jedis == null) {
  270. return null;
  271. }
  272. ret = jedis.hget(key, field);
  273. } catch (Exception e) {
  274. logger.error("redis getHm 出错", e);
  275. jedisPool.returnBrokenResource(jedis);
  276. } finally {
  277. if (null != jedis) {
  278. jedisPool.returnResource(jedis);
  279. }
  280. }
  281. return ret;
  282. }
  283. }

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号