个人推荐Redis比较好的一种使用规范
随着对个人项目的不断开发、迭代和重构,博主在这个过程中总结出了一套使用redis的较好的规范。主要包含Redis的key命名规范和Redis代码规范。
主要内容
主要包含以下几个内容:
- 同一应用的key在最前面添加统一的前缀,如应用名;
- 案例:appName:业务相关的key前缀:具有代表性的字段的值
- 例如:mhxysy:SEVER:1
- 所有key的前缀,根据业务功能,以常量的形式保存在同一个接口中;
- 一个业务的Redis缓存对应一个缓存类,使代码易于维护,把缓存的代码统一编写在一个类里,如果想要取消缓存,只需要修改这个缓存类的代码即可。缓存类可以根据自己的喜好来命名,如XxxRepository;
- 为了体现面向接口的开发原则,可以让所有Reids得缓存类实现一个代表Reids缓存的顶级接口,如RedisRepository;
代码展示
角色信息的缓存类RoleAccountRepository.java
package cn.edu.sgu.www.mhxysy.redis.repository.impl;import cn.edu.sgu.www.mhxysy.consts.RedisKeyPrefixes;
import cn.edu.sgu.www.mhxysy.entity.role.RoleAccount;
import cn.edu.sgu.www.mhxysy.redis.RedisUtils;
import cn.edu.sgu.www.mhxysy.redis.repository.RedisRepository;
import cn.edu.sgu.www.mhxysy.util.TimerUtils;
import cn.edu.sgu.www.mhxysy.vo.role.RoleAccountVO;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import java.util.List;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;/*** @author heyunlin* @version 1.0*/
@Slf4j
@Component
public class RoleAccountRepository implements RedisRepository {private final RedisUtils redisUtils;public RoleAccountRepository(RedisUtils redisUtils) {this.redisUtils = redisUtils;}@Overridepublic void put(String id, Object value) {String key = RedisKeyPrefixes.PREFIX_ROLE_ACCOUNT + id;redisUtils.set(key, JSON.toJSONString(value));redisUtils.expire(key, 7, TimeUnit.DAYS);}@Overridepublic RoleAccount get(String id) {String key = RedisKeyPrefixes.PREFIX_ROLE_ACCOUNT + id;String value = redisUtils.get(key);if (value != null) {log.debug("命中缓存{}", key);}return JSON.parseObject(value, RoleAccount.class);}@Overridepublic void putList(Object value) {String key = RedisKeyPrefixes.PREFIX_ROLE_ACCOUNTS;redisUtils.set(key, JSON.toJSONString(value), 7, TimeUnit.DAYS);}@Overridepublic List<RoleAccount> getList() {String key = RedisKeyPrefixes.PREFIX_ROLE_ACCOUNTS;String value = redisUtils.get(key);if (value != null) {log.debug("命中缓存{}", key);return JSON.parseArray(value, RoleAccount.class);}return null;}@Overridepublic void delete() {String key = RedisKeyPrefixes.PREFIX_ROLE_ACCOUNTS;redisUtils.delete(key);}@Overridepublic void delete(String primaryKey) {redisUtils.delete(RedisKeyPrefixes.PREFIX_ROLE_ACCOUNT + primaryKey);}@Overridepublic void delayDoubleDelete(String primaryKey, Consumer<String> consumer) {delete();delete(primaryKey);deleteCache(primaryKey);consumer.accept(primaryKey);// 延时双删TimerUtils.schedule(new TimerTask() {@Overridepublic void run() {delete();delete(primaryKey);deleteCache(primaryKey);}});}public void cacheRole(String roleId, RoleAccountVO roleAccountVO) {String key = RedisKeyPrefixes.PREFIX_ROLE_DETAIL + roleId;redisUtils.set(key, JSON.toJSONString(roleAccountVO));}public RoleAccountVO getCache(String roleId) {String key = RedisKeyPrefixes.PREFIX_ROLE_DETAIL + roleId;String value = redisUtils.get(key);if (value != null) {log.debug("命中缓存{}...", key);return JSON.parseObject(value, RoleAccountVO.class);}return null;}public void deleteCache(String roleId) {String key = RedisKeyPrefixes.PREFIX_ROLE_DETAIL + roleId;redisUtils.delete(key);}}
具体的角色service层方法
package cn.edu.sgu.www.mhxysy.service.role.impl;import cn.edu.sgu.www.mhxysy.base.Pager;
import cn.edu.sgu.www.mhxysy.dto.role.RoleAccountDTO;
import cn.edu.sgu.www.mhxysy.easyexel.impl.RoleAccountExcelData;
import cn.edu.sgu.www.mhxysy.entity.gang.Gang;
import cn.edu.sgu.www.mhxysy.entity.role.Account;
import cn.edu.sgu.www.mhxysy.entity.role.RoleAccount;
import cn.edu.sgu.www.mhxysy.entity.role.RoleModeling;
import cn.edu.sgu.www.mhxysy.entity.school.School;
import cn.edu.sgu.www.mhxysy.entity.server.Server;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import cn.edu.sgu.www.mhxysy.mapper.role.JiadianSchemaMapper;
import cn.edu.sgu.www.mhxysy.mapper.role.RoleAccountMapper;
import cn.edu.sgu.www.mhxysy.mapper.role.RoleAttributeMapper;
import cn.edu.sgu.www.mhxysy.mapper.role.RoleJiadianMapper;
import cn.edu.sgu.www.mhxysy.mapper.school.SchoolSkillCategoryMapper;
import cn.edu.sgu.www.mhxysy.mapper.school.SchoolSkillMapper;
import cn.edu.sgu.www.mhxysy.redis.repository.impl.RoleAccountRepository;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import cn.edu.sgu.www.mhxysy.service.gang.GangService;
import cn.edu.sgu.www.mhxysy.service.role.AccountService;
import cn.edu.sgu.www.mhxysy.service.role.RoleAccountService;
import cn.edu.sgu.www.mhxysy.service.role.RoleModelingService;
import cn.edu.sgu.www.mhxysy.service.school.SchoolService;
import cn.edu.sgu.www.mhxysy.service.server.ServerService;
import cn.edu.sgu.www.mhxysy.vo.role.RoleAccountVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;/*** @author heyunlin* @version 1.0*/
@Service
public class RoleAccountServiceImpl implements RoleAccountService {private final RoleAccountMapper roleAccountMapper;private final RoleJiadianMapper roleJiadianMapper;private final SchoolSkillMapper schoolSkillMapper;private final JiadianSchemaMapper jiadianSchemaMapper;private final RoleAttributeMapper roleAttributeMapper;private final RoleAccountRepository roleAccountRepository;private final SchoolSkillCategoryMapper schoolSkillCategoryMapper;private final GangService gangService;private final ServerService serverService;private final SchoolService schoolService;private final AccountService accountService;private final RoleModelingService roleModelingService;@Autowiredpublic RoleAccountServiceImpl(RoleAccountMapper roleAccountMapper,RoleJiadianMapper roleJiadianMapper,SchoolSkillMapper schoolSkillMapper,JiadianSchemaMapper jiadianSchemaMapper,RoleAttributeMapper roleAttributeMapper,RoleAccountRepository roleAccountRepository,SchoolSkillCategoryMapper schoolSkillCategoryMapper,GangService gangService,ServerService serverService,SchoolService schoolService,AccountService accountService,RoleModelingService roleModelingService) {this.roleAccountMapper = roleAccountMapper;this.roleJiadianMapper = roleJiadianMapper;this.schoolSkillMapper = schoolSkillMapper;this.jiadianSchemaMapper = jiadianSchemaMapper;this.roleAttributeMapper = roleAttributeMapper;this.roleAccountRepository = roleAccountRepository;this.schoolSkillCategoryMapper = schoolSkillCategoryMapper;this.gangService = gangService;this.serverService = serverService;this.schoolService = schoolService;this.accountService = accountService;this.roleModelingService = roleModelingService;}@Overridepublic RoleAccount selectById(String roleId) {RoleAccount roleAccount = roleAccountRepository.get(roleId);if (roleAccount == null) {roleAccount = roleAccountMapper.selectById(roleId);roleAccountRepository.put(roleId, roleAccount);}return roleAccount;}}
Redis的key前缀常量接口代码展示
package cn.edu.sgu.www.mhxysy.consts;/*** redis的key前缀的常量接口* @author heyunlin* @version 1.0*/
public interface RedisKeyPrefixes {String PREFIX_BASE = "mhxysy:";/*** 用户的邮箱*/String PREFIX_EMAIL = PREFIX_BASE + "EMAIL:";/*** 用户登录的验证码*/String PREFIX_CAPTCHA = PREFIX_BASE + "CAPTCHA:";/*** 用户的侧栏菜单*/String PREFIX_USER_LEFT_MENUS = PREFIX_BASE + "USER_LEFT_MENUS:";/*** 角色的菜单树*/String PREFIX_ROLE_MENU_TREE = PREFIX_BASE + "ROLE_MENU_TREE:";/*** 用户登录的次数*/String PREFIX_USER_LOGIN_TIMES = PREFIX_BASE + "USER_LOGIN_TIMES:";/*** shiro缓存认证管理*/String PREFIX_CACHE_MANAGER = PREFIX_BASE + "AUTHORIZATION:CACHE_MANAGER:";/*** 角色高级属性*/String PREFIX_ADVANCED_PROPERTY = PREFIX_BASE + "ROLE_GJSX:";/*** 角色详情*/String PREFIX_ROLE_DETAIL = PREFIX_BASE + "ROLE_DETAIL:";/*** 角色*/String PREFIX_ROLE_ACCOUNT = PREFIX_BASE + "ROLE_ACCOUNT:";/*** 角色列表*/String PREFIX_ROLE_ACCOUNTS = PREFIX_BASE + "ROLE_ACCOUNTS:";/*** 角色造型*/String PREFIX_ROLE_MODELING = PREFIX_BASE + "ROLE_MODELING:";/*** 角色造型列表*/String PREFIX_ROLE_MODELINGS = PREFIX_BASE + "ROLE_MODELINGS";/*** 帮派*/String PREFIX_GANG = PREFIX_BASE + "GANG:";/*** 帮派列表*/String PREFIX_GANGS = PREFIX_BASE + "GANGS";/*** 帮派职务*/String PREFIX_GANG_JOB = PREFIX_BASE + "GANG_JOB:";/*** 帮派职务列表*/String PREFIX_GANG_JOBS = PREFIX_BASE + "GANG_JOBS";/*** 门派*/String PREFIX_SCHOOL = PREFIX_BASE + "SCHOOL:";/*** 门派列表*/String PREFIX_SCHOOLS = PREFIX_BASE + "SCHOOLS";/*** 宠物*/String PREFIX_CHONGWU = PREFIX_BASE + "CHONGWU:";/*** 宠物列表*/String PREFIX_CHONGWUS = PREFIX_BASE + "CHONGWUS";/*** 宠物类型*/String PREFIX_CHONGWU_CATEGORY = PREFIX_BASE + "CHONGWU_CATEGORY:";/*** 宠物类型列表*/String PREFIX_CHONGWU_CATEGORIES = PREFIX_BASE + "CHONGWU_CATEGORIES";/*** 大区*/String PREFIX_AREA = PREFIX_BASE + "AREA:";/*** 大区列表*/String PREFIX_AREAS = PREFIX_BASE + "AREAS";/*** 服务器*/String PREFIX_SERVER = PREFIX_BASE + "SERVER:";/*** 服务器列表*/String PREFIX_SERVERS = PREFIX_BASE + "SERVERS";/*** 账号*/String PREFIX_ACCOUNT = PREFIX_BASE + "ACCOUNT:";/*** 账号列表*/String PREFIX_ACCOUNTS = PREFIX_BASE + "ACCOUNTS";
}
Redis缓存顶级接口
package cn.edu.sgu.www.mhxysy.redis.repository;import java.util.function.Consumer;/*** redis仓库的顶级接口:为了满足开闭原则设计了此接口* @author heyunlin* @version 1.0*/
public interface RedisRepository {void put(String key, Object value);Object get(String key);void putList(Object value);Object getList();/*** 删除数据缓存*/void delete();/*** 删除指定ID的数据缓存* @param primaryKey 数据的ID*/void delete(String primaryKey);/*** 延时双删* @param primaryKey 数据的ID* @param consumer Consumer<String>*/default void delayDoubleDelete(String primaryKey, Consumer<String> consumer) { }}
好了,文章就分享到这里了,后续会持续优化文章内容,感谢大家的支持~
最后,如果看完这篇文章觉得对你有所帮助或者启发,不要忘了点赞+收藏哦~
相关文章:
个人推荐Redis比较好的一种使用规范
随着对个人项目的不断开发、迭代和重构,博主在这个过程中总结出了一套使用redis的较好的规范。主要包含Redis的key命名规范和Redis代码规范。 主要内容 主要包含以下几个内容: 同一应用的key在最前面添加统一的前缀,如应用名; 案…...
【教程】宝塔default.db占用空间几十g解决方法|宝塔占用磁盘空间特别大解决方法|宝塔磁盘被占满怎么清理
目录 一、前言二、排查问题三、解决方法 一、前言 用过宝塔创建网站,大家应该都非常熟悉,但是用随着用的时间越来越多,宝塔所占用的空间也越来越多,不停的加大数据盘都没有用,我原先买了30G够用了,随着时间…...
Unity类银河恶魔城学习记录11-15 p117 Ice and Fire item Effect源代码
Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili IceAndFire_Controller.cs using System.Collections; using System.Coll…...
Qt QML的枚举浅用
QML的枚举用法 序言概念命名规则在QML定义枚举的规范 用法QML的枚举定义方法供QML调用的,C的枚举定义方法 序言 概念 QML的枚举和C的其实差不多,但是呢,局限比较多,首先不能在main.qml里定义,也不能在子项中定义。 …...
设计模式:单例模式六种实现
单例模式有多种实现方式,每种方式都有其设计思想、优缺点以及适用的使用场景。以下是一些常见的单例实现方式: 1. 懒汉式(线程不安全) 设计思想 这种实现方式采用了类加载的懒加载机制来保证单例只在第一次使用时被创建。 实现代码 public class Singleton {private s…...
Mybatis-Plus05(分页插件)
分页插件 MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能 1. 添加配置类 Configuration MapperScan("com.atguigu.mybatisplus.mapper") //可以将主类中的注解移到此处 public class MybatisPlusConfig {Bean public MybatisPlusIntercepto…...
python爬取B站视频
参考:https://cloud.tencent.com/developer/article/1768680 参考的代码有点问题,请求头需要修改,上代码: import requests import re # 正则表达式 import pprint import json from moviepy.editor import AudioFileClip, Vid…...
深度学习500问——Chapter05: 卷积神经网络(CNN)(2)
文章目录 5.6 有哪些池化方法 5.7 1x1卷积作用 5.8 卷积层和池化层有什么区别 5.9 卷积核是否一定越大越好 5.10 每层卷积是否只能用一种尺寸的卷积核 5.11 怎样才能减少卷积层参数量 5.12 在进行卷积操作时,必须同时考虑通道和区域吗 5.13 采用宽卷积的好处有什么 …...
基于单片机的测时仪系统设计
**单片机设计介绍,基于单片机的测时仪系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的测时仪系统设计是一个结合了单片机技术与测时技术的综合性项目。该设计的目标是创建一款精度高、稳定性强且…...
鸿蒙原生应用开发-网络管理Socket连接(三)
应用通过TLS Socket进行加密数据传输 开发步骤 客户端TLS Socket流程: 1.import需要的socket模块。 2.绑定服务器IP和端口号。 3.双向认证上传客户端CA证书及数字证书;单向认证只上传CA证书,无需上传客户端证书。 4.创建一个TLSSocket连接…...
【Java EE】关于Maven
文章目录 🎍什么是Maven🌴为什么要学Maven🌲创建⼀个Maven项目🌳Maven核心功能🌸项目构建🌸依赖管理 🍀Maven Help插件🎄Maven 仓库🌸本地仓库🌸私服 ⭕总结 …...
每日一题:C语言经典例题之反转数
题目描述 给定一个整数,请将该数各个数位上的数字反转得到一个新数。新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零。 题目描述 给定一个整数,请将该数各个数位上的数字反转得到一个…...
RESTfull接口访问Elasticsearch
【数据库的健康值】 curl -X GET "ip:9200/_cat/health" 【查看所有索引】 curl -X GET "ip:9200/_cat/indices?v" 【查看索引index_name】 curl -X GET "ip:9200/索引?pretty" 【创建索引/文档】 PUT "ip:9200/索引/文档id" {请…...
NoSQL之Redis
目录 一、关系型数据库与非关系型数据库 1.关系数据库 2.非关系数据库 2.1非关系型数据库产生背景 3.关系型数据库与非关系型数据区别 (1)数据存储方式不同 (2)扩展方式不同 (3)对事物性的支持不同 …...
double二分(P3743 小鸟的设备)
题目:P3743 小鸟的设备 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 代码: #include<bits/stdc.h> using namespace std; const int N2e510; double a[N],b[N]; int n; double p;bool check(double mid) {double sum0.0;for(int i1;i<n;i){if(a[i]*mi…...
【独立开发前线】Vol.36 为什么从2023年开始,独立开发者越来越多了?
不知道你有没有观察到,从2023年开始,国内的独立开发者越来越多了。 之前独立开发者是一个非常小众的群体,但现在很多互联网从业者都瞄准了这个方向,包括程序员、产品经理,运营等等。 我想可能是这样几个原因…...
GPT4不限制使用次数了!GPT5即将推出了!
今天登录到ChatGPT Plus账户,出现了如下提示: 已经没有了数量和时间限制的提示。 更改前:每 3 小时限制 40 次(团队计划为 100 次);更改后:可能会应用使用限制。 GPT-4放开限制 身边订阅了Ch…...
物联网实战--入门篇之(六)嵌入式-WIFI驱动(ESP8266)
目录 一、WIFI简介 二、基础网络知识 三、思路讲解 四、代码分析 4.1 状态机制 4.2 客户端连接 4.3 应用数据接收处理 4.4 数据发送 4.5 主函数调用 4.6 网络连接ID分配 五、总结 一、WIFI简介 WIFI在我们生活中太常见了,手机电脑都可以用WiFi连接路由器进行上…...
Java并发编程基础面试题详细总结
1. 什么是线程和进程? 1.1 何为进程? 进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。 在 Java 中,当我们启动 main 函数时其实就是启动了一个…...
EKO / 砍树
暴力是不行的,还得是二分吧 题目描述 伐木工人 Mirko 需要砍 M 米长的木材。对 Mirko 来说这是很简单的工作,因为他有一个漂亮的新伐木机,可以如野火一般砍伐森林。不过,Mirko 只被允许砍伐一排树。 Mirko 的伐木机工作流程如下&a…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)
引言 在嵌入式系统中,用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例,介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单,执行相应操作,并提供平滑的滚动动画效果。 本文设计了一个…...
GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...
shell脚本质数判断
shell脚本质数判断 shell输入一个正整数,判断是否为质数(素数)shell求1-100内的质数shell求给定数组输出其中的质数 shell输入一个正整数,判断是否为质数(素数) 思路: 1:1 2:1 2 3:1 2 3 4:1 2 3 4 5:1 2 3 4 5-------> 3:2 4:2 3 5:2 3…...
claude3.7高阶玩法,生成系统架构图,国内直接使用
文章目录 零、前言一、操作指南操作指导 二、提示词模板三、实战图书管理系统通过4o模型生成系统描述通过claude3.7生成系统架构图svg代码转换成图片 在线考试系统通过4o模型生成系统描述通过claude3.7生成系统架构图svg代码转换成图片 四、感受 零、前言 现在很多AI大模型可以…...
