潍坊专业网站建设哪家便宜,wordpress电视剧,电脑突然多了windows优化大师,深圳12个区地图场景#xff1a;给用户端展示的数据都是通过查询数据库所得#xff0c;因此数据库访问压力会随着用户访问量增大而增加#xff0c;从而导致系统响应慢、用户体验差。 方法#xff1a;通过Redis缓存数据#xff0c;减少查询数据库操作。#xff08;Redis的数据是存储在内存…场景给用户端展示的数据都是通过查询数据库所得因此数据库访问压力会随着用户访问量增大而增加从而导致系统响应慢、用户体验差。 方法通过Redis缓存数据减少查询数据库操作。Redis的数据是存储在内存的数据库的数据存储在磁盘访问内存会更快。Redis相关知识可参见Redis基础 举例 以外卖平台为例页面根据分类来展示菜品。当选择一个分类时页面展示该分类的所有菜品因此缓存逻辑为
每个分类下的菜品对应一份缓存数据数据库中菜品数据有变更时清理缓存数据。(避免数据不一致)
综上Redis的数据结构为 psRedis中的数据类型和Java中的数据类型并不是完全对应的Java中的任何一个对象都可以转成Redis中的string字符串进行存储。若是从Java层面考虑这里的value实则是List集合然后把这个集合序列化最终把它转成Redis字符串存储。dish_id表示分类id。
代码举例 使用Redis缓存访问数据——用户端实现
RestController(userDishController)
RequestMapping(/user/dish)
Api(tags C端-菜品相关接口)
public class DishController {Autowiredprivate DishService dishService;Autowiredprivate RedisTemplate redisTemplate;/*** 条件查询菜品和口味** param categoryId* return*/GetMapping(/list)ApiOperation(条件查询菜品和口味)public ResultListDishVO listWithCategoryId(Long categoryId) {// 1. 构造redis中的key 规则dish_分类idString key dish_ categoryId;// 2. 查询Redis是否存在菜品数据ListDishVO list (ListDishVO) redisTemplate.opsForValue().get(key);// 3. 如果存在直接返回无须查询数据库if (list ! null list.size() 0) {return Result.success(list);}// 4. 如果不存在查询数据库将查询到的数据放入Redis中Dish dish new Dish();dish.setCategoryId(categoryId);dish.setStatus(StatusConstant.ENABLE); // 查询起售中的菜品list dishService.listWithFlavor(dish);redisTemplate.opsForValue().set(key,list);// 存储查询结果到listreturn Result.success(list);}
}清除缓存数据——管理端实现 需要清除缓存数据的情况
修改了数据库中的数据删除了数据库中的数据新增了数据库中的数据 总结只要涉及到了对应数据库的增删改都需要清除缓存。
代码中涉及的不同情况
case1: 新增一个菜品——删除该菜品所属分类对应的缓存case2: 批量删除菜品——删除所有分类对应的缓存删除时是根据菜品的id删除的所以想要知道菜品所对应的分类id还遍历查询一遍case3: 修改菜品涉及两种情况a. 只修改菜品的基本信息菜品的分类不变b. 修改了菜品的分类这就涉及到了两个分类对应的缓存值——删除所有分类对应的缓存与上面的情况一样如果要确定哪两个分类受影响还得查一次查修改前所属分类id索性直接删除所有的分类的缓存
RestController
RequestMapping(/admin/dish)
Api(tags 菜品相关接口)
Slf4j
public class DishController {Autowiredprivate DishService dishService;Autowiredprivate RedisTemplate redisTemplate;/*** 清理缓存数据* param pattern*/private void cleanCache(String pattern){Set keys redisTemplate.keys(pattern);redisTemplate.delete(keys);}/*** 新增菜品case1** param dishDTO* return*/PostMappingApiOperation(新增菜品)public Result save(RequestBody DishDTO dishDTO) {log.info(新增菜品{}, dishDTO);dishService.saveWithFlavor(dishDTO);// 清理缓存数据String key dish_ dishDTO.getCategoryId();cleanCache(key);return Result.success();}/*** 菜品批量删除case2** param ids* return*/DeleteMappingApiOperation(菜品删除)// 通过RequestParam解析前端请求地址中字符串参数ids1,2,3...为一个列表public Result delete(RequestParam ListLong ids) {log.info(菜品批量删除{}, ids);dishService.deleteBatch(ids);// 清理缓存数据(将所有的dish_*的缓存数据都清除掉)cleanCache(dish_*);return Result.success();}/*** 修改菜品case3** param dishDTO* return*/PutMappingApiOperation(修改菜品)public Result update(RequestBody DishDTO dishDTO) {log.info(修改菜品{}, dishDTO);dishService.updateWithFlavor(dishDTO);// 清理缓存数据(将所有的dish_*的缓存数据都清除掉)cleanCache(dish_*);return Result.success();}
Spring Cache Spring Cache是Spring框架提供的缓存工具使用它可以进一步简化代码。它实现了基于注解的缓存功能我们只需要添加一个注解就能实现缓存功能。 Spring Cache只是提供了一层抽象底层可以切换不同的缓存实现包括EHCacheCaffeineRedis等。我们只需要导入对应的缓存产品的客户端就可以告诉Spring Cache我们想用哪个缓存实现。 maven坐标
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-cache/artifactId
/dependencySpring Cache提供的常用注解
注解说明EnableCaching开启缓存注解功能通常加在启动类上Cacheable在方法执行前先查询缓存中是否有数据如果有数据则直接返回缓存数据如果没有缓存数据调用方法并将方法返回值放到缓存中CachePut将方法的返回值放到缓存中CacheEvict将一条或多条数据从缓存中删除
使用Spring Cache缓存数据CachePut中key的生成cacheNames::key,这里使用SqEL语法,SqEL细则
Spring Expression Language (SpEL) expression for computing the key dynamically. Default is “”, meaning all method parameters are considered as a key, unless a custom keyGenerator has been set. The SpEL expression evaluates against a dedicated context that provides the following meta-data:
#result for a reference to the result of the method invocation. For supported wrappers such as Optional, #result refers to the actual object, not the wrapper#root.method, #root.target, and #root.caches for references to the method, target object, and affected cache(s) respectively.Shortcuts for the method name (#root.methodName) and target class (#root.targetClass) are also available.Method arguments can be accessed by index. For instance the second argument can be accessed via #root.args[1], #p1 or #a1. Arguments can also be accessed by name if that information is available.
举例 CachePut(cacheNames setmeal,key #setmealDTO.categoryId)注意 不同的注解对应支持生成key的方式可能不一样比如Chacheable中就不支持#result的形式所以使用的时候可以通过 Ctrl 鼠标点击key跳转到源文件中去查看。
举例 实现思路如下
导入Spring Cache和Redis相关maven坐标在启动类上加入EnableCaching注解开启缓存注解功能在用户端接口查询 方法上加入Cacheable注解在管理端接口数据库增、删改等方法上加入CacheEvict注解
CacheAble举例 /*** 条件查询* param categoryId* return*/GetMapping(list)ApiOperation(根据分类id查询套餐)// key为 setmealCache::categoryId值 Redis存储的value为list方法的返回结果Cacheable(cacheNames setmealCache, key #categoryId) public ResultListSetmeal list(Long categoryId){Setmeal setmeal new Setmeal();setmeal.setCategoryId(categoryId);setmeal.setStatus(StatusConstant.ENABLE);ListSetmeal etmealVOList setmealService.list(setmeal);return Result.success(etmealVOList);}CacheEvic举例 精确清理 /*** 新增套餐* param setmealDTO* return*/PostMappingApiOperation(新增套餐)CacheEvict(cacheNames setmealCache,key #setmealDTO.categoryId)public Result save(RequestBody SetmealDTO setmealDTO){log.info(新增套餐:{},setmealDTO);setmealService.save(setmealDTO);return Result.success();}全部清理 /*** 批量删除套餐* param ids* return*/DeleteMappingApiOperation(批量删除套餐)CacheEvict(cacheNames setmealCache,allEntries true)public Result deleteBatch(Long[] ids){setmealService.deleteBatch(ids);return Result.success();}