Redis实践—全国地址信息缓存

一、背景

在涉及全国地址的应用中,地址信息通常被频繁地查询和使用,例如电商平台、物流系统等。为了提高系统性能和减少对数据库的访问压力,可以使用缓存来存储常用的地址信息,其中 Redis 是一个非常流行的选择。

本次在一个企业入驻场场景中,需要选择企业服务区域,用户经常需要查询和使用全国省市地址信息(如下所示)。

如果每次查询都直接访问数据库,会增加数据库的负载,尤其是在高并发情况下。相较于其他数据,地址信息相对稳定,通常不会频繁变动。通过缓存常用的地址信息,可以加快查询速度,提高系统性能。

image

二、设计

数据库:字段及数据如下(需要sql文件,可私信联系)

image

Redis:使用List数据类型,把每条地址对象转换为json格式,存到Redis。

避免数据库更新,而缓存是老数据,导致数据不一致。设置过期时间7天,超过7天删除缓存,查询最新库中数据

image

三、代码

controller

image

@RestController
@RequestMapping("/pre_cook/client/address")
public class AddressClientController {@Resourceprivate AddressClientService addressClientService;/*** 全国地址查询** @return*/@PostMapping("/list")public List<AddressVO> addressList() {return addressClientService.addressList();}}

impl实现类

image

@Overridepublic List<AddressVO> addressList() {String addressKey = AddressEnum.Address_PREFIX.getValue();Boolean exist = redisUtil.hasKey(addressKey);//1.如果缓存有数据,取缓存数据if (exist) {List<String> jsonList = redisUtil.lRange(addressKey, 0, -1);log.info("缓存查询地址信息-json格式:{}", jsonList);List<AddressVO> addressVOS = jsonList.stream().map(json -> JSON.parseObject(json, AddressVO.class)).collect(Collectors.toList());return addressVOS;}//2.缓存无数据,查询数据库List<AddressInfoDO> infoDOList = addressInfoService.lambdaQuery().in(AddressInfoDO::getLevel, CompanyConstant.COUNTRY_LEVEL, CompanyConstant.PROVINCE_LEVEL, CompanyConstant.CITY_LEVEL, CompanyConstant.DISTRICT_LEVEL).eq(AddressInfoDO::getStatus, CompanyConstant.ADDRESS_ENABLED).eq(AddressInfoDO::getEnableFlag, EnableFlagEnum.ENABLE.getCode()).list();List<AddressVO> addressVOS = infoDOList.stream().map(e -> AddressVO.builder().id(e.getId()).addressCode(e.getCode()).addressName(e.getName()).level(e.getLevel()).parentCode(e.getParentCode()).key(PinYinUtils.getStringFirstName(e.getName())).build()).collect(Collectors.toList());List<AddressVO> voList = addressVOS.stream().sorted(Comparator.comparingInt(AddressVO::getLevel).thenComparing(AddressVO::getKey, (s1, s2) -> s1.compareToIgnoreCase(s2))).collect(Collectors.toList());//2.2存入缓存List<String> jsonList = voList.stream().map(AddressVO -> JSON.toJSONString(AddressVO)).collect(Collectors.toList());redisUtil.lRightPushAll(addressKey, jsonList);redisUtil.expire(addressKey, DigitalConstant.SEVEN, TimeUnit.DAYS);return voList;}

RedisUtil​​工具类方法

    /*** 获取列表指定范围内的元素** @param key   key* @param start 开始位置, 0是开始位置* @param end   结束位置, -1返回所有* @return*/public List<String> lRange(String key, long start, long end) {return redisTemplate.opsForList().range(key, start, end);}/*** @param key   key* @param value val* @return*/public Long lRightPushAll(String key, Collection<String> value) {return redisTemplate.opsForList().rightPushAll(key, value);}/*** 设置过期时间** @param key     key* @param timeout* @param unit* @return*/public Boolean expire(String key, long timeout, TimeUnit unit) {return redisTemplate.expire(key, timeout, unit);}

四、测试

第一次,查数据库,耗时4秒多

image

第二次,通过第一次查询,redis已存有数据,只需要200多毫秒

image

第三次,耗时200多毫秒

image

第四次,删除缓存,再次查库,耗时700多毫秒

image

通过上述测试,第一次查询Mysql数据库,耗时4秒多,后续查询耗时700多毫秒,说明MySQL 也有自身的缓存机制,其中包括查询缓存。

由于查询缓存的存在,第一次执行某个查询时可能会比较慢,因为需要执行实际的查询操作并将结果存入缓存中。但是,当相同的查询再次执行时,如果查询的条件和数据没有发生变化,就可以直接从查询缓存中获取结果,因此查询时间会明显减少。

这里使用Redis缓存,在首次从Mysql查询后,存入Redis。通过Redis查询,耗时只需200多毫秒,明显少于Mysql耗时,减轻了数据库压力,也可以支持更高的并发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/14012.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

tomcat关不掉解决方案

改造tomcat的脚本,增加强制关闭tomcat进程. 找到tomcat安装目录&#xff08;如&#xff1a;/data/b2b/b2b_erp02/apache-tomcat-8.5.82/bin&#xff09;&#xff0c;在该目录下有个catalina.sh脚本&#xff0c;在脚本的上面添加一行 CATALINA_PID/data/b2b/b2b_erp02/apache-t…

Redis的下载、安装、启动和初尝试【超级简单】

redis最好是在Linux系统中使用&#xff0c;这是最接近生产实际的环境。 不过&#xff0c;我们初学者&#xff0c;目的是学习Redis的使用、原理&#xff0c;如果在Linux下直接学习Redis&#xff0c;很可能会因为命令不熟悉而劝退&#xff0c;这是不好的。 因此&#xff0c;我主张…

linux命令中arj使用

arj 用于创建和管理.arj压缩包 补充说明 arj命令 是 .arj 格式的压缩文件的管理器&#xff0c;用于创建和管理 .arj 压缩包。 语法 arj(参数)参数 操作指令&#xff1a;对 .arj 压缩包执行的操作指令&#xff1b;压缩包名称&#xff1a;指定要操作的arj压缩包名称。 更多…

.NET Core Web Api Swagger运行异常

遇到的问题 因为新增了一个控制器方法&#xff0c;从而导致在运行Swagger的时候直接报错&#xff0c;异常如下&#xff1a; SwaggerGeneratorException: Conflicting method/path combination "POST api/UserOperationExample" for actions - WebApi.Controllers.Us…

HTML+CSS+JS 扩散登录表单动画

效果演示 Code <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,us…

光明于心,自理成翼:盲人生活自理能力训练探索

在探索未知的旅途中&#xff0c;盲人朋友同样怀揣着对自由与独立的向往。随着科技的不断进步&#xff0c;一款名为“蝙蝠避障”的辅助软件以其独特的实时避障与拍照识别功能&#xff0c;成为了盲人朋友提升生活自理能力的有力工具。本文将深入探讨盲人生活自理能力训练&#xf…

代码随想录--哈希表--有效的字母异位词

题目 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 示例 1: 输入: s “anagram”, t “nagaram” 输出: true 示例 2: 输入: s “rat”, t “car” 输出: false 说明: 你可以假设字符串只包含小写字母。 思路 先看暴力的解法&am…

低功耗 DC/DC 转换器的复杂设计原理分析介绍

DC/DC 转换解决方案都是低噪声线性设计&#xff0c;易于使用&#xff0c;但有两个主要缺点。首先&#xff0c;输出电压必须始终低于输入电压&#xff1b;然而&#xff0c;线性稳压器的效率非常低&#xff0c;并且将大部分供电功率以热量的形式耗散。其次&#xff0c;根据输入和…

【Spring】代理模式——动态代理

1、基本概念 动态代理允许我们在运行时根据指定的接口动态地创建代理对象&#xff0c;这个代理对象与目标对象实现了相同的接口&#xff0c;因此可以完全替代目标对象执行相同的操作。通过动态代理&#xff0c;我们可以在不修改目标对象代码的情况下&#xff0c;为目标对象添加…

ZISUOJ 数据结构--图及其应用

说明 主要考察建图&#xff0c;图的遍历以及求最小生成树。都还是比较简单的&#xff0c;后面就直接上代码了。 最小生成树采用prim还是kruskal算法要看题目怎么给出数据&#xff0c;如果以邻接矩阵的形式给出&#xff0c;采用prim算法比较合适&#xff0c;如果以边和边的权重的…

盲人社会适应性训练:打开生活的新篇章

在现代社会的快节奏中&#xff0c;每一位成员都在寻求更好的方式来适应环境&#xff0c;对于盲人群体而言&#xff0c;这种适应性尤为关键。盲人社会适应性训练作为一个旨在提升盲人生活质量和独立性的系统性过程&#xff0c;正逐步受到广泛关注。在这一过程中&#xff0c;一款…

轻量SEO分析报告程序网站已开心去授权

轻量SEO分析报告程序网站已开心去授权&#xff0c;可以让你生成有洞察力的、 简洁的、易于理解的SEO报告&#xff0c;帮助你的网页排名和表现更好 网站源码免费下载地址抄笔记 (chaobiji.cn)https://chaobiji.cn/

如何通过软件IIC使用MPU6050陀螺仪

目录 1. MPU6050简介 2. MPU6050参数 3. MPU6050硬件电路 4. 代码编写 4.1 MPU6050写寄存器 4.2 MPU6050读寄存器 4.3 初始化 4.4 MPU6050获取ID号 4.5 MPU6050获取数据 1. MPU6050简介 MPU6050是一个6轴姿态传感器&#xff0c;可以测量芯片自身X、Y、Z轴的…

前端路由原理及hash模式和history模式和Abstract模式

1.前端路由原理&#xff1a; 前端路由的核心在于改变视图的同时不会向后端发出请求&#xff0c;而是去加载路由对应的组件&#xff1b; vue-router是将组件映射到路由&#xff0c;然后在渲染出来&#xff0c;并且实现Hash、History、Abstract这三种模式&#xff0c;一般默认H…

iostat之性能监控

#date 2024年5月23日 #作者:野生老中医 #功能:查找磁盘或者cpu瓶颈,繁忙大于70,队列大于2,等待I/O平均的时间超过10毫秒的脚本 #脚本名称:io.sh #使用方式:sh io.sh #! /bin/bash #1 磁盘模块分析 #在使用IOStat进行系统性能监控时,需要注意综合分析磁盘和CPU等多…

Webpack5 解决静态资源重复打包问题

Webpack5 解决静态资源重复打包问题 在使用url-loader、file-loader时&#xff0c;想将资源打包到特定的文件夹&#xff0c;而不是根目录时&#xff0c;Webpack还是会重复将资源打包到根目录。 解决 {test: /\.(png|svg|jpg|jpeg|gif|ico)$/,use: [{loader: url-loader,option…

点灯yes,关灯no

main.c #include"led.h" //手动封装一个延时函数 void delay_ms(int ms) {int i,j;for(i0;i<ms;i){for(j0;j<2000;j){}} } int strcmp(char *s1,char *s2) {while(*s1&&(*s1*s2)){*s1;*s2;}return *s1-*s2; } int main() {//使能GPIO的外设时钟*((uns…

(delphi11最新学习资料) Object Pascal 学习笔记---第13章

第13章 对象和内存 ​ 本章关注 Object Pascal 语言中一项非常具体且相当重要的主题—内存管理。Object Pascal 语言及其运行时环境提供了一种独特的解决方案&#xff0c;介于 C 风格的手动内存管理和 Java 或 C# 风格的自动垃圾回收之间。 ​ 采用这种介于两者之间的方式在于…

2024-05-23 vscode + clang + clangd 解锁 modules

点击 <C 语言编程核心突破> 快速C语言入门 vscode clang clangd 解锁 modules 前言一、准备二、使用备注: 总结 前言 要解决问题: 昨天解锁VS使用modules, 但是不完美, 没有代码提示和补全了, 今天用 vscode clang clangd 解锁 modules, 同时还有代码补全及提示. …

js中的 map 方法遍历

map方法// map 方法不改变原本的数组 所以要将map之后的值赋值给一个新的变量 // ...item 的作用是 // 将调用 map 函数的数组里的所有数据 都复制到新的&#xff0c;接收map之后的数组中 // 在此基础上 再覆盖或者添加新的数据&#xff0c;如 outpatient 和 recommended 属性/…