当数据量很大时,还需要你模糊搜索,这时的性能优化你会怎么做?
前言
最近来了一个任务,让我查询一个银行卡bin信息,可能没有做过这方面的小伙伴们可能不知道,这个卡bin信息表的数据量非常大,如果接口处理不好的话速度会非常慢。(一个接口可能会拖垮整个项目)。
进入正题
任务背景
是一个非常简单的查询卡bin接口 如图:
代表银行卡号 (在后续查询中可能会出现其他参数,固定枚举型我们不做讨论) 用来@注解 做了一个简单的长度判断和提示信息
返回信息就是查询出来的卡bin信息
问题分析
常规查询操作: 直接不管是jpa还是什么的 直接根据cardNo模糊查询即可 (其他参数不讨论) 如图:
不了解的小伙伴可以一会去了解一下,使用方法非常简单。 方法很简单。
思路: 1.首先吧数据在启动项里面去调用,去简单的分类查一下所有的数据,然后把数据放入到redis里面去。 2.当我调用模糊查询方法时,直接做判断条件循环去从redis里取即可。
有了思路之后,我们就要开始干活了!
首先简单说一下redis怎么引入项目
简单说一下redis怎么引入 首先在项目中引入redis 在pom文件中,简单的加上依赖
<!--redis的起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在application.properties指向一下自己redis的服务地址
# redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
然后在想应用的地方直接注入redis操作类
@Autowired
private RedisTemplate<Object,Object> redisTemplate;
大致的引用就完成了
代码环节
到了本文的关键,代码环节。 我会尽量简化代码的阅读量,让大家最快的方式理解我的意思,方法是千变万化的,但是思路确能复用。
首先: 1.我要存储数据放入redis 但是放入redis之前,要先引用
@Autowired
protected RedisTemplate<String, CardBinDTO> redisTemplate;
注意:redisTemplate因为泛型参数不是Object,所以需要去配置一下 创建 RedisTemplateConfig 类
@Component
public class RedisTemplateConfig {
@Bean
public RedisTemplate<String, CardBinDTO> redisCardBinVOTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, CardBinDTO> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}
}
然后再去注入redisTemplate就可以了 继续看代码。 查询数据并放入redis代码
/**
* 缓存reids
*/
@Transactional(rollbackFor = Exception.class)
public void saveORUpdateRedisOrCardBin() {
//一个根据条件查询卡bin的方法
List<BankCardBin> cardBins = bankCardService.findAllByZyzhFlagAndFlag(ZyzhFlag.WITHDRAW_AND_CONSUME, CardFlag.DEBIT_CARD);
//list循环,缓存redis,同时吧对象复制成DTO对象进行数据传输
//设置redis生命周期,30days
cardBins.forEach(bankCardBin ->
redisTemplate.opsForValue().set(bankCardBin.getCardBin(), BeanCopyUtils.copyBean(bankCardBin, CardBinDTO.class), 30, TimeUnit.DAYS)
);
}
2.根据传入参数从Redis内返回指定数据
@Override
public CardBinDTO findCardBinInfo(String cardNo) {
//模糊的查询的是cardno 也就是银行卡号,表bin字段在需求书上有规定,最长是12,最短是3,所以循环条件是i=12,i>=3
for (int i = 12; i >= 3; i--) {
//根据i的当前长度截取一下银号卡号
String substring = cardNo.substring(0, i);
//根据现有银行卡号去从redis里取值,有一条数据就返回即可
if (redisTemplate.hasKey(substring)) {
return redisTemplate.opsForValue().get(substring);
}
}
//如果循环完没有值,则抛出异常
throw new ServiceException(ResultCode.NOT_CARD_BINDING);
}
到这里,方法大概就结束了,就剩下调用了。
代码和思路都很简单,希望大家看的明白!
如果大家觉得还不错,希望可以给我一个赞,非常感谢!
您的点赞是我最大的鼓励!
作者的话
互相尊重,互相进步,很感谢大家的无私精神。才能让我们中国IT越来越进步! 也非常愿意虚心听取更多大佬的意见和建议,和大家一起交流进步 我是你们的好朋友 樊亦凡
一个每天进步一点点的程序员!