使用bucket4j+JCache+Redisson+SpringBoot+Java17调用Bucket API时遇类型转换错误
使用Bucket4J+JCache+Redisson+SpringBoot时调用
tryConsumeAsMuchAsPossible抛出类型转换异常 问题场景
基于bucket4j + JCache + Redisson + SpringBoot + Java17技术栈,调用Bucket API的bucket.tryConsumeAsMuchAsPossible(n)方法时,预期限流操作成功执行,实际抛出类型转换异常。
依赖配置(pom.xml)
<!-- Bucket4J starter : Bucket4J + JCache --> <dependency> <groupId>com.giffing.bucket4j.spring.boot.starter</groupId> <artifactId>bucket4j-spring-boot-starter</artifactId> <version>0.9.1</version> <exclusions> <!-- EXCLUDE ehcache --> <exclusion> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> </exclusion> </exclusions> </dependency> <!-- REDIS redisson for cache cli --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>3.23.2</version> </dependency>
错误栈信息
io.github.bucket4j.distributed.proxy.DefaultBucketProxy@789e42d1 javax.cache.processor.EntryProcessorException: java.lang.ClassCastException: class java.lang.String cannot be cast to class [B (java.lang.String and [B are in module java.base of loader 'bootstrap') at org.redisson.jcache.JCache.invoke(JCache.java:3067) at io.github.bucket4j.grid.jcache.JCacheProxyManager.execute(JCacheProxyManager.java:82) at io.github.bucket4j.distributed.proxy.AbstractProxyManager$DefaultRemoteBucketBuilder$1.execute(AbstractProxyManager.java:197) at io.github.bucket4j.distributed.proxy.DefaultBucketProxy.execute(DefaultBucketProxy.java:208) at io.github.bucket4j.distributed.proxy.DefaultBucketProxy.consumeAsMuchAsPossibleImpl(DefaultBucketProxy.java:78) at io.github.bucket4j.AbstractBucket.tryConsumeAsMuchAsPossible(AbstractBucket.java:307)
根因分析
从嵌套异常可以定位核心问题:Bucket4J预期Redis中存储的是字节数组([B)格式的桶状态,但实际存储的是String类型数据,导致强制转换失败:
Caused by: java.lang.ClassCastException: class java.lang.String cannot be cast to class [B (java.lang.String and [B are in module java.base of loader 'bootstrap') at io.github.bucket4j.grid.jcache.JCacheProxyManager$JCacheTransaction.getRawState(JCacheProxyManager.java:188) at io.github.bucket4j.distributed.remote.AbstractBinaryTransaction.get(AbstractBinaryTransaction.java:72) at io.github.bucket4j.distributed.remote.commands.ConsumeAsMuchAsPossibleCommand.execute(ConsumeAsMuchAsPossibleCommand.java:109) at io.github.bucket4j.distributed.remote.AbstractBinaryTransaction.execute(AbstractBinaryTransaction.java:53) at io.github.bucket4j.grid.jcache.JCacheProxyManager$BucketProcessor.process(JCacheProxyManager.java:167) at io.github.bucket4j.grid.jcache.JCacheProxyManager$BucketProcessor.process(JCacheProxyManager.java:155) at org.redisson.jcache.JCache.invoke(JCache.java:3055)
通常是两种情况导致:
- Redis中存在历史遗留的String格式桶数据
- Redisson JCache默认序列化方式与Bucket4J预期的二进制序列化不匹配
解决方案
方案1:清理Redis旧数据
如果是历史数据残留导致,直接删除对应Key即可:
redis-cli DEL "your-bucket-key-prefix*"
方案2:配置Redisson使用二进制序列化
修改Redisson配置,指定JCache使用ByteArrayCodec匹配Bucket4J的序列化要求:
@Configuration public class RedissonConfig { @Bean public Config redissonConfig() { Config config = new Config(); // 根据实际环境配置Redis连接,示例为单节点模式 config.useSingleServer().setAddress("redis://localhost:6379"); // 注册ByteArrayCodec,覆盖默认序列化方式 config.getCodecProvider().registerCodec(new ByteArrayCodec()); return config; } @Bean public RedissonClient redissonClient(Config redissonConfig) { return Redisson.create(redissonConfig); } }
方案3:升级Bucket4J Starter版本
当前使用的bucket4j-spring-boot-starter版本0.9.1较旧,尝试升级到最新稳定版(如1.12.0+),新版本可能修复了与Redisson JCache的序列化兼容性问题:
<dependency> <groupId>com.giffing.bucket4j.spring.boot.starter</groupId> <artifactId>bucket4j-spring-boot-starter</artifactId> <version>1.12.0</version> <exclusions> <exclusion> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> </exclusion> </exclusions> </dependency>
内容的提问来源于stack exchange,提问作者Vivek Sharma
相关产品推荐
相关产品推荐

