Linux操作系统中Redis
1、什么是Redis
Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
可以理解成一个大容量的map。
2、Redis的作用
可以做为数据库存储数据,也可以用来做缓存、计数器、分布式锁等。实际工作中很少用它做数据库。
3、Redis常用的五种基本类型【必问】
string:字符串数据类型
hash:类似于对象,map的形式
list:表示一种线性数据结构,队列或栈
set:无序不可重复集合
zset:有序不可重复集合
另外还有三种数据类型,都不是很常用。Geospatial、Bitmap、Hyperloglog
redis可以操作位(bit),但是工作中几乎不用。
4、安装redis
基于docker的安装
4.1、查询镜像文件【省略】
#可以不操作: docker search redis
4.2、拉取镜像文件
docker pull redis:6.2.6
4.3、启动redis并设置密码
docker run -d --name redis-6379 -p 6379:6379 redis:6.2.6 --requirepass 123456
requirepass:设置密码
【工作时:】启动redis注意事项:
-
密码一定要设置,复杂一点
-
端口映射,redis一定不能用默认端口,用默认端口一定会被攻击
4.3.1、修改redis密码【可以不修改】
# 1/进入redis容器 docker exec -it redis-6379 /bin/bash # 2/找到redis-cli可执行文件 cd /usr/local/bin # 3/执行redis-cli redis-cli # 4/查看密码 config get requirepass # 5/授权 auth 密码 # 6/修改密码 config set requirepass 新密码
第一步骤:进入redis容器
第二步骤:找到redis-cli可执行文件
第三步骤:执行redis-cli
第四步骤:查看密码(显示没有授权)
第五步骤:授权
第六步骤:修改密码(最好还是使用123456,后面整合的时候,容易忘记。)
第七步骤:退出容器
4.3.2、删除密码【坚决不推荐】
config set requirepass ''
5、SpringBoot整合
1、添加maven依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.jsoft</groupId><artifactId>demo-redis</artifactId><version>0.0.1-SNAPSHOT</version>
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.13</version></parent>
<properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.6.13</spring-boot.version><jwt.version>0.7.0</jwt.version><fastjson.version>1.2.60</fastjson.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>compile</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--json--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version><scope>compile</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency></dependencies>
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><classifier>exec</classifier></configuration></plugin></plugins></build>
</project>
2、添加redis配置
spring: redis:host: 192.168.2.102port: 6379password: 123456
3、添加redisconfig
package com.jr.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
/*** 配置 RedisTemplate<String, Object>* 设置了键和值的序列化方式,键用字符串序列化,值用JSON序列化** @return RedisTemplate*/@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {GenericJackson2JsonRedisSerializer valueSerializer = new GenericJackson2JsonRedisSerializer();StringRedisSerializer keySerialize = new StringRedisSerializer();RedisTemplate<String, Object> result = new RedisTemplate<>();result.setConnectionFactory(redisConnectionFactory);result.setKeySerializer(keySerialize);result.setValueSerializer(valueSerializer);result.setHashKeySerializer(keySerialize);result.setHashValueSerializer(valueSerializer);return result;}
}
4、添加SpringBoot启动类:
@SpringBootApplication
public class SpringBootMain {public static void main(String[] args) {SpringApplication.run(SpringBootMain.class);}+
}
5、常用方法介绍【必问,记住3-5方法】
1.redisTemplate
redisTemplate.hasKey(key); //判断是否有key所对应的值,有则返回true,没有则返回false redisTemplate.opsForValue().get(key); //有则取出key值所对应的值 redisTemplate.delete(key); //删除单个key值 redisTemplate.delete(keys); //其中keys:Collection<K> keys redisTemplate.dump(key); //将当前传入的key值序列化为byte[]类型 redisTemplate.expire(key, timeout, unit); //设置过期时间 redisTemplate.expireAt(key, date); //设置过期时间 redisTemplate.keys(pattern); //查找匹配的key值,返回一个Set集合类型 redisTemplate.rename(oldKey, newKey); //返回传入key所存储的值的类型 redisTemplate.renameIfAbsent(oldKey, newKey); //如果旧值存在时,将旧值改为新值 redisTemplate.randomKey(); //从redis中随机取出一个key redisTemplate.getExpire(key); //返回当前key所对应的剩余过期时间 redisTemplate.getExpire(key, unit); //返回剩余过期时间并且指定时间单位 redisTemplate.persist(key); //将key持久化保存 redisTemplate.move(key, dbIndex); //将当前数据库的key移动到指定redis中数据库当中
【测试代码】
@Slf4j
@SpringBootTest(classes = DemoHelloworldApplication.class)
@SuppressWarnings("all")
public class RedisTest {
private static final String KEY = "test:commonKey";
@Autowiredprivate RedisTemplate<String, Object> redisTemplate;
@Testpublic void testCommon() {testCommon(KEY);}
public void testCommon(String key) {boolean hasKey = redisTemplate.hasKey(key); //hasKey(key);log.info("hasKey {}", hasKey);boolean delete = redisTemplate.delete(key); //delete(key);log.info("delete {}", delete);}
public void delete(String key) {boolean delete = redisTemplate.delete(key);}
}
2.ValueOperations=>String
ValueOperations opsForValue = redisTemplate.opsForValue(); opsForValue.set(key, value); //设置当前的key以及value值 opsForValue.set(key, value, offset);//用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始 opsForValue.set(key, value, timeout, unit); //设置当前的key以及value值并且设置过期时间 opsForValue.setBit(key, offset, value); //将二进制第offset位值变为value opsForValue.setIfAbsent(key, value);//重新设置key对应的值,如果存在返回false,否则返回true opsForValue.get(key, start, end); //返回key中字符串的子字符 opsForValue.getAndSet(key, value); //将旧的key设置为value,并且返回旧的key opsForValue.multiGet(keys); //批量获取值 opsForValue.size(key); //获取字符串的长度 opsForValue.append(key, value); //在原有的值基础上新增字符串到末尾 opsForValue.increment(key,double increment);//以增量的方式将double值存储在变量中 opsForValue.increment(key,long increment); //通过increment(K key, long delta)方法以增量方式存储long值(正值则自增,负值则自减)Map valueMap = new HashMap(); valueMap.put("valueMap1","map1"); valueMap.put("valueMap2","map2"); valueMap.put("valueMap3","map3"); opsForValue.multiSetIfAbsent(valueMap); //如果对应的map集合名称不存在,则添加否则不做修改 opsForValue.multiSet(valueMap); //设置map集合到redis
【测试代码】
@Slf4j
@SpringBootTest(classes = DemoHelloworldApplication.class)
@SuppressWarnings("all")
public class RedisTest {
private static final String KEY = "test:commonKey";
@Autowiredprivate RedisTemplate<String, Object> redisTemplate;
/*** - string:字符串数据类型*/@Testpublic void testString() {String key = "test:string";String key2 = "test:increment";String key3 = "test:object";delete(key);delete(key2);delete(key3);redisTemplate.opsForValue().set(key, "zhangsan"); // set(key, "zhangsan");Object value = redisTemplate.opsForValue().get(key); // get(key);log.info("value {}", value);redisTemplate.opsForValue().set(key, "lisi");value = redisTemplate.opsForValue().get(key);log.info("value {}", value);testCommon(key);boolean hasKey = redisTemplate.hasKey(key);log.info("hasKey {}", hasKey);redisTemplate.opsForValue().increment(key2, 10);// increment(key2, 10);计数器value = redisTemplate.opsForValue().get(key2);log.info("value {}", value);redisTemplate.opsForValue().increment(key2); // increment(key2); 涨1;increment(key2,10);涨10value = redisTemplate.opsForValue().get(key2);log.info("value {}", value);User user = new User();user.setName("zhangsan");user.setPassword("123456");redisTemplate.opsForValue().set(key3, user);value = redisTemplate.opsForValue().get(key3);log.info("value {}", value);}
}
3.HashOperations=>Hash
HashOperations opsForHash = redisTemplate.opsForHash(); opsForHash.get(key, field); //获取变量中的指定map键是否有值,如果存在该map键则获取值,没有则返回null opsForHash.entries(key); //获取变量中的键值对 opsForHash.put(key, hashKey, value); //新增hashMap值 opsForHash.putAll(key, maps); //以map集合的形式添加键值对 opsForHash.putIfAbsent(key, hashKey, value); //仅当hashKey不存在时才设置 opsForHash.delete(key, fields); //删除一个或者多个hash表字段 opsForHash.hasKey(key, field); //查看hash表中指定字段是否存在 opsForHash.increment(key, field, long increment); //给哈希表key中的指定字段的整数值加上增量increment opsForHash.increment(key, field, double increment); //给哈希表key中的指定字段的整数值加上增量increment opsForHash.keys(key); //获取所有hash表中字段 opsForHash.values(key); //获取hash表中存在的所有的值 opsForHash.scan(key, options); //匹配获取键值对,ScanOptions.NONE为获取全部键对
【测试代码】
@Slf4j
@SpringBootTest(classes = DemoHelloworldApplication.class)
@SuppressWarnings("all")
public class RedisTest {
private static final String KEY = "test:commonKey";
@Autowiredprivate RedisTemplate<String, Object> redisTemplate;
/*** - hash:类似于对象,map的形式*/@Testpublic void testHash() {String key = "test:hash";redisTemplate.opsForHash().put(key, "name", "zhangsan");redisTemplate.opsForHash().put(key, "age", 12);Object name = redisTemplate.opsForHash().get(key, "name");Object age = redisTemplate.opsForHash().get(key, "age");log.info("name {}", name);log.info("age {}", age);}
}
4.ListOperations=>List
ListOperations opsForList = redisTemplate.opsForList(); opsForList.index(key, index); //通过索引获取列表中的元素 opsForList.range(key, start, end); //获取列表指定范围内的元素(start开始位置, 0是开始位置,end 结束位置, -1返回所有) opsForList.leftPush(key, value); //存储在list的头部,即添加一个就把它放在最前面的索引处 opsForList.leftPush(key, pivot, value); //如果pivot处值存在则在pivot前面添加 opsForList.leftPushAll(key, value); //把多个值存入List中(value可以是多个值,也可以是一个Collection value) opsForList.leftPushIfPresent(key, value); //List存在的时候再加入 opsForList.rightPush(key, value); //按照先进先出的顺序来添加(value可以是多个值,或者是Collection var2) opsForList.rightPushAll(key, value); //在pivot元素的右边添加值 opsForList.set(key, index, value); //设置指定索引处元素的值 opsForList.trim(key, start, end); //将List列表进行剪裁 opsForList.size(key); //获取当前key的List列表长度//移除并获取列表中第一个元素(如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止) opsForList.leftPop(key); opsForList.leftPop(key, timeout, unit); //移除并获取列表最后一个元素 opsForList.rightPop(key); opsForList.rightPop(key, timeout, unit); //从一个队列的右边弹出一个元素并将这个元素放入另一个指定队列的最左边 opsForList.rightPopAndLeftPush(sourceKey, destinationKey); opsForList.rightPopAndLeftPush(sourceKey, destinationKey, timeout, unit);//删除集合中值等于value的元素(index=0, 删除所有值等于value的元素; index>0, 从头部开始删除第一个值等于value的元素; index<0, 从尾部开始删除第一个值等于value的元素) opsForList.remove(key, index, value);
【测试代码】
@Slf4j
@SpringBootTest(classes = DemoHelloworldApplication.class)
@SuppressWarnings("all")
public class RedisTest {
private static final String KEY = "test:commonKey";
@Autowiredprivate RedisTemplate<String, Object> redisTemplate;
/*** - list:表示一种线性数据结构,队列或栈*/@Testpublic void testList() {String key = "test:list";log.info("----------------------- {}", "模拟队列");/*模拟队列*/for (int i = 0; i < 5; i++) {redisTemplate.opsForList().leftPush(key, i);}long listSize = redisTemplate.opsForList().size(key);log.info("listSize {}", listSize);for (int i = 0; i < listSize; i++) {log.info("test:list {}", redisTemplate.opsForList().rightPop(key));}listSize = redisTemplate.opsForList().size(key);log.info("listSize {}", listSize);log.info("----------------------- {}", "模拟栈");/*模拟栈*/for (int i = 0; i < 5; i++) {redisTemplate.opsForList().leftPush(key, i);}listSize = redisTemplate.opsForList().size(key);log.info("listSize {}", listSize);for (int i = 0; i < listSize; i++) {log.info("test:list {}", redisTemplate.opsForList().leftPop(key));}listSize = redisTemplate.opsForList().size(key);log.info("listSize {}", listSize);}
}
5.SetOperations=>Set
SetOperations opsForSet = redisTemplate.opsForSet(); opsForSet.add(key, values); //添加元素 opsForSet.remove(key, values); //移除元素(单个值、多个值) opsForSet.pop(key); //删除并且返回一个随机的元素 opsForSet.size(key); //获取集合的大小 opsForSet.isMember(key, value); //判断集合是否包含value opsForSet.intersect(key, otherKey); //获取两个集合的交集(key对应的无序集合与otherKey对应的无序集合求交集) opsForSet.intersect(key, otherKeys);//获取多个集合的交集(Collection var2) opsForSet.intersectAndStore(key, otherKey, destKey); //key集合与otherKey集合的交集存储到destKey集合中(其中otherKey可以为单个值或者集合) opsForSet.intersectAndStore(key, otherKeys, destKey); //key集合与多个集合的交集存储到destKey无序集合中 opsForSet.union(key, otherKeys); //获取两个或者多个集合的并集(otherKeys可以为单个值或者是集合) opsForSet.unionAndStore(key, otherKey, destKey); //key集合与otherKey集合的并集存储到destKey中(otherKeys可以为单个值或者是集合) opsForSet.difference(key, otherKeys); //获取两个或者多个集合的差集(otherKeys可以为单个值或者是集合) opsForSet.differenceAndStore(key, otherKey, destKey); //差集存储到destKey中(otherKeys可以为单个值或者集合) opsForSet.randomMember(key); //随机获取集合中的一个元素 opsForSet.members(key); //获取集合中的所有元素 opsForSet.randomMembers(key, count); //随机获取集合中count个元素 opsForSet.distinctRandomMembers(key, count); //获取多个key无序集合中的元素(去重),count表示个数 opsForSet.scan(key, options); //遍历set类似于Interator(ScanOptions.NONE为显示所有的)
【测试代码】
@Slf4j
@SpringBootTest(classes = DemoHelloworldApplication.class)
@SuppressWarnings("all")
public class RedisTest {
private static final String KEY = "test:commonKey";
@Autowiredprivate RedisTemplate<String, Object> redisTemplate;
/*** - set:无序不可重复集合*/@Testpublic void testSet() {String key = "test:set";redisTemplate.opsForSet().add(key, "zhangsan", "lisi", "wangwu", 12, 22, 32, "wangwu", 12, "12");long listSize = redisTemplate.opsForSet().size(key);log.info("listSize {}", listSize);for (int i = 0; i < listSize; i++) {log.info("test:set {}", redisTemplate.opsForSet().pop(key));}listSize = redisTemplate.opsForSet().size(key);log.info("listSize {}", listSize);}
}
6.ZSetOperations=>zSet
ZSetOperations提供了一系列方法对有序集合进行操作 ZSetOperations opsForZSet = redisTemplate.opsForZSet(); opsForZSet.add(key, value, score); //添加元素(有序集合是按照元素的score值由小到大进行排列) opsForZSet.remove(key, values); //删除对应的value,value可以为多个值 opsForZSet.incrementScore(key, value, delta); //增加元素的score值,并返回增加后的值 opsForZSet.rank(key, value); //返回元素在集合的排名,有序集合是按照元素的score值由小到大排列 opsForZSet.reverseRank(key, value); //返回元素在集合的排名,按元素的score值由大到小排列 opsForZSet.reverseRangeWithScores(key, start,end); //获取集合中给定区间的元素(start 开始位置,end 结束位置, -1查询所有) opsForZSet.reverseRangeByScore(key, min, max); //按照Score值查询集合中的元素,结果从小到大排序 opsForZSet.reverseRangeByScoreWithScores(key, min, max); //返回值为:Set<ZSetOperations.TypedTuple<V>> opsForZSet.count(key, min, max); //根据score值获取集合元素数量 opsForZSet.size(key); //获取集合的大小 opsForZSet.zCard(key); //获取集合的大小 opsForZSet.score(key, value); //获取集合中key、value元素对应的score值 opsForZSet.removeRange(key, start, end); //移除指定索引位置处的成员 opsForZSet.removeRangeByScore(key, min, max); //移除指定score范围的集合成员 opsForZSet.unionAndStore(key, otherKey, destKey);//获取key和otherKey的并集并存储在destKey中(其中otherKeys可以为单个字符串或者字符串集合) opsForZSet.intersectAndStore(key, otherKey, destKey); //获取key和otherKey的交集并存储在destKey中(其中otherKeys可以为单个字符串或者字符串集合)
【测试代码】
@Slf4j
@SpringBootTest(classes = DemoHelloworldApplication.class)
@SuppressWarnings("all")
public class RedisTest {
private static final String KEY = "test:commonKey";
@Autowiredprivate RedisTemplate<String, Object> redisTemplate;
/*** - zset:有序不可重复集合*/@Testpublic void testZset() {String key = "test:zset";redisTemplate.opsForZSet().add(key, "zhangsan", 12);redisTemplate.opsForZSet().add(key, "lisi", 22);redisTemplate.opsForZSet().add(key, "wangwu", 32);redisTemplate.opsForZSet().add(key, "wangwu1", 121);redisTemplate.opsForZSet().add(key, "wangwu2", 122);redisTemplate.opsForZSet().add(key, "wangwu3", 123);redisTemplate.opsForZSet().add(key, "wangwu4", 124);redisTemplate.opsForZSet().add(key, "wangwu5", 125);redisTemplate.opsForZSet().add(key, "wangwu6", 126);Long zCard = redisTemplate.opsForZSet().zCard(key);//long listSize = redisTemplate.opsForZSet().size(key);log.info("zCard {}", zCard);log.info("listSize {}", listSize);
// for (int i = 0; i < listSize; i++) {
// log.info("test:set {}", redisTemplate.opsForZSet().popMax(key));
// }listSize = redisTemplate.opsForZSet().size(key);log.info("listSize {}", listSize);log.info("----------------------- {}", "华丽的分割线");Set<Object> range = redisTemplate.opsForZSet().range(key, 1, 3);for (Object o : range) {log.info("range {}", o);}listSize = redisTemplate.opsForZSet().size(key);log.info("listSize {}", listSize);}
}
6、面试题:
1、缓存穿透
一、概念
缓存穿透:缓存和数据库中都没有的数据,可用户还是源源不断的发起请求,导致每次请求都会到数据库,从而压垮数据库。
如下图红色的流程:
比如客户查询一个根本不存在的东西,首先从Redis中查不到,然后会去数据库中查询,数据库中也查询不到,那么就不会将数据放入到缓存中,后面如果还有类似源源不断的请求,最后都会压到数据库来处理,从而给数据库造成巨大的压力。
二、解决办法
①、业务层校验
用户发过来的请求,根据请求参数进行校验,对于明显错误的参数,直接拦截返回。
比如,请求参数为主键自增id,那么对于请求小于0的id参数,明显不符合,可以直接返回错误请求。
②、不存在数据设置短过期时间
对于某个查询为空的数据,可以将这个空结果进行Redis缓存,但是设置很短的过期时间,比如30s,可以根据实际业务设定。注意一定不要影响正常业务。
③、布隆过滤器
关于布隆过滤器,后面会详细介绍。布隆过滤器是一种数据结构,利用极小的内存,可以判断大量的数据“一定不存在或者可能存在”。
对于缓存击穿,我们可以将查询的数据条件都哈希到一个足够大的布隆过滤器中,用户发送的请求会先被布隆过滤器拦截,一定不存在的数据就直接拦截返回了,从而避免下一步对数据库的压力。
2、缓存击穿
一、概念
缓存击穿:Redis中一个热点key在失效的同时,大量的请求过来,从而会全部到达数据库,压垮数据库。
这里要注意的是这是某一个热点key过期失效,和后面介绍缓存雪崩是有区别的。比如淘宝双十一,对于某个特价热门的商品信息,缓存在Redis中,刚好0点,这个商品信息在Redis中过期查不到了,这时候大量的用户又同时正好访问这个商品,就会造成大量的请求同时到达数据库。
二、解决办法
①、设置热点数据永不过期
对于某个需要频繁获取的信息,缓存在Redis中,并设置其永不过期。当然这种方式比较粗暴,对于某些业务场景是不适合的。
②、定时更新
比如这个热点数据的过期时间是1h,那么每到59minutes时,通过定时任务去更新这个热点key,并重新设置其过期时间。
③、互斥锁
这是解决缓存穿透比较常用的方法。
互斥锁简单来说就是在Redis中根据key获得的value值为空时,先锁上,然后从数据库加载,加载完毕,释放锁。若其他线程也在请求该key时,发现获取锁失败,则睡眠一段时间(比如100ms)后重试。
3、缓存雪崩
一、概念
缓存雪崩:Redis中缓存的数据大面积同时失效,或者Redis宕机,从而会导致大量请求直接到数据库,压垮数据库。
对于一个业务系统,如果Redis宕机或大面积的key同时过期,会导致大量请求同时打到数据库,这是灾难性的问题。
二、解决办法
①、设置有效期均匀分布
避免缓存设置相近的有效期,我们可以在设置有效期时增加随机值;
或者统一规划有效期,使得过期时间均匀分布。
②、数据预热
对于即将来临的大量请求,我们可以提前走一遍系统,将数据提前缓存在Redis中,并设置不同的过期时间。
③、保证Redis服务高可用
前面我们介绍过Redis的哨兵模式和集群模式,为防止Redis集群单节点故障,可以通过这两种模式实现高可用。
相关文章:
Linux操作系统中Redis
1、什么是Redis Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSIC语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。 可以理解成一个大容量的map。…...
每日论文5—06TCAS2锁相环电流匹配的gain-boosting电荷泵
《Gain-Boosting Charge Pump for Current Matching in Phase-Locked Loop》 06TCAS2 本质上和cascode来增加输出电阻,从而减小电流变化的思路是一样的。这里用了放大器来增加输出电阻。具体做法如下图: 如图1(a),A3把Vb和Vx拉平࿰…...
接口隔离原则(学习笔记)
客户端不应该被迫依赖于它不使用的方法:一个类对另一个类的依赖应该建立在最小的接口上。 上面的设计我们发现他存在的问题,黑马品牌的安全门具有防盗,防水,防火的功能。现在如果我们还需要再创建一盒传智品牌的安全门,…...
基于ESP8266—AT指令连接阿里云+MQTT透传数据(1)
在阿里云创建MQTT产品的过程涉及几个关键步骤,主要包括注册阿里云账号、实名认证、开通MQTT服务实例、创建产品与设备等。以下是详细的步骤说明: 一、准备工作 访问阿里云官网,点击注册按钮,填写相关信息(如账号、密码、手机号等)完成注册。注册完成后,需要对账号进行实…...
强化学习-python案例
强化学习是一种机器学习方法,旨在通过与环境的交互来学习最优策略。它的核心概念是智能体(agent)在环境中采取动作,从而获得奖励或惩罚。智能体的目标是最大化长期奖励,通过试错的方式不断改进其决策策略。 在强化学习…...
Element UI教程:如何将Radio单选框的圆框改为方框
大家好,今天给大家带来一篇关于Element UI的使用技巧。在项目中,我们经常会用到Radio单选框组件,默认情况下,Radio单选框的样式是圆框。但有时候,为了满足设计需求,我们需要将圆框改为方框,如下…...
vue3结合 vue-router和keepalive实现路由跳转保持滚动位置不改变(超级简易清晰)
1.首先我们在路由跳转页面设置keepalive(Seeall是我想实现结果的页面) 2. 想实现结果的页面中如果不是全屏实现滚动而是有单独的标签实现滚动效果...
PostgreSQL 字段使用pglz压缩测试
PostgreSQL 字段使用pglz压缩测试 测试一: 创建测试表 yewu1.test1,并插入1000w行数据 创建测试表 yewu1.test2,使用 pglz压缩字段,并插入1000w行数据–创建测试表1,并插入1000w行数据 white# create table yewu1.t…...
基于大数据的学生体质健康信息系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...
【STM32】 TCP/IP通信协议(1)--LwIP介绍
一、前言 TCP/IP是干啥的?它跟SPI、IIC、CAN有什么区别?它如何实现stm32的通讯?如何去配置?为了搞懂这些问题,查询资料可解决如下疑问: 1.为什么要用以太网通信? 以太网(Ethernet) 是指遵守 IEEE 802.3 …...
828华为云征文|部署音乐流媒体服务器 mStream
828华为云征文|部署音乐流媒体服务器 mStream 一、Flexus云服务器X实例介绍二、Flexus云服务器X实例配置2.1 重置密码2.2 服务器连接2.3 安全组配置2.4 Docker 环境搭建 三、Flexus云服务器X实例部署 mStream3.1 mStream 介绍3.2 mStream 部署3.3 mStream 使用 四、…...
【动态规划-最长公共子序列(LCS)】力扣712. 两个字符串的最小ASCII删除和
给定两个字符串s1 和 s2,返回 使两个字符串相等所需删除字符的 ASCII 值的最小和 。 示例 1: 输入: s1 “sea”, s2 “eat” 输出: 231 解释: 在 “sea” 中删除 “s” 并将 “s” 的值(115)加入总和。 在 “eat” 中删除 “t” 并将 116 加入总和。 结束时&…...
override
override 是 C11 引入的一个关键字,override 的作用是在派生类中显式地声明某个函数是用于重写基类的虚函数。它不仅仅是一个语法标记,更重要的是提供了编译时的错误检查功能,确保程序员确实按照预期在派生类中重写了基类的函数。如果没有正确…...
万象奥科工业平板上线,邀您体验与众不同!
Vanxoak推出的全新品类——ARM工业平板电脑!该系列工业平板具有防护等级高、接口丰富、易开发等特点,专为工业HMI(人机界面)和工业控制领域设计。整机采用高性能工业级ARM处理器,适配全贴合电容触摸屏,可选…...
java将word转pdf
总结 建议使用aspose-words转pdf,poi的容易出问题还丑… poi的(多行的下边框就不对了) aspose-words的(基本和word一样) poi工具转换 <!-- 处理PDF --><dependency><groupId>fr.opensagres.xdocreport</groupId><artifactId>fr.opensagres…...
Golang | Leetcode Golang题解之第449题序列化和反序列化二叉搜索树
题目: 题解: type Codec struct{}func Constructor() (_ Codec) { return }func (Codec) serialize(root *TreeNode) string {arr : []string{}var postOrder func(*TreeNode)postOrder func(node *TreeNode) {if node nil {return}postOrder(node.Le…...
基于SpringBoot+Vue+MySQL的美食信息推荐系统
系统展示 用户前台界面 管理员后台界面 系统背景 在数字化时代,随着人们对美食文化的热爱与追求不断增长,美食信息推荐系统成为了连接食客与美食之间的重要桥梁。面对海量的美食信息,用户往往难以快速找到符合个人口味和需求的美食。因此&…...
spring boot jar 分离自动部署脚本
背景 远程部署时spring boot 包,比较大。可以采用依赖库和业务包分离的方式。提供一个脚本进行自动部署 maven 配置分离jar包 <build><finalName>${project.artifactId}</finalName><plugins><plugin><groupId>org.springfra…...
PGMP-03战略一致性
1.概要 program strategy alignment:战略一致性 2.详细...
华为OD机试真题---智能成绩表
题目描述 小明来到某学校当老师,需要将学生按考试总分或单科分数进行排名。输入包括学生人数、科目数量、科目名称、每个学生的姓名和对应科目的成绩,最后输入一个用作排名的科目名称。如果输入的排名科目不存在,则按总分进行排序。输出一行…...
828华为云征文 | 华为云Flexus云服务器X实例搭建企业内部VPN私有隧道,以实现安全远程办公
VPN虚拟专用网络适用于企业内部人员流动频繁和远程办公的情况,出差员工或在家办公的员工利用当地ISP就可以和企业的VPN网关建立私有的隧道连接。 通过拨入当地的ISP进入Internet再连接企业的VPN网关,在用户和VPN网关之间建立一个安全的“隧道”ÿ…...
Hadoop集群的高可用(HA):NameNode和resourcemanager高可用的搭建
文章目录 一、NameNode高可用的搭建1、免密配置2、三个节点都需要安装psmisc3、检查三个节点是否都安装jdk以及zk4、检查是否安装了hadoop集群5、修改hadoop-env.sh6、修改core-site.xml7、修改hdfs-site.xml8、检查workers 文件是否为三台服务9、分发给其他两个节点10、初始化…...
支付宝沙箱环境 支付
一 什么是沙箱: 沙箱环境是支付宝开放平台为开发者提供的安全低门槛的测试环境 支付宝正式和沙箱环境的区别 : AI: 从沙箱到正式环境: 当应用程序开发完成后,需要将应用程序从沙箱环境迁移到正式环境。 这通常涉及…...
获取unity中prefab的中文文本内容以及和prefab有关的问题
背景1:经常会在开发中遇到策划需要改某个界面,但是我们不知道那是什么界面,只看到一些关键字比如圣诞活动,那这样我就可以轻易找到这个预设了。另外还可以扩展就是收集项目中的所有中文文本然后归集到多语言表中,然后接…...
Web自动化中常用XPath定位方式
在进行Web自动化测试时,元素定位是一个至关重要的环节。XPath(XML Path Language)是一种用于在XML文档中定位节点的语言。在Web自动化中,XPath广泛应用于定位HTML元素。本文将详细介绍几种常用的XPath定位方式,包括绝对…...
Unity3D播放GIF图片使用Animation来制作动画
系列文章目录 unity工具 文章目录 系列文章目录👉前言👉一、下载GIF动图,用PS制作导出帧动画图片👉二、使用Animation制作动画👉三、脚本控制动画播放👉壁纸分享👉总结👉前言 unity播放gif图片,本身是不支持的,但是可以使用其他方法来实现, 1.有一种使用System…...
redo log 和 bin log 的两阶段提交
两阶段提交的过程 当事务提交后,有一个两阶段提交策略。 在开启两阶段提交时,会开启一个 XA 事务(宏观上的事务), Prepare 阶段:将 redo log 的状态设置为 prepare,然后将 事务XID 写入 redo…...
Go基础学习07-map注意事项;多协程对map的资源竞争;sync.Mutex避免竟态条件
文章目录 Go中map使用以及注意事项map使用时的并发安全问题 Go中map使用以及注意事项 Go语言中map使用简单示例: func main() {var mp map[string]int// mp : map[string]int{}val, ok : mp["one"]if ok {fmt.Println(val)} else {fmt.Println(val)}mp[…...
远程服务器安装anaconda并创建虚拟环境
1、承接上文新用户zrcs,在服务器的zrcs文件夹下直接下载anaconda(很慢): wget https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh 或者选择本地下载,清华大学开源软件镜像站:https:/…...
什么是IIC通信协议?
IIC(Inter-Integrated Circuit)通信协议,又称为I2C(Inter-Integrated Circuit 2)协议,是一种广泛使用的串行通信协议。它由飞利浦半导体公司(现NXP Semiconductors)开发,…...
濮阳做网站的公司有哪些/枸橼酸西地那非片功效效及作用
G - 一行盒子 你有一行盒子,从左到右依次编号为1, 2, 3,…, n。你可以执行四种指令: 1 X Y表示把盒子X移动到盒子Y左边(如果X已经在Y的左边则忽略此指令)。 2 X Y表示把盒子X移动到盒子Y右边(如果X已经在Y的右边则忽略…...
越南的网站建设/百度推广优化怎么做的
首先请大家看这么一个简单的小程序: #include <stdio.h>void main(){int i, b[10];for ( i 0; i < 10; i ) { b[i] 0; }} 请问这个程序是否有错?A.正常 B.越界 C.死循环 正确答案是C,相信选A或选B的朋友一定会很纳闷…...
漯河网做网站/互联网推广是什么
这是【综合类型第 5 篇】,如果觉得有用的话,欢迎关注专栏。 文章目录一:安装 Homebrew 失败问题描述二:安装 Homebrew 过程三:验证是否安装成功四:更新 Homebrew五:卸载 Homebrew一:…...
做名片赞机器人电脑网站是多少钱/百度指数app官方下载
相信玩过laravel框架的小伙伴们,都知道它路由的强大之处 今天我想给大家分析下这个 首先 要找到配置路由的位置 routes这个目录下,我们找到web.php文件 里面可以看到现成的一个路由 Route::get(/,function(){ return view(welcome); });//第一个是url路径,第二个是回调函数 当然…...
广西网站建设运营费用/万网官网首页
前言 从小就写字很挫,所以受够了被人鄙视的感觉,今天有个coder突然跟我说,你的代码怎么像小孩写的一样,顿时心情沮丧的极点。越来越发现一致的编程风格的重要性,于是把Google的C编程风格指南看了一遍, 这里…...
重庆企业网站推广流程/百度seo规则最新
l> 我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版,欢迎购买。点击进入详情 文章目录1.开发环境2.第三方库3.实现1.分析url格式2.分析图片格式3.保存图片到本地4.输入页数4.优化1.防止被封2.多线程下载3.便捷获取图片地址5.效果6.Gith…...