一、概述
常用网站汇总
官方网站: Redis
Redis中文文档 redis中文文档Redis 在线测试 Try Redis
Redis 命令参考 Commands | Redis
1.1 jedis(一般不用,了解即可)
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.1</version>
</dependency>
package com.yanyu.redisjedistest.demo;
import redis.clients.jedis.Jedis;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class JedisDemo
{
public static void main(String[] args)
{
//1 connection获得,通过指定ip和端口号
Jedis jedis = new Jedis("0", 3390);
//2 指定访问服务器的密码
jedis.auth("0");
// 指定访问的数据库(此处以第0号数据库为例)
jedis.select(16);
//3 获得了jedis客户端,可以像jdbc一样,访问我们的redis
System.out.println(jedis.ping());
//keys
Set<String> keys = jedis.keys("*");
System.out.println(keys);
//string
jedis.set("k3","hello-jedis");
System.out.println(jedis.get("k3"));
System.out.println(jedis.ttl("k3"));
jedis.expire("k3",20L);
//list
jedis.lpush("list","11","12","13");
List<String> list = jedis.lrange("list", 0, -1);
for (String element : list) {
System.out.println(element);
}
// hash
jedis.hset("hset1","k1","v1");
Map<String,String> hash = new HashMap<>();
hash.put("k1","1");
hash.put("k2","2");
hash.put("k3","3");
jedis.hmset("hset2",hash);
System.out.println(jedis.hmget("hset2","k1","k3","k2"));
System.out.println(jedis.hget("hset1", "k1"));
System.out.println(jedis.hexists("hset2","k2"));
System.out.println(jedis.hkeys("hset2"));
// set
jedis.sadd("set1","1","2","3");
jedis.sadd("set2","4");
System.out.println(jedis.smembers("set1"));
System.out.println(jedis.scard("set1"));
System.out.println(jedis.spop("set1"));
jedis.smove("set1","set2","2");
System.out.println(jedis.smembers("set1"));
System.out.println(jedis.smembers("set2"));
System.out.println(jedis.sinter("set1", "set2")); // 交集
System.out.println(jedis.sunion("set1","set2")); // 并集
// zset
jedis.zadd("zset1",100,"v1");
jedis.zadd("zset1",80,"v2");
jedis.zadd("zset1",60,"v3");
List<String> zset1 = jedis.zrange("zset1", 0, -1);
for (String s : zset1) {
System.out.println(s);
}
List<String> zset11 = jedis.zrevrange("zset1", 0, -1);
for (String s : zset11) {
System.out.println(s);
}
}
}
1.2 lettuce(了解)
<!-- https://mvnrepository.com/artifact/io.lettuce/lettuce-core -->
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.2.3.RELEASE</version>
</dependency>
package com.yanyu.redisjedistest.demo;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import java.util.List;
public class LettuceDemo
{
public static void main(String[] args)
{
// 1 使用构建器链式编程来builder我们RedisURI
RedisURI uri = RedisURI.builder()
.redis("0")
.withPort(0)
.withAuthentication("default","")
.build();
//2 创建连接客户端
RedisClient redisClient = RedisClient.create(uri);
StatefulRedisConnection conn = redisClient.connect();
//3 通过conn创建操作的command
RedisCommands commands = conn.sync();
commands.select(16);
//========biz====================
//keys
List keys = commands.keys("*");
System.out.println("***********"+keys);
//string
commands.set("k5","hello-lettuce");
System.out.println("***********"+commands.get("k5"));
// list
commands.lpush("list01","1","2","3");
List<String> list01 = commands.lrange("list01", 0, -1);
for (String s : list01) {
System.out.println("================"+s);
}
System.out.println("===================="+ commands.rpop("list01", 2));
// hash
commands.hset("hash","k1","v1");
commands.hset("hash","k2","v2");
commands.hset("hash","k3","v3");
System.out.println("======================="+commands.hgetall("hash"));
Boolean hexists = commands.hexists("hash", "v2");
System.out.println("------"+hexists);
// set
commands.sadd("s1","1","2");
System.out.println("=================================" + commands.smembers("s1"));
System.out.println(commands.sismember("s1", "1"));
System.out.println(commands.scard("s1"));
// zset
commands.zadd("a1",100,"v1");
commands.zadd("a1",80,"v2");
System.out.println(commands.zrange("a1", 0, -1));
System.out.println("======================"+commands.zcount("a1", "90", "100"));
//4 各种关闭释放资源
conn.close();
redisClient.shutdown();
}
}
1.3RedisTemplate
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
默认情况下会为我们提供下面两个bean对象,我更推荐使用StringRedisTemplate原因如下
RedisTemplate<Object, Object>
StringRedisTemplate
配置
# Spring Boot应用程序的Spring Data Redis配置
spring:
data:
redis:
# 指定要连接的Redis数据库编号。Redis默认有16个数据库(编号为0至15),此处设置为16。
database: 16
# Redis服务器的主机地址,这里是
host:
# Redis服务器监听的端口号,此处设置为
port:
# 访问Redis服务器所需的密码。此处设置为`
password:
# 配置Lettuce连接池参数(Lettuce是Spring Data Redis使用的默认客户端库之一)
lettuce:
pool:
# 连接池中允许的最大活动连接数。当达到此限制时,新请求将被阻塞直到有连接释放。此处设置为`8`
max-active: 8
# 当连接池耗尽时,客户端尝试获取连接的最长时间。负值表示无限等待。此处设置为`-1ms`,意味着无限制等待
max-wait: -1ms
# 连接池中的最大空闲连接数。超过此数量的空闲连接将被断开。此处设置为`8`
max-idle: 8
# 连接池中的最小空闲连接数。低于此数量时,连接池将尝试补充空闲连接。此处设置为`0`,意味着无需保持最小空闲连接数
min-idle: 0
service
package com.yanyu.redisjedistest.service;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
@Service
@Slf4j
public class OrderService
{
public static final String ORDER_KEY = "ord:";
@Resource
private RedisTemplate redisTemplate;
//@Resource private StringRedisTemplate StringRedisTemplate;
public void addOrder()
{
int keyId = ThreadLocalRandom.current().nextInt(1000)+1;
String serialNo = UUID.randomUUID().toString();
String key = ORDER_KEY+keyId;
String value = "京东订单"+serialNo;
redisTemplate.opsForValue().set(key,value);
log.info("***key:{}",key);
log.info("***value:{}",value);
}
public String getOrderById(Integer keyId)
{
return (String) redisTemplate.opsForValue().get(ORDER_KEY + keyId);
//return StringRedisTemplate.opsForValue().get(ORDER_KEY + keyId);
}
}
controller
package com.yanyu.redisjedistest.controller;
import com.yanyu.redisjedistest.service.OrderService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class OrderController
{
@Resource
private OrderService orderService;
@RequestMapping(value = "/order/add",method = RequestMethod.POST)
public void addOrder()
{
orderService.addOrder();
}
@RequestMapping(value = "/order/{keyId}",method = RequestMethod.GET)
public String getOrderById(@PathVariable Integer keyId)
{
return orderService.getOrderById(keyId);
}
}
config
package com.yanyu.redisjedistest.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
/**
* redis序列化的工具配置类,下面这个请一定开启配置
* 127.0.0.1:6379> keys *
* 1) "ord:102" 序列化过
* 2) "\xac\xed\x00\x05t\x00\aord:102" 野生,没有序列化过
* this.redisTemplate.opsForValue(); //提供了操作string类型的所有方法
* this.redisTemplate.opsForList(); // 提供了操作list类型的所有方法
* this.redisTemplate.opsForSet(); //提供了操作set的所有方法
* this.redisTemplate.opsForHash(); //提供了操作hash表的所有方法
* this.redisTemplate.opsForZSet(); //提供了操作zset的所有方法
* @param lettuceConnectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 设置 RedisTemplate 连接工厂
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
// 设置键(Key)的序列化方式为字符串(String)
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 设置值(Value)的序列化方式为 JSON,使用 Jackson 库实现
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
// 设置哈希键(Hash Key)和哈希值(Hash Value)的序列化方式同上
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
// 调用 afterPropertiesSet() 方法完成模板初始化
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
1.4集群
spring:
redis:
password: 123456
lettuce:
pool:
max-idle: 32
max-active: 32
min-idle: 8
max-wait: -1
cluster:
nodes:
- 192.168.139.140:6379
- 192.168.139.140:6380
- 192.168.139.140:6381
- 192.168.139.140:6382
- 192.168.139.140:6383
- 192.168.139.140:6384
max-redirects: 3
问题复现:
选择一台主节点宕机,这里选择 6379,首先找到一个会落到6379节点的key
问题的原因:服务没有感受到集群的变化。
Lettuce 不会刷新拓扑图。
解决方案:
方案一:使用 jedis(不推荐)
方案二:重写连接工厂实例(不推荐)
方案三:刷新节点集群拓扑动态感应(官网)
spring:
redis:
password: 123456
lettuce:
cluster:
# 刷新集群拓扑
refresh:
adaptive: true
period: 2000
参考链接 spring boot整合redis集群,连接虚拟机redis集群,Unable to connect to 127-java面试题网