Redis 工具类 与 Redis 布隆过滤器
Redis 工具类
1. 核心依赖
<!--redis-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>31.1-jre</version>
</dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.31</version>
</dependency>
2. 序列化
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");private Class<T> clazz;static {ParserConfig.getGlobalInstance().setAutoTypeSupport(true);}public FastJsonRedisSerializer(Class<T> clazz) {super();this.clazz = clazz;}@Overridepublic byte[] serialize(T t) throws SerializationException {if (t == null) {return new byte[0];}return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);}@Overridepublic T deserialize(byte[] bytes) throws SerializationException {if (bytes == null || bytes.length <= 0) {return null;}String str = new String(bytes, DEFAULT_CHARSET);return JSON.parseObject(str, clazz);}protected JavaType getJavaType(Class<?> clazz){return TypeFactory.defaultInstance().constructType(clazz);}
}
@Configuration
public class RedisSerializeConfig {@Bean@SuppressWarnings(value = { "unchecked", "rawtypes" })public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();template.setConnectionFactory(connectionFactory);FastJsonRedisSerializer serializer = new FastJsonRedisSerializer(Object.class);// 使用StringRedisSerializer来序列化和反序列化redis的key值template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(serializer);// Hash的key也采用StringRedisSerializer的序列化方式template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(serializer);template.afterPropertiesSet();return template;}
}
3. 布隆过滤器
/*** 算法过程:* 1. 首先需要k个hash函数,每个函数可以把key散列成为1个整数* 2. 初始化时,需要一个长度为n比特的数组,每个比特位初始化为0* 3. 某个key加入集合时,用k个hash函数计算出k个散列值,并把数组中对应的比特位置为1* 4. 判断某个key是否在集合时,用k个hash函数计算出k个散列值,并查询数组中对应的比特位,如果所有的比特位都是1,认为在集合中。**/
@Component
public class BloomFilterHelper<T> {private int numHashFunctions;private int bitSize;private Funnel<T> funnel;private static final int NUM_BITS = (int) 1e4;private static final double RATE = 0.03;//不存在误判为存在的概率private static void funnel(@Nullable Object o, PrimitiveSink primitiveSink) {primitiveSink.putBytes(o.toString().getBytes());}public BloomFilterHelper() {this((Funnel) BloomFilterHelper::funnel, NUM_BITS, RATE);}public BloomFilterHelper(Funnel<T> funnel, int expectedInsertions, double fpp) {this.funnel = funnel;// 计算bit数组长度bitSize = optimalNumOfBits(expectedInsertions, fpp);// 计算hash方法执行次数numHashFunctions = optimalNumOfHashFunctions(expectedInsertions, bitSize);}public int[] getHashOffset() {return new int[numHashFunctions];}public int[] murmurHashOffset(T value) {int[] offset = new int[numHashFunctions];long hash64 = Hashing.murmur3_128().hashObject(value, funnel).asLong();int hash1 = (int) hash64;int hash2 = (int) (hash64 >>> 32);for (int i = 1; i <= numHashFunctions; i++) {int nextHash = hash1 + i * hash2;if (nextHash < 0) {nextHash = ~nextHash;}offset[i - 1] = nextHash % bitSize;}return offset;}/*** 计算bit数组长度*/private int optimalNumOfBits(long n, double p) {if (p == 0) {// 设定最小期望长度p = Double.MIN_VALUE;}return (int) (-n * Math.log(p) / (Math.log(2) * Math.log(2)));}/*** 计算hash方法执行次数*/private int optimalNumOfHashFunctions(long n, long m) {return Math.max(1, (int) Math.round((double) m / n * Math.log(2)));}
}
@Component
@RequiredArgsConstructor
public class RedisBloomFilter {private final RedisTemplate redisTemplate;private final BloomFilterHelper bloomFilterHelper;public void init(String bloomFilterName) {int[] offset = bloomFilterHelper.getHashOffset();for (int i : offset) {redisTemplate.opsForValue().setBit(bloomFilterName, i, true);}}/*** 根据给定的布隆过滤器添加值*/public <T> void add(String bloomFilterName, T value) {int[] offset = bloomFilterHelper.murmurHashOffset(value);for (int i : offset) {redisTemplate.opsForValue().setBit(bloomFilterName, i, true);}}/*** 根据给定的布隆过滤器判断值是否存在*/public <T> boolean contains(String bloomFilterName, T value) {int[] offset = bloomFilterHelper.murmurHashOffset(value);for (int i : offset) {if (!redisTemplate.opsForValue().getBit(bloomFilterName, i)) {return false;}}return true;}}
4. Redis工具类
@Component
@RequiredArgsConstructor
@Slf4j
@SuppressWarnings(value = { "unchecked", "rawtypes" })
public class RedisCache {private final RedisTemplate redisTemplate;private final RedisBloomFilter redisBloomFilter;/*** 设置有效时间** @param key Redis键* @param timeout 超时时间* @return true=设置成功;false=设置失败*/public Boolean expire(final String key, final long timeout, final TimeUnit timeUnit) {log.info("为 Redis 的键值设置超时时间\t[{}]-[{} {}]", key, timeout, timeUnit.name());return redisTemplate.expire(key, timeout, timeUnit);}/*** 原子设置过期时间* @param key* @param value* @param timeout*/public <T> void execute(final String key, final T value, final long timeout, final TimeUnit timeUnit) {log.info("尝试存入 Redis\t[{}]-[{}],超时时间:[{} {}]", key, value, timeout, timeUnit.name());redisTemplate.execute(new SessionCallback() {@Overridepublic Object execute(RedisOperations redisOperations) throws DataAccessException {redisOperations.multi();redisOperations.opsForValue().set(key, value);redisOperations.expire(key, timeout, timeUnit);return redisOperations.exec();}});}/*** 获得对象的剩余存活时间* @param key 键* @return 剩余存活时间*/public long getKeyTTL(final String key, final TimeUnit timeUnit) {int ttl = Math.toIntExact(redisTemplate.opsForValue().getOperations().getExpire(key));String message = null;switch (ttl) {case -1:message = "没有设置过期时间";break;case -2:message = "key不存在";break;default:message = ttl + " " + TimeUnit.SECONDS.name();break;}log.info("查询 Redis key[{}] 剩余存活时间:{}", key, message);return TimeUnit.SECONDS.convert(ttl, timeUnit);}/*** 缓存基本的对象,Integer、String、实体类等** @param key 缓存的键值* @param value 缓存的值*/public <T> void setCacheObject(final String key, final T value) {log.info("存入 Redis\t[{}]-[{}]", key, value);redisTemplate.opsForValue().set(key, value);}/*** 缓存基本的对象,Integer、String、实体类等** @param key 缓存的键值* @param value 缓存的值* @param timout 超时时间*/public <T> void setCacheObject(final String key, final T value, final long timout, final TimeUnit timeUnit) {log.info("存入 Redis\t[{}]-[{}],超时时间:[{} {}]", key, value, timout, timeUnit.name());redisTemplate.opsForValue().set(key, value, timout, timeUnit);}/*** 获取键值* @param key 键* @return 键对应的值,并封装成 Optional 对象* @param <T>*/public <T> Optional<T> getCacheObject(final String key) {T value = (T) redisTemplate.opsForValue().get(key);log.info("查询 Redis\t[{}]-[{}]", key, value);return Optional.ofNullable(value);}/*** 让指定 Redis 键值进行自减* @param key 键* @return 自减后的值*/public long decrementCacheNumber(final String key) {long number = redisTemplate.opsForValue().decrement(key);log.info("Redis key[{}] 自减后:{}", key, number);return number;}/*** 让指定 Redis 键值进行自增* @param key 键* @return 自增后的值*/public long incrementCacheNumber(final String key) {long number = redisTemplate.opsForValue().increment(key);log.info("Redis key[{}] 自增后:{}", key, number);return number;}/*** 初始化布隆过滤器* @param bloomFilterName*/public void initBloomFilter(final String bloomFilterName) {log.info("初始化布隆过滤器[{}]", bloomFilterName);redisTemplate.execute(new SessionCallback() {@Overridepublic Object execute(RedisOperations redisOperations) throws DataAccessException {redisOperations.multi();redisBloomFilter.init(bloomFilterName);return redisOperations.exec();}});}/*** 初始化布隆过滤器* @param bloomFilterName* @param timeout* @param timeUnit*/public void initBloomFilter(final String bloomFilterName, final long timeout, final TimeUnit timeUnit) {redisTemplate.execute(new SessionCallback() {@Overridepublic Object execute(RedisOperations redisOperations) throws DataAccessException {redisOperations.multi();redisBloomFilter.init(bloomFilterName);expire(bloomFilterName, timeout, timeUnit);return redisOperations.exec();}});}/*** 加入布隆过滤器* @param bloomFilterName 隆过滤器的名字* @param key key 键*/public <T> void addToBloomFilter(final String bloomFilterName, final T key) {log.info("加入布隆过滤器[{}]\tkey[{}]", bloomFilterName, key);redisTemplate.execute(new SessionCallback() {@Overridepublic Object execute(RedisOperations redisOperations) throws DataAccessException {redisOperations.multi();redisBloomFilter.add(bloomFilterName, key);return redisOperations.exec();}});}/*** 布隆过滤器是否存在该键值* @param bloomFilterName 布隆过滤器的名字* @param key 键* @return 键是否存在*/public <T> boolean containsInBloomFilter(final String bloomFilterName, final T key) {boolean flag = redisBloomFilter.contains(bloomFilterName, key);log.info("key[{}]\t是否存在于布隆过滤器[{}]:\t{}", key, bloomFilterName, flag);return flag;}/*** 缓存Map** @param key* @param data*/public <K, T> void setCacheMap(final String key, final Map<K, T> data) {if (Objects.nonNull(data)) {log.info("Map 存入 Redis\t[{}]-[{}]", key, data);redisTemplate.opsForHash().putAll(key, data);}}/*** 缓存Map** @param key* @param data*/public <K, T> void setCacheMap(final String key, final Map<K, T> data, long timeout, final TimeUnit timeUnit) {if (Objects.nonNull(data)) {Map<String, T> map = new HashMap<>();data.entrySet().stream().parallel().forEach(entry -> {map.put(entry.getKey().toString(), entry.getValue());});log.info("尝试存入 Redis\t[{}]-[{}] 超时时间:[{} {}]", key, map, timeout, timeUnit.name());redisTemplate.execute(new SessionCallback() {@Overridepublic Object execute(RedisOperations redisOperations) throws DataAccessException {redisOperations.multi();redisTemplate.opsForHash().putAll(key, map);expire(key, timeout, timeUnit);return redisOperations.exec();}});}}/*** 获得缓存的Map** @param key* @return*/public <K, T> Optional<Map<K, T>> getCacheMap(final String key) {Map<K, T> data = redisTemplate.opsForHash().entries(key);data = data.size() == 0 ? null: data;log.info("获取 Redis 中的 Map 缓存\t[{}]-[{}]", key, data);return Optional.ofNullable(data);}/*** 往Hash中存入数据** @param key Redis键* @param hashKey Hash键* @param value 值*/public <K, T> void setCacheMapValue(final String key, final K hashKey, final T value) {log.info("存入 Redis 的某个 Map\t[{}.{}]-[{}]", key, hashKey, value);redisTemplate.opsForHash().put(key, hashKey.toString(), value);}/*** 获取Hash中的数据** @param key Redis键* @param hashKey Hash键* @return Hash中的对象*/public <K, T> Optional<T> getCacheMapValue(final String key, final K hashKey) {T value = (T) redisTemplate.opsForHash().get(key, hashKey.toString());log.info("获取 Redis 中的 Map 的键值\t[{}.{}]-[{}]", key, hashKey, value);return Optional.ofNullable(value);}/*** 删除Hash中的数据** @param key* @param hashKey*/public <K> void delCacheMapValue(final String key, final K hashKey) {log.info("删除 Redis 中的 Map 的键值\tkey[{}.{}]", key, hashKey);redisTemplate.opsForHash().delete(key, hashKey.toString());}/*** 让指定 HashMap 的键值进行自减* @param key HashMap的名字* @param hashKey HashMap的一个键* @return 自减后的值*/public <K> long decrementCacheMapNumber(final String key, final K hashKey) {long number = redisTemplate.opsForHash().increment(key, hashKey.toString(), -1);log.info("Redis key[{}.{}] 自减后:{}", key, hashKey, number);return number;}/*** 让指定 HashMap 的键值进行自增* @param key HashMap的名字* @param hashKey HashMap的一个键* @return 自增后的值*/public <K> long incrementCacheMapNumber(final String key, final K hashKey) {long number = redisTemplate.opsForHash().increment(key, hashKey.toString(), +1);log.info("Redis key[{}.{}] 自增后:{}", key, hashKey, number);return number;}/*** 删除单个对象* @param key*/public boolean deleteObject(final String key) {log.info("删除 Redis 的键值\tkey[{}]", key);return redisTemplate.delete(key);}}
5. 查询Redis与Redis设置缓存的技巧
伪代码:
redisCache.getCacheObject(redisKey).orElseGet(() -> {/* balabala ....*/// 可能查询有误,所以这里也可能没法获取到data(为null),也就可能没必要设置缓存redisCache.setCacheObject(redisKey, data, ttl, unit); /* balabala ....*/return data;}));
现实示例:
相关文章:
Redis 工具类 与 Redis 布隆过滤器
Redis 工具类 1. 核心依赖 <!--redis--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency><groupId>com.google.guava…...
自定义el-upload 上传文件
前言 最近在做一个文件上传的功能,后端接口写好了、发现前端上传文件的页面不会写……(我很笨的)然后我就找啊找发现element有个组件是<el-upload/>能直接上传文件。我就想直接用拿来改改改成自己想要的,可是就是这样我花了…...
LeetCode69. x 的平方根(C++)
LeetCode69. x 的平方根 题目链接代码 题目链接 https://leetcode.cn/problems/sqrtx/description/ 代码 class Solution { public:int mySqrt(int x) {int right x, left 0, ans -1;while(left < right){long long mid left (right - left) / 2;if(mid * mid <…...
[c++] 单例模式 + cyberrt TimingWheel 单例分析
单例模式要求一个类在一个进程中只能创建一个对象。比如 cyberrt 中的 TimingWheel 类就是单例模式,这个类管理着一个进程内的所有定时器,只需要一个对象就可以。 单例模式的实现有两种方式,懒汉式和饿汉式。懒汉式,当第一次使用…...
如何在cmd里面创建一个vue项目
在命令提示符(CMD)中创建一个Vue项目,你需要先确保你已经全局安装了Vue CLI(Vue的命令行工具)。如果你还没有安装Vue CLI,可以通过以下命令进行安装: bash复制代码 npm install -g vue/cli # O…...
Day2 JS基础
2.1 运算符 赋值运算符 一元运算符 -- <script>let h20let kh hconsole.log(h) //22console.log(k) //42let i1console.log(i i i) //7 // 递增运算符:var a8aconsole.log(a) //9 var num10var bnumconsole.log(b) //10</script> 比较运…...
mybatis----有用配置知识归纳(狂神说学习总结)
1.mybatis介绍 MyBatis 是一款优秀的持久层框架MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 实体类映射成数据库中的记录 官网 Mybatis中文官方文档 : https…...
【TCP/IP】组播
一、组播介绍 组播(Multicast)是网络技术中数据传输的一种方法,它允许将数据包同时发送给一组指定的目标,而不是单个的目标(单播 Unicast)或所有可能的目标(广播 Broadcast)。组播传…...
java 内存模型
程序计数器 线程私有主要字节码解释器通过读取程序计数器来选取下一条需要执行的指令,比如分支,循环,跳转和异常处理如果执行的是java 方法,那么程序计数器记录的时候虚拟机字节码指令的地址,如果执行的是native 方法…...
Linux——缓冲区封装系统文件操作
📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、FILE二、封装系统接口实现文件操作1、text.c2、mystdio.c3、mystdio.h 一、FILE 因为IO相…...
深度学习系列59:文字识别
1. 简单文本: 使用google加的tesseract,效果不错。 首先安装tesseract,在mac直接brew install即可。 python调用代码: import pytesseract from PIL import Image img Image.open(1.png) pytesseract.image_to_string(img, lan…...
学习JAVA的第七天(基础)
目录 static 静态变量 静态方法 工具类: static的注意事项 继承 继承的好处 继承的特点 方法的重写 书写格式 override重写注解 方法重写的要求 this关键字 super关键字 static static表示静态,是Java中的一个修饰符,可以修饰成…...
GoLand 相关
goland 下载依赖 go mod tidy:保持依赖整洁 go mod tidy 命令的作用是清理未使用的依赖,并更新 go.mod 以及 go.sum 文件。 go mod tidy 和 go mod vendor 两个命令是维护项目依赖不可或缺的工具。go mod tidy 确保了项目的 go.mod 文件精简且准确&…...
顶顶通呼叫中心中间件-如何使处于机器人话术中的通话手动转接到坐席分机上
文章目录 前言联系我们实现步骤freeswitch命令转接api接口转接 前言 本文讲解呼叫中心中间件如何手动转接通话。 场景:利用自动外呼进入机器人,在通话过程中,转接到坐席分机上。 联系我们 有意向了解呼叫中心中间件的用户,可以点…...
RabbitMQ开启MQTT协议支持
1)RabbitMQ启用MQTT插件 rootmq:/# rabbitmq-plugins enable rabbitmq_mqtt Enabling plugins on node rabbitmq: rabbitmq_mqtt The following plugins have been configured:rabbitmq_managementrabbitmq_management_agentrabbitmq_mqttrabbitmq_web_dispatch Ap…...
Orange3数据预处理(列选择组件)数据角色及类型描述
在Orange3的文件组件中,datetime、categorical、numeric以及text代表不同种类的数据类型,具体如下: datetime:代表日期和时间类型的数据。通常用于时间序列分析、生存分析和其他需要考虑时间因素的机器学习任务中。例如࿰…...
c sharp资料
资料 c#菜鸟教程 Xml XmlNode 类 XPath或运算 SelectNodes的使用 基础 string.Format 复合格式设置标准数字格式字符串...
《低功耗方法学》翻译——第十四章:电源切换网络设计
第十四章:电源切换网络设计 功率门控是在待机或休眠模式下降低漏电功率最有效的方法,但这种方法存在诸如休眠晶体管占用的硅面积、永久和虚拟电源网络的布线资源以及复杂的功率门控设计和实现过程等开销,影响设计风险和进度。 除了开销外&a…...
如何使用Axure RP制作web页面并实现无公网ip远程访问——“cpolar内网穿透”
文章目录 前言1.在AxureRP中生成HTML文件2.配置IIS服务3.添加防火墙安全策略4.使用cpolar内网穿透实现公网访问4.1 登录cpolar web ui管理界面4.2 启动website隧道4.3 获取公网URL地址4.4. 公网远程访问内网web站点4.5 配置固定二级子域名公网访问内网web站点4.5.1创建一条固定…...
vue2实现无感刷新token
🎬 江城开朗的豌豆:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 📝 个人网站 :《 江城开朗的豌豆🫛 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 📘 引言: Ǵ…...
每日学习-2月18日
知识点:二叉树 中序遍历算法: void InOrderTraverse(BiTree T) { if(TNULL) return; InOrderTraverse(T->lchild); printf("%c",T->data); InOrderTraverse(T->rchild); } 算法过程: (1)调用InOrderTraverse(T)&#…...
AI 使人机交互发生根本性转变 AI芯片主战场,变了
语言将主导AI交互界面,同时AI应用正逐步适应人类 AI正创造人为中心和基于代理的未来。 这是 OpenAI 首位投资人 Vinod Khosla 关于 AI 交互与革命的最新洞察。Khosla 对常见术语“AI 硬件”和“小工具”表示怀疑,他主张从一个新的视角来看待这些设备&a…...
容器库(12)-std::unordered_multiset
unordered_multiset是以key为元素无序的关联容器,搜索、移除和插入操作是平均常数的时间复杂度。unordered_multiset在内部没有按任何顺序排列,而是放在桶当中的,放进哪个桶是通过计算key的hash值来决定的。和unordered_set不同的是ÿ…...
Mysql学习之事务日志undolog深入剖析
Undo log redo log 是事务持久性的保证,undo log是事务原子性的保证。在事务中更新数据的前置操作其实是要先写入一个undo log。 如何理解undo 日志? 事务需要保证原子性,也就是事务中的操作要么全部完成,要么什么也不做。但有时…...
springboot整合druid及可能遇到的问题
第一步,导入druid的maven依赖 在这里,我们选择导入druid-spring-boot-starter,使用配置文件的形式进行配置(不需要再编写配置类) <dependency><groupId>com.alibaba</groupId><artifactId>dr…...
c++文件的打开、读写和关闭。缓冲区的使用和控制。
在C中,文件的打开、读写和关闭通常使用标准库中的文件流对象(如std::ifstream用于输入文件,std::ofstream用于输出文件)来完成。这些对象封装了与操作系统交互的底层细节,使得文件操作更为简单和安全。 以下是文件打开…...
网络层的DDoS攻击与应用层的DDoS攻击之间的区别
DDoS攻击(即“分布是拒绝服务攻击”),是基于DoS的特殊形式的拒绝服务攻击,是一种分布式、协作的大规模攻击方式,主要瞄准一些企业或政府部门的网站发起攻击。根据攻击原理和方式的区别,可以把DDoS攻击分为两…...
Windows系统安全策略设置之本地NTLM重放提权
经安全部门研究分析,近期利用NTLM重放机制入侵Windows 系统事件增多,入侵者主要通过Potato程序攻击拥有SYSTEM权限的端口伪造网络身份认证过程,利用NTLM重放机制骗取SYSTEM身份令牌,最终取得系统权限,该安全风险微软并…...
AI云增强升级!还原生动人像,拍出质感照片
近期不少细心用户发现,在用HUAWEI Mate 60 Pro手机拍照后,使用相册中的AI云增强功能,照片变得更加细腻有质感。这是因为AI云增强升级并更新支持了人像模式拍摄的照片,高清自然的人像细节还原和单反级别的光学景深效果,…...
PHP WebSocket:技术解析与实用指南
本文旨在帮助初学者掌握在PHP中使用WebSocket的关键概念和技术。我们将深入讨论从建立连接、绑定到监听等各方面的操作,并提供易于理解和实践的指导。 一、socket协议的简介 WebSocket是什么,有什么优点 WebSocket是一个持久化的协议,这是…...
保定网络公司建设网站/电脑优化大师有用吗
首先写好一个列表写好的样式是这样滴操作来了在computed里面定义了一个search函数 使用filter过滤接下来在method 里面写一个sousuo1函数 进行一个判断 如果搜索这个输入框框里是空 就是展示原数据 如果这个不为空 就会展示搜索到的数据最后 很重要把list改为sousuo1()这个函数…...
网站怎么做抽奖/上海seo招聘
要成为一个优秀的嵌入式工程师,你需要具备以下技能和素质: 熟练掌握计算机硬件知识,包括微处理器,存储器,输入/输出设备等。 精通嵌入式操作系统,包括实时系统和嵌入式 Linux 等。 熟悉嵌入式编程语言,如 C…...
wordpress标志/全面的seo网站优化排名
6、到这里我们就可以打开Win7本地连接属性了,在里边即可更高本地连接IP地址了,如下图所示,我们切换到网络一栏,然后选中“ Internet 协议版本4 ”,然后点击下边的属性,如下图所示1、2、3步骤:7…...
还有哪些网站可以做淘宝活动吗/深圳网站设计公司
使用RMAN备份与恢复数据库(2)——参数文件的备份与恢复 Oracle有两类参数文件: (1)pfile:文本格式的参数文件,文件名通常为init.ora; (2)spfile:…...
dede如何制作手机网站/seo优化上海牛巨微
打开你的Mac电脑是不是都会有很多应用程序和服务会在后台自动启动?有的是我们需要的,但是有的不需要,那么开机启动,会耽搁你的开机时间,今天macz将为您介绍在Mac上添加,删除和延迟启动项的方法。 但是过多使用它们会增加设备的启动时间并降低其性能。这就是为什么必须在M…...
武汉 网站 合作伙伴/爱站网ip反域名查询
日常使用PHP开发较多,但是有些地方PHP的语言的瓶颈就显露出来了,例如,同样是抓取一个网站的内容,使用PHP需要较为复杂的正则匹配,效率较为低下。python具有丰富的类库,拿过来直接可以使用,功能强…...