一、背景与认证选型
mrs 是华为云大数据平台,fusioninsight 是其私有化部署形态。mrs redis 基于开源 redis cluster 深度定制,接入层增加了安全认证机制:要求客户端提供「用户名 + 密码」,经集群认证中心(kdc)校验后才允许读写,普通 redis 的"只填密码"玩法在这里行不通。
mrs redis 官方支持的客户端认证方式主要有三种:
| 认证方式 | 说明 | 适用场景 |
|---|---|---|
| 用户名密码(basic)认证 | 用户名+密码向 kdc 换取票据,再 auth 认证 | spring boot + jedis,无需 keytab,本文方案 |
| auth.conf 文件认证 | 配置文件全局认证 | 原生 jedis、老旧项目 |
| kerberos keytab 认证 | keytab + gssapi sasl 握手 | 等保合规要求高的环境 |
选型建议:新项目优先用用户名密码认证。只需在 fusioninsight manager 创建人机用户,把账号密码写入配置即可,不用准备 keytab 和 krb5.conf,接入成本最低。
二、版本选型:什么 mrs 配什么依赖
这是最先踩坑的地方——mrs 版本不同,配套的 jedis 制品、spring boot 版本甚至 jdk 都不同,混用必报错。
| mrs 版本 | jedis(groupid:artifactid:version) | spring boot / sdr | jdk |
|---|---|---|---|
| 3.5.x | redis.clients:jedis:3.6.3-h0.cbu.mrs.350.r11(本地)/ .351.r22(服务器) | boot 2.4~2.7 / sdr 2.x | 1.8 |
| 3.6.0 | redis.clients:jedis:5.2.0-h0.cbu.mrs.360.r9 | boot 3.x / sdr 3.4.9+ | 17 |
三个结论:① mrs 定制 jedis 的 groupid 仍是 redis.clients,版本号带 h0.cbu.mrs 后缀,内含集群连接增强类;② mrs 3.6.0 官方样例基于 jdk 17,团队还在用 jdk 1.8 就选 mrs 3.5.x;③ spring-boot-starter-data-redis 不写版本号,交给 boot 父 pom 管理。
三、pom.xml 依赖配置
核心依赖三块:starter(排除 lettuce)+ mrs 定制 jedis + commons-pool2:
<properties>
<jedis.version>3.6.3-h0.cbu.mrs.350.r11</jedis.version>
</properties>
<dependencies>
<!-- 必须用 starter 并排除 lettuce -->
<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>
<!-- @slf4j 日志注解(config 代码用到;不用 lombok 可自行删除) -->
<dependency>
<groupid>org.projectlombok</groupid>
<artifactid>lombok</artifactid>
<optional>true</optional>
</dependency>
<!-- mrs 定制 jedis -->
<dependency>
<groupid>redis.clients</groupid>
<artifactid>jedis</artifactid>
<version>${jedis.version}</version>
</dependency>
<dependency>
<groupid>org.apache.commons</groupid>
<artifactid>commons-pool2</artifactid>
<version>2.11.1</version>
</dependency>
</dependencies>三条纪律:必须用 spring-boot-starter-data-redis,单独引 spring-data-redis 不会触发自动装配,启动报 nosuchbeandefinitionexception;必须排除 lettuce,否则与 jedis 类冲突;不要额外声明 junit(starter-test 已包含)。
四、配置文件 application.properties
推荐 properties 格式(可规避 yaml 缩进坑):
# 集群节点,多个用逗号分隔,至少 1 个,其余自动拓扑发现 spring.redis.cluster.nodes=192.168.x.1:22400,192.168.x.2:22401,192.168.x.3:22402 server.port=9093 # ★ 密码认证核心配置 spring.redis.username=your_mrs_user spring.redis.password=your_password spring.redis.ssl=false spring.redis.timeout=5000 # 连接池 spring.redis.jedis.pool.max-active=10 spring.redis.jedis.pool.max-idle=10 spring.redis.jedis.pool.min-idle=2 spring.redis.jedis.pool.max-wait=2000
注意两点:① 端口规律:实例端口 = 22400 + 实例id - 1(r1→22400、r2→22401),节点信息可用 netstat -tlnp | grep redis-server 获取;② 若用 yaml,nodes 必须比 cluster 多缩进 2 格,否则解析成 spring.redis.nodes,报 could not resolve placeholder。
五、核心难点:boot 2.x 的 noauth 缺陷
配置就绪后启动,大概率遇到经典报错:
noauth authentication required
根因不是账号密码错了,而是 boot 2.x 自动装配的 jedisconnectionfactory 创建集群连接时,内部 createcluster() 只把 password 传给 jedis,没有传 username;mrs redis 开启 acl 认证,要求两者同时提供,缺一即拒。
更棘手的是时序问题:bean 初始化时自动调用 afterpropertiesset(),此刻连接已建立并抛异常,bean 初始化中断;事后想补传 username 为时已晚。
解法:绕开自动装配,手动构建携带 username 的 jediscluster,再反射注入 jedisconnectionfactory:
@slf4j
@configuration
public class mrsredisconfig {
@value("${spring.redis.cluster.nodes}") private string nodesstr;
@value("${spring.redis.username}") private string username;
@value("${spring.redis.password}") private string password;
@value("${spring.redis.timeout:5000}") private int timeout;
@bean
@primary // ★ 覆盖 boot 自动装配的连接工厂
public redisconnectionfactory redisconnectionfactory() throws exception {
// 1. 解析节点
set<hostandport> hosts = new hashset<>();
for (string node : nodesstr.split(",")) {
string[] hp = node.trim().split(":");
hosts.add(new hostandport(hp[0], integer.parseint(hp[1])));
}
// 2. 连接池 + 空闲驱逐策略(避免空闲连接被服务端回收后 ping 超时)
jedispoolconfig poolconfig = new jedispoolconfig();
poolconfig.setmaxtotal(10);
poolconfig.setminidle(2);
poolconfig.settimebetweenevictionrunsmillis(30000);
poolconfig.setminevictableidletimemillis(60000);
poolconfig.settestwhileidle(true);
// 3. ★ 关键:同时传 username + password
defaultjedisclientconfig clientconfig = defaultjedisclientconfig.builder()
.user(username).password(password)
.connectiontimeoutmillis(timeout)
.sockettimeoutmillis(timeout).build();
// 4. 手动构建带用户名认证的 jediscluster
jediscluster jediscluster = new jediscluster(hosts, clientconfig, 5, poolconfig);
// 5. ★ 不调用 afterpropertiesset(),直接反射注入 cluster
jedisconnectionfactory factory = new jedisconnectionfactory();
field clusterfield = jedisconnectionfactory.class.getdeclaredfield("cluster");
clusterfield.setaccessible(true);
clusterfield.set(factory, jediscluster);
log.info("mrs redis 集群连接工厂初始化完成");
return factory;
}
}若你的项目是 boot 2.3.x + 老版
com.huawei.jredis:jedis-mrs:反射字段名是configuration而非cluster(2.4+ 才是cluster),且需额外处理shardinfo空指针,建议直接升级 boot 版本走本方案。照抄提示:代码依赖 lombok
@slf4j(见上文 pom);import 只需补全jedisconnectionfactory、jediscluster、defaultjedisclientconfig、hostandport、jedispoolconfig、set/hashset、java.lang.reflect.field,ide 可自动导入。setmaxtotal(10)等连接池参数若想从配置文件读取,给字段加@value("${spring.redis.jedis.pool.max-active:10}")即可,与第四节 properties 一一对应。另注意:config/controller 必须放在启动类所在包(或其子包)内,否则组件扫描不到、自定义连接工厂不生效——症状是仍走自动装配,继续报 noauth。
六、controller 与联调验证
连接工厂就绪后 redistemplate 由 boot 自动装配,直接注入使用。boot 2.x 泛型为 redistemplate<object, object>(boot 3.x 才是 <string, string>),泛型不符会报 nosuchbeandefinitionexception。代码省略 import(@restcontroller/@autowired/@getmapping/redistemplate,ide 自动补全):
@restcontroller
public class rediscontroller {
@autowired
private redistemplate<object, object> redistemplate; // boot 2.x 泛型
@getmapping("/set")
public string set() {
redistemplate.opsforvalue().set("key", "value");
return "success";
}
@getmapping("/get")
public object get() {
return redistemplate.opsforvalue().get("key");
}
}联调前先用 redis-cli 验证账号本身可用,排除网络因素:
/opt/hadoopclient/redis/bin/redis-cli -h <hostip> -p <port> -c --realm <realm> --user <username> -a <password>
应用启动后,日志出现 mrs redis 集群连接工厂初始化完成 即代表连接成功,随后 curl http://localhost:9093/set、/get 验证读写。
七、常见问题速查表
| 报错 | 根因 | 解法 |
|---|---|---|
noauth authentication required | 建连只传 password 没传 username | 本文第五节方案 |
nosuchbeandefinitionexception | 单独引 spring-data-redis 或泛型不符 | 用 starter;注入 <object,object> |
could not resolve placeholder | yaml 缩进错误 / properties 未打包 | nodes 比 cluster 多缩进 2 格;pom 显式声明 resources |
jedisconnectionexception: auth failed | 用户名或密码错误 | 核对 manager 人机用户 |
no reachable node in cluster | 网络不通 / ssl 开关不一致 | ping 节点,核对 spring.redis.ssl 与集群 redis_ssl_on 一致 |
nosuchfieldexception: clusterconfig | 老版本 jedis 字段名不同 | 反射改用 configuration 字段 |
八、总结
一句话:绕开 boot 2.x 连接工厂的 acl 缺陷,用 defaultjedisclientconfig 把 username 和 password 完整传给 jediscluster。把握三点即可少走弯路:
- 版本对齐:mrs 3.5.x ↔ boot 2.4~2.7 + jdk 8;mrs 3.6.0 ↔ boot 3.x + jdk 17;
- 依赖纪律:starter-data-redis(排除 lettuce)+ mrs 定制 jedis,缺一不可;
- 认证纪律:用户名密码必须成对传递,任何"只传 password"的写法在 mrs acl 集群上必然失败。
本文代码整理自已在生产服务器验证的示例项目,希望能帮你顺利趟过 mrs redis 的"认证深水区"。
到此这篇关于spring boot 对接华为 mrs redis 集群(密码认证)全流程实战的文章就介绍到这了,更多相关spring boot 华为 mrs redis 集群内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论