Redis面试题28道

1、什么是类加载器,类加载器有哪些?

1、什么是类加载器?

类加载器负责加载所有的类,其为所有被载入内存的类生成一个 java.lang.Class 实例对象。

2、类加载器有哪些?

JVM 有三种类加载器:

(1)启动类加载器

该类没有父加载器,用来加载 Java 的核心类,启动类加载器的实现依赖于底层操作系统,属于虚拟机实现的一部分,它并不继承自 java.lang.classLoader。

(2)扩展类加载器

它的父类为启动类加载器,扩展类加载器是纯 java 类,是 ClassLoader 类的子类,负责加载 JRE 的扩展目录。

(3)应用程序类加载器

它的父类为扩展类加载器,它从环境变量 classpath 或者系统属性 java.lang.path 所指定的目录中加载类,它是自定义的类加载器的父加载器。

2、说一下类加载的执行过程?

当程序主动使用某个类时,如果该类还未被加载到内存中,JVM 会通过加载、连接、初始化 3 个步骤对该类进行类加载。

1、加载

加载指的是将类的 class 文件读入到内存中,并为之创建一个 java.lang.Class 对象。

类的加载由类加载器完成,类加载器由 JVM 提供,开发者也可以通过继承 ClassLoader 基类来创建自己的类加载器。

通过使用不同的类加载器可以从不同来源加载类的二进制数据,通常有如下几种来源:

  1. 从本地文件系统加载
  2. 从 jar 包加载
  3. 通过网络加载
  4. 把一个 Java 源文件动态编译,并执行加载

2、连接

当类被加载之后,系统为之生成一个对应的 Class 对象,接着进入连接阶段,连接阶段负责将类的二进制数据合并到 JRE 中。

类连接又可分为三个阶段:

(1)验证

文件格式验证
元数据验证
字节码验证
符号引用验证

(2)准备

为类的静态变量分配内存,并设置默认初始值。

(3)解析

将类的二进制数据中的符号引用替换成直接引用。

3、初始化

为类的静态变量赋予初始值。

3、JVM 的类加载机制是什么?

JVM 类加载机制主要有三种:

1、全盘负责

类加载器加载某个 class 时,该 class 所依赖的和引用其它的 class 也由该类加载器载入。

2、双亲委派

先让父加载器加载该 class,父加载器无法加载时才考虑自己加载。

3、缓存机制

缓存机制保证所有加载过的 class 都会被缓存,当程序中需要某个 class 时,先从缓存区中搜索,如果不存在,才会读取该类对应的二进制数据,并将其转换成 class 对象,存入缓存区中。

这就是为什么修改了 class 后,必须重启 JVM,程序所做的修改才会生效的原因。

4、什么是双亲委派模型?

如果一个类收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器执行,如果父加载器还存在其父加载器,则进一步向上委托,依次递归,请求将最终到达顶层的启动类加载器,如果父类加载器可以完成父加载任务,就成功返回,如果父加载器无法完成加载任务,子加载器才会尝试自己去加载,这就是双亲委派模型。

双亲委派模式的优势:

  1. 避免重复加载;
  2. 考虑到安全因素,java 核心 api 中定义类型不会被随意替换,假设通过网络传递一个名为 java.lang.Integer 的类,通过双亲委派模式传递到启动加载器,而启动加载器在核心 Java API 中发现同名的类,发现该类已经被加载,就不会重新加载网络传递的 Integer 类,而直接返回已加载过的 Integer.class,这样可以防止核心 API 库被随意篡改。

5、怎么判断对象是否可以被回收?

1、引用计数算法

(1)判断对象的引用数量

通过判断对象的引用数量来决定对象是否可以被回收;
每个对象实例都有一个引用计数器,被引用 + 1,完成引用 - 1;
任何引用计数为 0 的对象实例可以被当做垃圾回收;

(2)优缺点

优点:执行效率高,程序受影响较小;
缺点:无法检测出循环引用的情况,导致内存泄漏;

2、可达性分析算法

通过判断对象的引用链是否可达来决定对象是否可以被回收。

如果程序无法再引用该对象,那么这个对象肯定可以被回收,这个状态称为不可达。

那么不可达状态如何判断呢?

答案是 GC roots,也就是根对象,如果一个对象无法到达根对象的路径,或者说从根对象无法引用到该对象,该对象就是不可达的。

以下三种对象在 JVM 中被称为 GC roots,来判断一个对象是否可以被回收。

(1)虚拟机栈的栈帧

每个方法在执行的时候,JVM 都会创建一个相应的栈帧(操作数栈、局部变量表、运行时常量池的引用),当方法执行完,该栈帧就从栈中弹出,这样一来,方法中临时创建的独享就不存在了,或者说没有任何 GC roots 指向这些临时对象,这些对象在下一次 GC 的时候便会被回收。

(2)方法区中的静态属性

静态属性数据类属性,不属于任何实例,因此该属性自然会作为 GC roots。这要这个 class 在,该引用指向的对象就一直存在,class 也由被回收的时候。

class 何时会被回收?

  1. 堆中不存在该类的任何实例
  2. 加载该类的 classLoader 已经被回收
  3. 该类的 java.lang.class 对象没有在任何地方被引用,也就是说无法通过反射访问该类的信息

(3)本地方法栈引用的对象

6、说一下 jvm 有哪些垃圾回收算法?

1、对象是否已死算法

  • 引用计数器算法
  • 可达性分析算法

2、GC 算法

(1)标记清除算法

如果对象被标记后进行清除,会带来一个新的问题 – 内存碎片化。如果下次有比较大的对象实例需要在堆上分配较大的内存空间时,可能会出现无法找到足够的连续内存而不得不再次触发垃圾回收。

(2)复制算法(Java 堆中新生代的垃圾回收算法)

  1. 先标记待回收内存和不用回收内存;
  2. 将不用回收的内存复制到新的内存区域;
  3. 就的内存区域就可以被全部回收了,而新的内存区域也是连续的;

缺点是损失部分系统内存,因为腾出部分内存进行复制。

(3)标记压缩算法(Java 堆中老年代的垃圾回收算法)

对于新生代,大部分对象都不会存活,所以复制算法较高效,但对于老年代,大部分对象可能要继续存活,如果此时使用复制算法,效率会降低。

标记压缩算法首先还是标记,将不用回收的内存对象压缩到内存一端,此时即可清除边界处的内存,这样就能避免复制算法带来的效率问题,同时也能避免内存碎片化的问题。

老年代的垃圾回收算法称为 “Major GC”。

7、说一下 jvm 有哪些垃圾回收器?

说一下 jvm 有哪些垃圾回收器?

8、JVM 栈堆概念,何时销毁对象

  1. 类在程序运行的时候就会被加载,方法是在执行的时候才会被加载,如果没有任何引用了,Java 自动垃圾回收,也可以用 System.gc() 开启回收器,但是回收器不一定会马上回收。
  2. 静态变量在类装载的时候进行创建,在整个程序结束时按序销毁;
  3. 实例变量在类实例化对象时创建,在对象销毁的时候销毁;
  4. 局部变量在局部范围内使用时创建,跳出局部范围时销毁;

9、新生代垃圾回收器和老生代垃圾回收器都有哪些?有什么区别?

新生代回收器:Serial、ParNew、Parallel Scavenge

老年代回收器:Serial Old、Parallel Old、CMS

新生代回收器一般采用的是复制算法,复制算法效率较高,但是浪费内存;

老生代回收器一般采用标记清楚算法,比如最常用的 CMS;

10、详细介绍一下 CMS 垃圾回收器?

CMS 垃圾回收器是 Concurrent Mark Sweep,是一种同步的标记 - 清除,CMS 分为四个阶段:

初始标记,标记一下 GC Root 能直接关联到的对象,会触发 “Stop The World”;
并发标记,通过 GC Roots Tracing 判断对象是否在使用中;
重新标记,标记期间产生对象的再次判断,执行时间较短,会触发 “Stop The World”;
并发清除,清除对象,可以和用户线程并发进行;

11、简述分代垃圾回收器是怎么工作的?

分代回收器分为新生代和老年代,新生代大概占 1/3,老年代大概占 2/3;

新生代包括 Eden、From Survivor、To Survivor;

Eden 区和两个 survivor 区的 的空间比例 为 8:1:1 ;

垃圾回收器的执行流程:

  1. 把 Eden + From Survivor 存活的对象放入 To Survivor 区;
  2. 清空 Eden + From Survivor 分区,From Survivor 和 To Survivor 分区交换;
  3. 每次交换后存活的对象年龄 + 1,到达 15,升级为老年代,大对象会直接进入老年代;
  4. 老年代中当空间到达一定占比,会触发全局回收,老年代一般采取标记 - 清除算法;

12、Redis 是什么?

Redis 是一个 key-value 存储系统,它支持存储的 value 类型相对更多,包括 string、list、set、zset(sorted set – 有序集合)和 hash。这些数据结构都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis 支持各种不同方式的排序。为了保证效率,数据都是缓存在内存中,Redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了 master-slave(主从)同步。

13、Redis 都有哪些使用场景?

  1. Redis 是基于内存的 nosql 数据库,可以通过新建线程的形式进行持久化,不影响 Redis 单线程的读写操作
  2. 通过 list 取最新的 N 条数据
  3. 模拟类似于 token 这种需要设置过期时间的场景
  4. 发布订阅消息系统
  5. 定时器、计数器

14、Redis 有哪些功能?

1、基于本机内存的缓存

当调用 api 访问数据库时,假如此过程需要 2 秒,如果每次请求都要访问数据库,那将对服务器造成巨大的压力,如果将此 sql 的查询结果存到 Redis 中,再次请求时,直接从 Redis 中取得,而不是访问数据库,效率将得到巨大的提升,Redis 可以定时去更新数据(比如 1 分钟)。

2、如果电脑重启,写入内存的数据是不是就失效了呢,这时 Redis 还提供了持久化的功能。

3、哨兵(Sentinel)和复制

Sentinel 可以管理多个 Redis 服务器,它提供了监控、提醒以及自动的故障转移功能;

复制则是让 Redis 服务器可以配备备份的服务器;

Redis 也是通过这两个功能保证 Redis 的高可用;

4、集群(Cluster)

单台服务器资源总是有上限的,CPU 和 IO 资源可以通过主从复制,进行读写分离,把一部分 CPU 和 IO 的压力转移到从服务器上,但是内存资源怎么办,主从模式只是数据的备份,并不能扩充内存;

现在我们可以横向扩展,让每台服务器只负责一部分任务,然后将这些服务器构成一个整体,对外界来说,这一组服务器就像是集群一样。

15、Redis 支持的数据类型有哪些?

  1. 字符串
  2. hash
  3. list
  4. set
  5. zset

16、Redis 取值存值问题

1、先把 Redis 的连接池拿出来

JedisPool pool = new JedisPool(new JedisPoolConfig(),"127.0.0.1");Jedis jedis = pool.getResource();

2、存取值

jedis.set("key","value");
jedis.get("key");
jedis.del("key");
//给一个key叠加value
jedis.append("key","value2");//此时key的值就是value + value2;
//同时给多个key进行赋值:
jedis.mset("key1","value1","key2","value2");

3、对 map 进行操作

Map<String,String> user = new HashMap();
user.put("key1","value1");
user.put("key2","value2");
user.put("key3","value3");
//存入
jedis.hmset("user",user);
//取出user中key1 
List<String> nameMap = jedis.hmget("user","key1");
//删除其中一个键值
jedis.hdel("user","key2");
//是否存在一个键
jedis.exists("user");
//取出所有的Map中的值:
Iterator<String> iter = jedis.hkeys("user").iterator();
while(iter.next()){jedis.hmget("user",iter.next());
}

17、Redis 为什么是单线程的?

  1. 代码更清晰,处理逻辑更简单;
  2. 不用考虑各种锁的问题,不存在加锁和释放锁的操作,没有因为可能出现死锁而导致的性能问题;
  3. 不存在多线程切换而消耗 CPU;
  4. 无法发挥多核 CPU 的优势,但可以采用多开几个 Redis 实例来完善;

18、Redis 真的是单线程的吗?

Redis6.0 之前是单线程的,Redis6.0 之后开始支持多线程;
redis 内部使用了基于 epoll 的多路服用,也可以多部署几个 redis 服务器解决单线程的问题;
redis 主要的性能瓶颈是内存和网络;
内存好说,加内存条就行了,而网络才是大麻烦,所以 redis6 内存好说,加内存条就行了;
而网络才是大麻烦,所以 redis6.0 引入了多线程的概念,
redis6.0 在网络 IO 处理方面引入了多线程,如网络数据的读写和协议解析等,需要注意的是,执行命令的核心模块还是单线程的。

19、Redis 持久化有几种方式?

redis 提供了两种持久化的方式,分别是 RDB(Redis DataBase)和 AOF(Append Only File)。

RDB,简而言之,就是在不同的时间点,将 redis 存储的数据生成快照并存储到磁盘等介质上;

AOF,则是换了一个角度来实现持久化,那就是将 redis 执行过的所有写指令记录下来,在下次 redis 重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。

其实 RDB 和 AOF 两种方式也可以同时使用,在这种情况下,如果 redis 重启的话,则会优先采用 AOF 方式来进行数据恢复,这是因为 AOF 方式的数据恢复完整度更高。

如果你没有数据持久化的需求,也完全可以关闭 RDB 和 AOF 方式,这样的话,redis 将变成一个纯内存数据库,就像 memcache 一样。

20、Redis 和 memecache 有什么区别?

1、Redis 相比 memecache,拥有更多的数据结构和支持更丰富的数据操作。

(1)Redis 支持 key-value,常用的数据类型主要有 String、Hash、List、Set、Sorted Set。

(2)memecache 只支持 key-value。

2、内存使用率对比,Redis 采用 hash 结构来做 key-value 存储,由于其组合式的压缩,其内存利用率会高于 memecache。

3、性能对比:Redis 只使用单核,memecache 使用多核。

4、Redis 支持磁盘持久化,memecache 不支持。

Redis 可以将一些很久没用到的 value 通过 swap 方法交换到磁盘。

5、Redis 支持分布式集群,memecache 不支持。

21、Redis 支持的 java 客户端都有哪些?

Redisson、Jedis、lettuce 等等,官方推荐使用 Redisson。

22、jedis 和 redisson 有哪些区别?

Jedis 和 Redisson 都是 Java 中对 Redis 操作的封装。Jedis 只是简单的封装了 Redis 的 API 库,可以看作是 Redis 客户端,它的方法和 Redis 的命令很类似。Redisson 不仅封装了 redis ,还封装了对更多数据结构的支持,以及锁等功能,相比于 Jedis 更加大。但 Jedis 相比于 Redisson 更原生一些,更灵活。

23、什么是缓存穿透?怎么解决?

1、缓存穿透

一般的缓存系统,都是按照 key 去缓存查询,如果不存在对用的 value,就应该去后端系统查找(比如 DB 数据库)。一些恶意的请求会故意查询不存在的 key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。

2、怎么解决?

对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该 key 对应的数据 insert 之后清理缓存。
 
对一定不存在的 key 进行过滤。可以把所有的可能存在的 key 放到一个大的 Bitmap 中,查询时通过该 Bitmap 过滤。

3、缓存雪崩

当缓存服务器重启或者大量缓存集中在某一时间段失效,这样在失效的时候,会给后端系统带来很大的压力,导致系统崩溃。

4、如何解决?

  1. 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其它线程等待;
  2. 做二级缓存;
  3. 不同的 key,设置不同的过期时间,让缓存失效的时间尽量均匀;

24、怎么保证缓存和数据库数据的一致性?

1、淘汰缓存

数据如果为较为复杂的数据时,进行缓存的更新操作就会变得异常复杂,因此一般推荐选择淘汰缓存,而不是更新缓存。

2、选择先淘汰缓存,再更新数据库

假如先更新数据库,再淘汰缓存,如果淘汰缓存失败,那么后面的请求都会得到脏数据,直至缓存过期。

假如先淘汰缓存再更新数据库,如果更新数据库失败,只会产生一次缓存穿透,相比较而言,后者对业务则没有本质上的影响。

3、延时双删策略

如下场景:同时有一个请求 A 进行更新操作,另一个请求 B 进行查询操作。

  1. 请求 A 进行写操作,删除缓存
  2. 请求 B 查询发现缓存不存在
  3. 请求 B 去数据库查询得到旧值
  4. 请求 B 将旧值写入缓存
  5. 请求 A 将新值写入数据库

次数便出现了数据不一致问题。采用延时双删策略得以解决。

public void write(String key,Object data){redisUtils.del(key);db.update(data);Thread.Sleep(100);redisUtils.del(key);
}

这么做,可以将 1 秒内所造成的缓存脏数据,再次删除。这个时间设定可根据俄业务场景进行一个调节。

4、数据库读写分离的场景

两个请求,一个请求 A 进行更新操作,另一个请求 B 进行查询操作。

  1. 请求 A 进行写操作,删除缓存
  2. 请求 A 将数据写入数据库了,
  3. 请求 B 查询缓存发现,缓存没有值
  4. 请求 B 去从库查询,这时,还没有完成主从同步,因此查询到的是旧值
  5. 请求 B 将旧值写入缓存
  6. 数据库完成主从同步,从库变为新值

依旧采用延时双删策略解决此问题。

25、Redis,什么是缓存穿透?怎么解决?

1、缓存穿透

一般的缓存系统,都是按照 key 去缓存查询,如果不存在对用的 value,就应该去后端系统查找(比如 DB 数据库)。一些恶意的请求会故意查询不存在的 key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。

2、怎么解决?

对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该 key 对应的数据 insert 之后清理缓存。
 
对一定不存在的 key 进行过滤。可以把所有的可能存在的 key 放到一个大的 Bitmap 中,查询时通过该 Bitmap 过滤。

3、缓存雪崩

当缓存服务器重启或者大量缓存集中在某一时间段失效,这样在失效的时候,会给后端系统带来很大的压力,导致系统崩溃。

4、如何解决?

  1. 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其它线程等待;
  2. 做二级缓存;
  3. 不同的 key,设置不同的过期时间,让缓存失效的时间尽量均匀;

26、Redis 怎么实现分布式锁?

使用 Redis 实现分布式锁

redis 命令:set users 10 nx ex 12   原子性命令

//使用uuid,解决锁释放的问题
@GetMapping
public void testLock() throws InterruptedException {String uuid = UUID.randomUUID().toString();Boolean b_lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 10, TimeUnit.SECONDS);if(b_lock){Object value = redisTemplate.opsForValue().get("num");if(StringUtils.isEmpty(value)){return;}int num = Integer.parseInt(value + "");redisTemplate.opsForValue().set("num",++num);Object lockUUID = redisTemplate.opsForValue().get("lock");if(uuid.equals(lockUUID.toString())){redisTemplate.delete("lock");}}else{Thread.sleep(100);testLock();}
}

备注:可以通过 lua 脚本,保证分布式锁的原子性。

27、Redis 分布式锁有什么缺陷?

Redis 分布式锁不能解决超时的问题,分布式锁有一个超时时间,程序的执行如果超出了锁的超时时间就会出现问题。

Redis 容易产生的几个问题:

  1. 锁未被释放
  2. B 锁被 A 锁释放了
  3. 数据库事务超时
  4. 锁过期了,业务还没执行完
  5. Redis 主从复制的问题

28、Redis 如何做内存优化?

1、缩短键值的长度

  1. 缩短值的长度才是关键,如果值是一个大的业务对象,可以将对象序列化成二进制数组;
  2. 首先应该在业务上进行精简,去掉不必要的属性,避免存储一些没用的数据;
  3. 其次是序列化的工具选择上,应该选择更高效的序列化工具来降低字节数组大小;
  4. 以 JAVA 为例,内置的序列化方式无论从速度还是压缩比都不尽如人意,这时可以选择更高效的序列化工具,如: protostuff,kryo 等

2、共享对象池

对象共享池指 Redis 内部维护 [0-9999] 的整数对象池。创建大量的整数类型 redisObject 存在内存开销,每个 redisObject 内部结构至少占 16 字节,甚至超过了整数自身空间消耗。所以 Redis 内存维护一个 [0-9999] 的整数对象池,用于节约内存。 除了整数值对象,其他类型如 list,hash,set,zset 内部元素也可以使用整数对象池。因此开发中在满足需求的前提下,尽量使用整数对象以节省内存。

3、字符串优化

4、编码优化

5、控制 key 的数量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/298310.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软考--软件设计师(软件工程总结2)

目录 1.测试方法 2.软件项目管理 3.软件容错技术 4.软件复杂性度量 5.结构化分析方法&#xff08;一种面向数据流的开发方法&#xff09; 6.数据流图 1.测试方法 软件测试&#xff1a;静态测试&#xff08;被测程序采用人工检测&#xff0c;计算机辅助静态分析的手段&…

GraphSage

背景 大型图中节点的低维嵌入在各种预测任务中非常有用。GraphSage是一种通用的归纳框架&#xff0c;它利用节点特征信息&#xff08;例如&#xff0c;文本属性&#xff09;有效地为以前看不见的数据生成节点嵌入。相比于对每个节点训练单独的嵌入&#xff0c;GraphSage学习了一…

Hyper-v平台搭建pve系统之网络配置(双网卡、内外网分离)

现在我需要在我本地配置的PVE系统上配置双网卡&#xff0c;然后一个连接外部网络&#xff08;访问互联网&#xff09;&#xff0c;一个连接内部网络&#xff08;只能和宿主机之间互相访问&#xff09; 最终效果&#xff1a; 登录PVE平台&#xff0c;我可以正常访问外网&#…

用html写一个爱心

<!DOCTYPE html> <html lang"zh-CN"><head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8" /><title>爱您</title><style>* {padding: 0;margin: 0;}body {background-color: pin…

铁山靠之数学建模-基础篇

小黑子的数模基础篇 一、什么是数学建模1.1 数学模型分类1.2 备战准备什么1.3 组队学习路线1.4 赛前准备1.5 赛题选择1.5.1 赛题类型1.5.2 ABC赛题建议 1.6 学会查询1.6.1 百度搜索技巧1.6.2 查文献1.6.3 数据预处理 1.7 建模全过程 二、数模论文2.1 论文排版2.2 标题怎么写2.3…

前端学习之BOM编程-window对象、history对象、navigator对象、location对象

window对象 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>widnow对象</title><style>div{width: 2000px;height: 4000px;background-image: linear-gradient(to bottom right,red,blue…

JVM调优参数介绍

堆配置 -Xms:初始堆大小 -Xms&#xff1a;最大堆大小 -XX:NewSizen:设置年轻代大小 -XX:NewRation:设置年轻代和年老代的比值。如&#xff1a;为3表示年轻代和年老代比值为1&#xff1a;3&#xff0c;年轻代占整个年轻代年老代和的1/4 -XX:SurvivorRation:年轻代中Eden区与…

计组第三版书例题

基础知识过一下 存储器与CPU的连接主要通过数据总线、地址总线和控制总线实现。CPU首先向存储器发送地址信号&#xff0c;然后发出读写控制信号&#xff0c;最后在数据总线上进行数据的读写操作 。这种连接方式确保了CPU能够正确地访问和控制存储器中的数据。 https://blog.cs…

ES6学习(五)-- Module 语法

文章目录 Module 语法1.1 痛点介绍(1) 异步加载(2) 私密(3) 重名(4) 依赖 1.2 解决方法(1) 解决异步加载问题(2) 解决私密问题(3) 重名解决方法(4) 解决依赖问题 1.3 模块化使用案例 Module 语法 之前js 出现的某些痛点&#xff1a; 在script 中引入的变量名不可以重复&#…

Day:003 | Python爬虫:高效数据抓取的编程技术(爬虫基础)

urllib发送get请求 在目前网络获取数据的方式有多种方式&#xff1a;GET方式大部分被传输到浏览器的html&#xff0c;images, js,css, … 都是通过GET 方法发出请求的。它是获取数据的主要方法 例如&#xff1a;www.baidu.com 搜索 Get请求的参数都是在Url中体现的,如果有中…

SQLAlchemy 建立数据库模型之间的关系

常见关系&#xff1a; 一对多关系多对一关系多对多关系一对一关系 一对多关系&#xff08;一个作者&#xff0c;多篇文章&#xff09; ## 一对多关系&#xff0c;单作者-多文章&#xff0c;外键不可少 ## 外键(ForeignKey)总在多的那边定义,关系(relationship)总在单的那边定…

12-项目部署_持续集成

项目部署_持续集成 1 今日内容介绍 1.1 什么是持续集成 持续集成&#xff08; Continuous integration &#xff0c; 简称 CI &#xff09;指的是&#xff0c;频繁地&#xff08;一天多次&#xff09;将代码集成到主干 持续集成的组成要素 一个自动构建过程&#xff0c; 从…

华为ensp中ospf多区域管理 原理及配置命令(详解)

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; ————前言———— OSPF 多区域的主要作用是缩小链路状态数据库和路由表的规模&#xff0c;减少路由更新的频率&#xff0c;提高网络的可扩展性&#xff0c;实现路由过滤和路由汇总&#xff0…

【计算机网络】应用层——HTTP协议详解

文章目录 1. HTTP协议简介2. Fiddler简介&#xff08;抓包工具&#xff09;2.1 安装Fiddler2.2 使用Fiddler进行抓包2.3 Fiddler的工作原理 3. HTTP协议的报文格式4. HTTP 请求4.1 HTTP请求首行4.2 认识 URL关于 URL encoding 4.3 认识“方法”GET方法POST方法GET和POST的区别关…

【linux】基础IO(二)

我们在基础IO&#xff08;一&#xff09;主要讲述了fd&#xff0c;一切皆文件&#xff0c;文件的系统调用与语言文件库函数的关系&#xff0c; 今天主要进行对重定向与缓冲区的理解与应用。另外&#xff0c;对系统调用的read进行一下使用。 read的使用&#xff1a; 再使用rea…

CMakeLists.txt编写简单介绍:CMakeLists.txt同时编译.cpp和.cu

关于CMakeLists.txt的相关介绍,这里不赘诉,本人的出发点是借助于CMakeLists.txt掌握基本的C++构建项目流程,下面是本人根据网络资料以及个人实践掌握的资料。 CMakeList.txt构建C++项目 下图是一个使用CUDA实现hello world的项目,一般来说,一个标准的C++项目包括三个文件…

类的函数成员(三):拷贝构造函数

一.什么是拷贝构造函数&#xff1f; 1.1 概念 同一个类的对象在内存中有完全相同的结构&#xff0c;如果作为一个整体进行复制或称拷贝是完全可行的。这个拷贝过程只需要拷贝数据成员&#xff0c;而函数成员是共用的&#xff08;只有一份拷贝&#xff09;。 在建立对象…

Linux 文件相关命令

一、查看文件命令 1&#xff09;浏览文件less 默认查看文件的前 10 行。 less /etc/services ##功能说明&#xff1a; #1.默认打开首屏内容 #2.按【回车】按行访问 #3.按【空格】按屏访问 #4.【从上向下】搜索用/111,搜索包含111的内容&#xff0c;此时按n继续向下搜&#x…

leetcode.203. 移除链表元素

题目 题意&#xff1a;删除链表中等于给定值 val 的所有节点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5] 示例 2&#xff1a; 输入&#xff1a;head [], val 1 输出&#xff1a;[] 示例 3&#xff1a; 输入&#…

LeetCode 热题 100 | 贪心算法

目录 1 121. 买卖股票的最佳时机 2 55. 跳跃游戏 3 45. 跳跃游戏 II 4 763. 划分字母区间 菜鸟做题&#xff0c;语言是 C 1 121. 买卖股票的最佳时机 解题思路&#xff1a; 维护一个变量 max_pricemax_price 用于存储排在 i 天之后的股票最高价格第 i 天的最高利润 …