Redis工具类(解决缓存穿透、缓存击穿)
文章目录
- 前言
- IBloomFilter
- ObjectMapUtils
- CacheClient
- 使用示例
- 具体业务的布隆过滤器
- 控制层
- 服务层
前言
该工具类包含以下功能:
1.将任意对象存储在 hash 类型的 key 中,并可以设置 TTL
2.将任意对象存储在 hash 类型的 key 中,并且可以设置逻辑过期时间
3.将空对象存入 hash 类型的 key 中,并且可以设置超时时间
4.缓存空对象解决缓存穿透
5.布隆过滤器解决缓存穿透
6.布隆过滤器+缓存空对象解决缓存穿透
7.互斥锁解决缓存击穿
8.逻辑过期解决缓存击穿
以下是关键代码
IBloomFilter
IBloomFilter 是自定义的布隆过滤器接口。这里使用接口的原因在于,每个业务使用的布隆过滤器可能是不一样的,因此为了让工具类能兼容所有的布隆过滤器,这里添加接口,并使用泛型表示布隆过滤器内部存储数据的类型
public interface IBloomFilter<T> {// 添加void add(T id);// 判断是否存在boolean mightContain(T id);}
ObjectMapUtils
ObjectMapUtils 是对象与 Map 类型的相互转换,可以让对象转换为 Map 集合,也可以让 Map 集合转回对象
public class ObjectMapUtils {// 将对象转为 Mappublic static Map<String, String> obj2Map(Object obj) throws IllegalAccessException {Map<String, String> result = new HashMap<>();Class<?> clazz = obj.getClass();Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {// 如果为 static 且 final 则跳过if (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers())) {continue;}field.setAccessible(true); // 设置为可访问私有字段Object fieldValue = field.get(obj);if (fieldValue != null) {result.put(field.getName(), field.get(obj).toString());}}return result;}// 将 Map 转为对象public static<R> R map2Obj(Map<Object, Object> map, Class<R> clazz) throws Exception {R obj = clazz.getDeclaredConstructor().newInstance();for (Map.Entry<Object, Object> entry : map.entrySet()) {Object fieldName = entry.getKey();Object fieldValue = entry.getValue();Field field = clazz.getDeclaredField(fieldName.toString());field.setAccessible(true); // 设置为可访问私有字段String fieldValueStr = fieldValue.toString();// 根据字段类型进行转换fillField(obj, field, fieldValueStr);}return obj;}// 将 Map 转为对象(含排除字段)public static<R> R map2Obj(Map<Object, Object> map, Class<R> clazz, String... excludeFields) throws Exception {R obj = clazz.getDeclaredConstructor().newInstance();for (Map.Entry<Object, Object> entry : map.entrySet()) {Object fieldName = entry.getKey();if(Arrays.asList(excludeFields).contains(fieldName)) {continue;}Object fieldValue = entry.getValue();Field field = clazz.getDeclaredField(fieldName.toString());field.setAccessible(true); // 设置为可访问私有字段String fieldValueStr = fieldValue.toString();// 根据字段类型进行转换fillField(obj, field, fieldValueStr);}return obj;}// 填充字段private static void fillField(Object obj, Field field, String value) throws IllegalAccessException {if (field.getType().equals(int.class) || field.getType().equals(Integer.class)) {field.set(obj, Integer.parseInt(value));} else if (field.getType().equals(boolean.class) || field.getType().equals(Boolean.class)) {field.set(obj, Boolean.parseBoolean(value));} else if (field.getType().equals(double.class) || field.getType().equals(Double.class)) {field.set(obj, Double.parseDouble(value));} else if (field.getType().equals(long.class) || field.getType().equals(Long.class)) {field.set(obj, Long.parseLong(value));} else if (field.getType().equals(String.class)) {field.set(obj, value);} else if(field.getType().equals(LocalDateTime.class)) {field.set(obj, LocalDateTime.parse(value));}// 如果有需要可以继续添加...}}
CacheClient
CacheClient 就是缓存工具类,包含了之前提到的所有功能
@Component
@Slf4j
public class CacheClient {@Autowiredprivate StringRedisTemplate redisTemplate;// 重建缓存线程池private static final ExecutorService CACHE_REBUILD_EXECUTOR = Executors.newFixedThreadPool(10);// 将任意对象存储在 hash 类型的 key 中,并可以设置 TTLpublic void setByHash(String key, Object value, Long time, TimeUnit unit) throws IllegalAccessException {redisTemplate.opsForHash().putAll(key, ObjectMapUtils.obj2Map(value));redisTemplate.expire(key, time, unit);}// 将任意对象存储在 hash 类型的 key 中,并且可以设置逻辑过期时间public void setWithLogicalExpireByHash(String key, Object value, Long time, TimeUnit unit) throws IllegalAccessException {Map<String, String> map = ObjectMapUtils.obj2Map(value);// 添加逻辑过期时间map.put(RedisConstants.EXPIRE_KEY, LocalDateTime.now().plusSeconds(unit.toSeconds(time)).toString());redisTemplate.opsForHash().putAll(key, map);}// 将空对象存入 hash 类型的 key 中,并且可以设置超时时间public void setNullByHash(String key, Long time, TimeUnit unit) {redisTemplate.opsForHash().put(key, "", "");redisTemplate.expire(key, time, unit);}// 尝试加锁private boolean tryLock(String key, Long time, TimeUnit unit) {Boolean isLocked = redisTemplate.opsForValue().setIfAbsent(key,"1", time, unit);return Boolean.TRUE.equals(isLocked);}// 解锁private void unlock(String key) {redisTemplate.delete(key);}// 缓存空对象解决缓存穿透public<R, ID> R queryWithCacheNull(String keyPrefix, ID id, Class<R> clazz, Function<ID, R> dbFallback,Long time, TimeUnit unit) {// 从 redis 查询String key = keyPrefix + id;Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);// 缓存命中if (!entries.isEmpty()) {try {// 如果是空对象,表示一定不存在数据库中,直接返回(解决缓存穿透)if (entries.containsKey("")) {log.info("redis查询到id={}的空对象,", id);return null;}// 刷新有效期redisTemplate.expire(key, time, unit);R r = ObjectMapUtils.map2Obj(entries, clazz);log.info("缓存命中,结果为:{}", r);return r;} catch (Exception e) {throw new RuntimeException(e);}}// 查询数据库R r = dbFallback.apply(id);if (r == null) {log.info("id={}不存在于数据库,存入redis", id);// 存入空值setNullByHash(key, RedisConstants.CACHE_NULL_TTL, TimeUnit.MINUTES);// 不存在,直接返回return null;}// 存在,写入 redistry {setByHash(key, r, time, unit);} catch (IllegalAccessException e) {throw new RuntimeException(e);}log.info("查询数据库,获取结果:{}", r);return r;}// 布隆过滤器解决缓存穿透public<R, ID> R queryWithBloom(String keyPrefix, ID id, Class<R> clazz, Function<ID, R> dbFallback,Long time, TimeUnit unit, IBloomFilter<ID> bloomFilter) {// 如果不在布隆过滤器中,直接返回if (!bloomFilter.mightContain(id)) {log.info("id={}不存在于布隆过滤器", id);return null;}// 从 redis 查询String key = keyPrefix + id;Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);// 缓存命中if (!entries.isEmpty()) {try {// 刷新有效期redisTemplate.expire(key, time, unit);R r = ObjectMapUtils.map2Obj(entries, clazz);log.info("缓存命中,结果为:{}", r);return r;} catch (Exception e) {throw new RuntimeException(e);}}// 查询数据库R r = dbFallback.apply(id);if (r == null) {log.info("id={}不存在于数据库", id);// 不存在,直接返回return null;}// 存在,写入 redistry {setByHash(key, r, time, unit);} catch (IllegalAccessException e) {throw new RuntimeException(e);}log.info("查询数据库,获取结果:{}", r);return r;}// 布隆过滤器+缓存空对象解决缓存穿透public<R, ID> R queryWithBloomAndCacheNull(String keyPrefix, ID id, Class<R> clazz, Function<ID, R> dbFallback,Long time, TimeUnit unit, IBloomFilter<ID> bloomFilter) {// 如果不在布隆过滤器中,直接返回if (!bloomFilter.mightContain(id)) {log.info("id={}不存在于布隆过滤器", id);return null;}// 从 redis 查询String key = keyPrefix + id;Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);// 缓存命中if (!entries.isEmpty()) {try {// 如果是空对象,表示一定不存在数据库中,直接返回(解决缓存穿透)if (entries.containsKey("")) {log.info("redis查询到id={}的空对象,", id);return null;}// 刷新有效期redisTemplate.expire(key, RedisConstants.CACHE_SHOP_TTL, TimeUnit.MINUTES);R r = ObjectMapUtils.map2Obj(entries, clazz);log.info("缓存命中,结果为:{}", r);return r;} catch (Exception e) {throw new RuntimeException(e);}}// 查询数据库R r = dbFallback.apply(id);if (r == null) {log.info("id={}不存在于数据库,存入redis", id);// 存入空值setNullByHash(key, RedisConstants.CACHE_NULL_TTL, TimeUnit.MINUTES);// 不存在,直接返回return null;}// 存在,写入 redistry {setByHash(key, r, time, unit);} catch (IllegalAccessException e) {throw new RuntimeException(e);}log.info("查询数据库,获取结果:{}", r);return r;}// 互斥锁解决缓存击穿public<R, ID> R queryWithMutex(String keyPrefix, ID id, Class<R> clazz, Function<ID, R> dbFallback,Long cacheTime, TimeUnit cacheUnit, String lockKeyPrefix,Long lockTime, TimeUnit lockUnit) {String key = keyPrefix + id;String lockKey = lockKeyPrefix + id;boolean flag = false;int cnt = 10; // 重试次数try {do {// 从 redis 查询Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);// 缓存命中if (!entries.isEmpty()) {try {// 刷新有效期redisTemplate.expire(key, RedisConstants.CACHE_SHOP_TTL, TimeUnit.MINUTES);R r = ObjectMapUtils.map2Obj(entries, clazz);log.info("缓存命中,结果为:{}", r);return r;} catch (Exception e) {throw new RuntimeException(e);}}// 缓存未命中,尝试获取互斥锁log.info("缓存未命中,尝试获取互斥锁 id={}", id);flag = tryLock(lockKey, lockTime, lockUnit);if (flag) { // 获取成功,进行下一步log.info("成功获取互斥锁 id={}", id);break;}// 获取失败,睡眠后重试Thread.sleep(50);} while ((--cnt) != 0); // 未获取到锁,休眠后重试if(!flag) { // 重试次数到达上限log.info("重试次数达到上限 id={}", id);return null;}// 查询数据库R r = dbFallback.apply(id);if (r == null) {log.info("id={}不存在于数据库", id);// 不存在,直接返回return null;}// 存在,写入 redistry {setByHash(key, r, cacheTime, cacheUnit);} catch (IllegalAccessException e) {throw new RuntimeException(e);}log.info("查询数据库,获取结果:{}", r);return r;} catch (InterruptedException e) {throw new RuntimeException(e);} finally {if (flag) { // 获取了锁需要释放log.info("解锁id={}", id);unlock(lockKey);}}}// 逻辑过期解决缓存击穿public<R, ID> R queryWithLogicalExpire(String keyPrefix, ID id, Class<R> clazz, Function<ID, R> dbFallback,Long expireTime, TimeUnit expireUnit,String lockKeyPrefix, Long lockTime, TimeUnit lockUnit) {String key = keyPrefix + id;String lockKey = lockKeyPrefix + id;// 从 redis 查询Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);// 缓存未命中,返回空if(entries.isEmpty()) {log.info("缓存未命中,返回空 id={}", id);return null;}try {R r = ObjectMapUtils.map2Obj(entries, clazz, RedisConstants.EXPIRE_KEY);LocalDateTime expire = LocalDateTime.parse(entries.get(RedisConstants.EXPIRE_KEY).toString());// 判断缓存是否过期if(expire.isAfter(LocalDateTime.now())) {// 未过期则直接返回log.info("缓存未过期,结果为;{}", r);return r;}// 过期需要先尝试获取互斥锁log.info("尝试获取互斥锁 id={}", id);if(tryLock(lockKey, lockTime, lockUnit)) {log.info("获得到互斥锁 id={}", id);// 获取成功// 双重检验entries = redisTemplate.opsForHash().entries(key);r = ObjectMapUtils.map2Obj(entries, clazz, RedisConstants.EXPIRE_KEY);expire = LocalDateTime.parse(entries.get(RedisConstants.EXPIRE_KEY).toString());if(expire.isAfter(LocalDateTime.now())) {// 未过期则直接返回log.info("缓存未过期,结果为;{}", r);log.info("解锁 id={}", id);unlock(lockKey);return r;}// 通过线程池完成重建缓存任务CACHE_REBUILD_EXECUTOR.submit(() -> {try {log.info("进行重建缓存任务 id={}", id);setWithLogicalExpireByHash(key, dbFallback.apply(id), expireTime, expireUnit);} catch (Exception e) {throw new RuntimeException(e);} finally {log.info("解锁 id={}", id);unlock(lockKey);}});}log.info("返回结果:{}", r);return r;} catch (Exception e) {throw new RuntimeException(e);}}}
使用示例
具体业务的布隆过滤器
public class ShopBloomFilter implements IBloomFilter<Long> {private BloomFilter<Long> bloomFilter;public ShopBloomFilter(ShopMapper shopMapper) {// 初始化布隆过滤器,设计预计元素数量为100_0000L,误差率为1%bloomFilter = BloomFilter.create(Funnels.longFunnel(), 100_0000, 0.01);// 将数据库中已有的店铺 id 加入布隆过滤器List<Shop> shops = shopMapper.selectList(null);for (Shop shop : shops) {bloomFilter.put(shop.getId());}}public void add(Long id) {bloomFilter.put(id);}public boolean mightContain(Long id){return bloomFilter.mightContain(id);}}
控制层
/*** 根据id查询商铺信息* @param id 商铺id* @return 商铺详情数据*/
@GetMapping("/{id}")
public Result queryShopById(@PathVariable("id") Long id) {return shopService.queryShopById(id);
}
服务层
@Override
public Result queryShopById(Long id) {// 缓存空对象解决缓存穿透/*Shop shop = cacheClient.queryWithCacheNull(RedisConstants.CACHE_SHOP_KEY,id, Shop.class, this::getById, RedisConstants.CACHE_SHOP_TTL, TimeUnit.MINUTES);*/// 布隆过滤器解决缓存穿透/*Shop shop = cacheClient.queryWithBloom(RedisConstants.CACHE_SHOP_KEY,id, Shop.class, this::getById, RedisConstants.CACHE_SHOP_TTL, TimeUnit.MINUTES, shopBloomFilter);*/// 布隆过滤器+缓存空对象解决缓存穿透/*Shop shop = cacheClient.queryWithBloomAndCacheNull(RedisConstants.CACHE_SHOP_KEY,id, Shop.class, this::getById, RedisConstants.CACHE_SHOP_TTL, TimeUnit.MINUTES, shopBloomFilter);*/// 互斥锁解决缓存击穿/*Shop shop = cacheClient.queryWithMutex(RedisConstants.CACHE_SHOP_KEY, id, Shop.class, this::getById,RedisConstants.CACHE_SHOP_TTL, TimeUnit.MINUTES,RedisConstants.LOCK_SHOP_KEY, RedisConstants.LOCK_SHOP_TTL, TimeUnit.SECONDS);*/// 逻辑过期解决缓存击穿Shop shop = cacheClient.queryWithLogicalExpire(RedisConstants.CACHE_SHOP_KEY, id, Shop.class, this::getById,RedisConstants.CACHE_SHOP_TTL, TimeUnit.MINUTES,RedisConstants.LOCK_SHOP_KEY, RedisConstants.LOCK_SHOP_TTL, TimeUnit.SECONDS);if(shop == null) {return Result.fail("商铺不存在");}return Result.ok(shop);
}
相关文章:
Redis工具类(解决缓存穿透、缓存击穿)
文章目录 前言IBloomFilterObjectMapUtilsCacheClient使用示例具体业务的布隆过滤器控制层服务层 前言 该工具类包含以下功能: 1.将任意对象存储在 hash 类型的 key 中,并可以设置 TTL 2.将任意对象存储在 hash 类型的 key 中,并且可以设置…...
Air780E量产binpkg文件的获取方法
Air780E量产binpkg文件如何获取呢?操作方法如下。 一、背景 最近luatos开发客户增多,客户在量产烧录的时候需要binpkg文件,但是有些客户不知道binpkg文件是什么,在哪里获取,是否可以用soc文件提取出来,使…...
C++STL之stack
1.stack的使用 函数说明 接口说明 stack() 构造空的栈 empty() 检测 stack 是否为空 size() 返回 stack 中元素的个数 top() 返回栈顶元素的引用 push() 将元素 val 压入 stack 中 pop() 将 stack 中尾部的元素弹出 2.stack的模拟实现 #include<vector> namespace abc { …...
git的学习之远程进行操作
1.代码托管GitHub:充当中央服务器仓库的角色 2.git远程进行操作 3.配置本地服务器的公钥 4.推送 5.git远程操作 pull .gitignore 6.给命令配置别名 git config --global alias.st status 7.标签管理 git tag -a [name] -m "XXX" [commit_id] 操作标签…...
蓝桥杯普及题
[蓝桥杯 2024 省 B] 好数 题目描述 一个整数如果按从低位到高位的顺序,奇数位(个位、百位、万位……)上的数字是奇数,偶数位(十位、千位、十万位……)上的数字是偶数,我们就称之为“好数”。 给定一个正整数 N N N,请计算从 1 1...
Spreadsheet导出excel
记录下常用的方法 数字转字符:Coordinate::stringFromColumnIndex(27); 输出 AA字符转数字:Coordinate::columnIndexFromString(AA); 输出27设置单元格式 eg:(设置为保留两位小数点) $sheet->getStyle($columnLetter)->getNumberFormat()->set…...
Leetcode|454.四数相加II ● 383. 赎金信 ● 15. 三数之和 ● 18. 四数之和
15.三数之和 哈希解法: 用俩个for循环求出,所需的a和b,再用哈希表,判断剩余的那个c是否在数组 class Solution { public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>…...
使用ceph-csi把ceph-fs做为k8s的storageclass使用
背景 ceph三节点集群除了做为对象存储使用,计划使用cephfs替代掉k8s里面现有的nfs-storageclass。 思路 整体实现参考ceph官方的ceph csi实现,这套环境是arm架构的,即ceph和k8s都是在arm上实现。实测下来也兼容。 ceph-fs有两种两种挂载方…...
太速科技-212-RCP-601 CPCI刀片计算机
RCP-601 CPCI刀片计算机 一、产品简介 RCP-601是一款基于Intel i7双核四线程的高性能CPCI刀片式计算机,同时,将CPCI产品的欧卡结构及其可靠性、可维护性、可管理性与计算机的抗振动、抗冲击、抗宽温环境急剧变化等恶劣环境特性进行融合。产品特别…...
【解决 Windows 下 SSH “Bad owner or permissions“ 错误及端口转发问题详解】
使用 Windows 连接远程服务器出现 Bad owner or permissions 错误及解决方案 在 Windows 系统上连接远程服务器时,使用 SSH 可能会遇到以下错误: Bad owner or permissions on C:\Users\username/.ssh/config这个问题通常是由于 SSH 配置文件 .ssh/con…...
使用预训练的BERT进行金融领域问答
获取更多完整项目代码数据集,点此加入免费社区群 : 首页-置顶必看 1. 项目简介 本项目旨在开发并优化一个基于预训练BERT模型的问答系统,专注于金融领域的应用。随着金融市场信息复杂性和规模的增加,传统的信息检索方法难以高效…...
ReactOS系统中MM_REGION结构体的声明
ReactOS系统中MM_REGION结构体的声明 ReactOS系统中MM_REGION结构体的声明 文章目录 ReactOS系统中MM_REGION结构体的声明MM_REGION MM_REGION typedef struct _MM_REGION {ULONG Type;//MEM_COMMIT,MEM_RESERVEULONG Protect;//PAGE_READONLYY,PAGE_READ_WRITEULONG Length;…...
web相关知识学习笔记
一, web安全属于网络信息安全的一个分支,www即全球广域网,也叫万维网,是一个分布式图形信息系统 二, 1.①安全领域,通常将用户端(浏览器端)称为前端,服务器端称为后端 ②…...
App测试环境部署
一.JDK安装 参考以下AndroidDevTools - Android开发工具 Android SDK下载 Android Studio下载 Gradle下载 SDK Tools下载 二.SDK安装 安装地址:https://www.androiddevtools.cn/ 解压 环境变量配置 变量名:ANDROID_SDK_HOME 参考步骤: A…...
【论文阅读】Tabbed Out: Subverting the Android Custom Tab Security Model
论文链接:Tabbed Out: Subverting the Android Custom Tab Security Model | IEEE Conference Publication | IEEE Xplore 总览 “Tabbed Out: Subverting the Android Custom Tab Security Model” 由 Philipp Beer 等人撰写,发表于 2024 年 IEEE Symp…...
2025 - AI人工智能药物设计 - 中药网络药理学和毒理学的研究
中药网络药理学和毒理学的研究 TCMSP:https://old.tcmsp-e.com/tcmsp.php 然后去pubchem选择:输入Molecule Name 然后进行匹配:得到了smiles 再次通过smiles:COC1C(CC(C2C1OC(CC2O)C3CCCCC3)O)O 然后再次输入:http…...
iwebsec靶场 XSS漏洞通关笔记
目录 前言 1.反射性XSS 2.存储型XSS 3.DOM型XSS 第01关 反射型XSS漏洞 1.打开靶场 2.源码分析 3.渗透 第02关 存储型XSS漏洞 1.打开靶场 2.源码分析 4.渗透 方法1: 方法2 方法3 第03关 DOM XSS漏洞 1.打开靶场 2.源码分析 3.渗透分析 3.渗透过程…...
设计模式-单例模型(单件模式、Singleton)
单例模式是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。 单例模式同时解决了两个问题, 所以违反了单一职责原则: 保证一个类只有一个实例。 为什么会有人想要控制一个类所拥有的实例…...
笔记本双系统win10+Ubuntu 20.04 无法调节亮度亲测解决
sudo add-apt-repository ppa:apandada1/brightness-controller sudo apt-get update sudo apt-get install brightness-controller-simple 安装好后找到一个太阳的图标,就是这个软件,打开后调整brightness,就可以调整亮度,可…...
零基础Java第十一期:类和对象(二)
目录 一、对象的构造及初始化 1.1. 就地初始化 1.2. 默认初始化 1.3. 构造方法 二、封装 2.1. 封装的概念 2.2. 访问限定符 2.3. 封装扩展之包 三、static成员 3.1. 再谈学生类 3.2. static修饰成员变量 一、对象的构造及初始化 1.1. 就地初始化 在声明成员变…...
NumPy包(下) python笔记扩展
9.迭代数组 nditer 是 NumPy 中的一个强大的迭代器对象,用于高效地遍历多维数组。nditer 提供了多种选项和控制参数,使得数组的迭代更加灵活和高效。 控制参数 nditer 提供了多种控制参数,用于控制迭代的行为。 1.order 参数 order 参数…...
极狐GitLab 17.5 发布 20+ 与 DevSecOps 相关的功能【一】
GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料: 极狐GitLab 官网极狐…...
Oracle 第1章:Oracle数据库概述
在讨论Oracle数据库的入门与管理时,我们可以从以下几个方面来展开第一章的内容:“Oracle数据库概述”,包括数据库的历史与发展,Oracle数据库的特点与优势。 数据库的历史与发展 数据库技术的发展可以追溯到上世纪50年代…...
7、Nodes.js包管理工具
四、包管理工具 4.1 npm(Node Package Manager) Node.js官方内置的包管理工具。 命令行下打以下命令: npm -v如果返回版本号,则说明npm可以正常使用 4.1.1npm初始化 #在包所在目录下执行以下命令 npm init #正常初始化,手动…...
网络地址转换——NAT技术详解
网络地址转换——NAT技术详解 一、引言 随着互联网的飞速发展,IP地址资源日益紧张。为了解决IP地址资源短缺的问题,NAT(Network Address Translation,网络地址转换)技术应运而生。NAT技术允许一个私有IP地址的网络通…...
问:数据库存储过程优化实践~
存储过程优化是提高数据库性能的关键环节。通过精炼SQL语句、合理利用数据库特性、优化事务管理和错误处理,可以显著提升存储过程的执行效率和稳定性。以下是对存储过程优化实践点的阐述,结合具体示例,帮助大家更好地理解和实施这些优化策略。…...
C++ vector的使用(一)
vector vector类似于数组 遍历 这里的遍历跟string那里的遍历是一样的 1.auto(范围for) 2.迭代器遍历 3.operator void vector_test1() {vector<int> v;vector<int> v1(10, 1);//初始化10个都是1的变量vector<int> v3(v1.begin(), --…...
深入浅出:ProcessPoolExecutor 处理异步生成器函数
深入浅出:ProcessPoolExecutor 处理异步生成器函数 什么是 ProcessPoolExecutor?为什么要使用 ProcessPoolExecutor 处理异步生成器函数?ProcessPoolExecutor 处理异步生成器函数的基本用法1. 导入模块2. 定义异步生成器函数3. 定义处理函数4…...
elementUI表达自定义校验,校验在v-for中
注意:本帖为公开技术贴,不得用做任何商业用途 <el-form :inline"true" :rules"rules" :model"formData" ref"formRef" class"mt-[20px]"><el-form-item label"选择区域" prop&qu…...
Elasticsearch 在linux部署 及 Docker 集群部署详解案例示范
1. 在 CentOS 上安装和配置 Elasticsearch 在 CentOS 系统下,安装 Elasticsearch 主要分为以下步骤: 1.1 准备工作 在开始安装之前,确保你的系统满足以下基本条件: CentOS 版本要求:推荐使用 CentOS 7 及以上版本。…...
wordpress商业授权/首页排名优化公司
Activity的四种状态:--Active/Runing 一个新 Activity 启动入栈后,它在屏幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态。 --Paused 当 Activity 被另一个透明或者 Dialog 样式的 Activity 覆盖时的状态。此时…...
图片本地化wordpress/公司主页网站设计
数据库设计在系统设计过程中,数据库也是一个不可以忽视的环节,数据库的设计关系到系统的稳定性,所以每个信息的管理,必须设计好,下面是我们用mysql设计的相关系统的数据库。1、 用户表2、 商品信息表…...
网页设计师培训费用图/中国seo第一人
题库来源:安全生产模拟考试一点通公众号小程序 安全员-B证(陕西省)考试题参考答案及安全员-B证(陕西省)考试试题解析由安全生产模拟考试一点通题库老师及安全员-B证(陕西省)操作证已考过的学员…...
苏州工业园区网站/快手推广网站
自定义Mvc框架结构及其使用方法 一,什么是MVC框架 MVC框架全名是model(模型)controller(控制器)view(视图文件)所构成的一种开发框架,是一种典型的软件设计典范,用一种…...
网站建设专利申请/百度搜索次数统计
干货:命令行程序mysql实际上是MySQL客户端,真正的MySQL服务器程序是mysqld,在后台运行.数据库事务具有ACID特性,用来保证多条SQL的全部执行。五、MySQL通过mysql命令行登录MySQL Client的可执行程序是mysql,MySQL Server的可执行程…...
贵州省网站建设/上海最新新闻事件今天国内
LM3S之boot loader学习笔记-1 彭会锋 (首先声明,此系列文章编写参考了很多资料,其中一些内容是原版内容的引用和整理,并加入了一些自己的见解,我已经尽量标明引用部分,如有未全部标注部分,还望见…...