Java面试黄金宝典9
1. Redis 持久化机制
Redis 提供了两种主要的持久化机制:RDB(Redis Database)和 AOF(Append Only File),下面对这两种机制进行详细介绍。
RDB(Redis Database)
- 原理:RDB 是将 Redis 在某一时刻的内存数据以快照的形式保存到磁盘文件中。它会记录下 Redis 内存中的所有键值对,形成一个二进制文件。在 Redis 重启时,可以直接加载这个 RDB 文件来恢复数据。
- 触发方式
- 手动触发:可以使用
SAVE
或BGSAVE
命令。SAVE
命令会阻塞 Redis 服务器进程,在保存 RDB 文件的过程中,服务器无法处理其他客户端的请求,直到 RDB 文件创建完毕。而BGSAVE
命令会派生出一个子进程来进行快照操作,主进程可以继续处理客户端的请求,不会被阻塞。 - 自动触发:可以在 Redis 的配置文件中设置
save
选项。例如,save 900 1
表示在 900 秒(15 分钟)内,如果至少有 1 个键被修改,就会自动触发一次BGSAVE
操作。
- 手动触发:可以使用
- 优点
- 文件紧凑:RDB 文件是一个二进制文件,占用的磁盘空间相对较小,适合用于备份和灾难恢复。可以将 RDB 文件复制到其他服务器上,以便在需要时快速恢复数据。
- 恢复速度快:由于 RDB 文件记录的是某一时刻的内存快照,在 Redis 重启时,只需要将 RDB 文件加载到内存中即可,恢复速度比 AOF 方式快。
- 缺点
- 数据丢失风险:由于 RDB 是定期进行快照的,所以可能会丢失最后一次快照之后的数据。例如,如果在两次快照之间 Redis 服务器发生故障,那么这期间的数据修改就会丢失。
- 快照过程占用内存:在进行快照操作时,需要将内存中的数据复制到磁盘上,这可能会占用较多的内存资源,尤其是在数据量较大的情况下。
AOF(Append Only File)
- 原理:AOF 是将 Redis 执行的所有写命令追加到一个文件中。在 Redis 重启时,会重新执行这些命令来恢复数据。AOF 文件是一个文本文件,记录了 Redis 服务器接收到的每一个写操作。
- 触发方式:在 Redis 的配置文件中设置
appendonly yes
来开启 AOF 持久化。同时,可以选择不同的同步策略,如:- appendfsync always:每次写操作都同步到磁盘。这种策略可以保证数据的安全性,最多只会丢失一个写操作的数据,但会影响 Redis 的性能,因为每次写操作都需要进行磁盘 I/O。
- appendfsync everysec:每秒同步一次。这是默认的同步策略,在性能和数据安全性之间取得了一个平衡。最多可能会丢失 1 秒内的数据。
- appendfsync no:由操作系统决定何时同步。这种策略的性能最高,但数据安全性最低,因为操作系统可能会在一段时间后才将数据写入磁盘,在这段时间内如果发生故障,可能会丢失较多的数据。
- 优点
- 数据安全性高:由于 AOF 文件记录了所有的写操作,所以最多只会丢失 1 秒内的数据(使用
appendfsync everysec
策略),相比 RDB 方式,数据的安全性更高。 - 文件可读性强:AOF 文件是一个文本文件,可以直接查看和修改。如果不小心执行了错误的命令,可以通过编辑 AOF 文件来恢复数据。
- 数据安全性高:由于 AOF 文件记录了所有的写操作,所以最多只会丢失 1 秒内的数据(使用
- 缺点
- 文件体积大:由于 AOF 文件记录了所有的写操作,随着时间的推移,文件会越来越大,占用的磁盘空间也会越来越多。
- 恢复速度慢:在 Redis 重启时,需要重新执行 AOF 文件中的所有命令来恢复数据,这比加载 RDB 文件的速度要慢。
- 要点
- 适用场景选择:RDB 适合大规模数据恢复和对数据安全性要求不是特别高的场景,例如缓存数据的恢复。AOF 适合对数据安全性要求较高的场景,如数据库的持久化。
- 组合使用:可以同时使用 RDB 和 AOF 两种持久化机制,以提高数据的安全性和恢复效率。在 Redis 重启时,会优先使用 AOF 文件来恢复数据,如果 AOF 文件不存在,则使用 RDB 文件。
- 应用
- 混合持久化:Redis 4.0 引入了混合持久化方式,结合了 RDB 和 AOF 的优点。在进行 AOF 重写时,将 RDB 快照内容和增量的 AOF 日志合并到一个新的 AOF 文件中。这样,在 Redis 重启时,可以先加载 RDB 快照部分,然后再执行增量的 AOF 日志,既保证了数据的安全性,又提高了恢复速度。
2. Redis 的一致性哈希算法
- 定义
一致性哈希算法是一种特殊的哈希算法,用于解决分布式系统中数据分布和负载均衡的问题。在 Redis 集群中,一致性哈希算法用于将数据均匀地分布到多个节点上。
- 原理
- 虚拟环形空间:首先,将整个哈希空间(通常是 0 到 2^32 - 1)想象成一个虚拟的环形空间。这个环形空间就像一个时钟盘面,从 0 开始,顺时针方向依次递增,直到 2^32 - 1 后又回到 0。
- 节点映射:然后,将每个 Redis 节点通过哈希函数(如 MD5、SHA - 1 等)映射到这个环形空间上的一个点。例如,有三个 Redis 节点 A、B、C,通过哈希函数计算出它们在环形空间上的位置分别为 HA、HB、HC。
- 数据映射与存储:当有数据需要存储时,同样使用哈希函数将数据的键映射到环形空间上的一个点。然后,从这个点开始顺时针查找,找到第一个遇到的节点,将数据存储到该节点上。例如,有数据键 K,其哈希值为 HK,从 HK 开始顺时针查找,第一个遇到的节点是 B,那么就将数据存储到节点 B 上。
- 解决节点增减问题
- 增加节点:当增加一个节点时,只会影响到该节点顺时针方向最近的一个节点的数据分布,其他节点的数据不受影响。例如,增加一个新节点 D,其哈希值为 HD,从 HD 开始顺时针查找,第一个遇到的节点是 B,那么原本存储在节点 B 上,哈希值在 HD 到 HB 之间的数据就会被迁移到节点 D 上,而其他节点的数据不会发生变化。
- 删除节点:当删除一个节点时,只会影响到该节点顺时针方向最近的一个节点的数据分布,其他节点的数据不受影响。例如,删除节点 B,那么原本存储在节点 B 上的数据就会被迁移到节点 C 上,而节点 A 和 D 的数据不会发生变化。
- 要点
- 减少数据迁移:一致性哈希算法可以减少节点增减时数据的迁移量,提高系统的可扩展性和稳定性。相比传统的哈希算法,当节点数量发生变化时,只需要迁移部分数据,而不是重新计算所有数据的存储位置。
- 虚拟节点:为了避免数据分布不均匀的问题,可以引入虚拟节点的概念。将一个物理节点映射到多个虚拟节点上,这些虚拟节点均匀地分布在环形空间上,从而使数据更加均匀地分布在各个物理节点上。例如,一个物理节点可以映射成 100 个虚拟节点,这样在数据存储时,就会有更多的机会选择不同的物理节点,减少了数据倾斜的可能性。
- 应用
- Redis Cluster 分片:在实际应用中,Redis Cluster 采用了分片的方式来实现数据的分布式存储,虽然没有完全使用一致性哈希算法,但也借鉴了其思想。Redis Cluster 将整个哈希空间划分为 16384 个槽(slot),每个节点负责一部分槽的存储。当有数据需要存储时,先计算数据键的哈希值,然后根据哈希值确定对应的槽,再将数据存储到负责该槽的节点上。
3. Redis 有哪几种数据类型
Redis 支持多种数据类型,每种数据类型都有其特点和适用场景,以下是常见的几种数据类型:
字符串(String)
- 特点:是 Redis 最基本的数据类型,可以存储任何类型的数据,如文本、整数、二进制数据等。一个字符串类型的值最大可以存储 512MB 的数据。
- 常见操作:
- SET:用于设置一个键的值。例如,
SET key value
可以将键key
的值设置为value
。 - GET:用于获取一个键的值。例如,
GET key
可以获取键key
的值。 - INCR:用于将一个键的值加 1。如果键不存在,则先将其值初始化为 0,再进行加 1 操作。例如,
INCR counter
可以将键counter
的值加 1。 - DECR:用于将一个键的值减 1。如果键不存在,则先将其值初始化为 0,再进行减 1 操作。例如,
DECR counter
可以将键counter
的值减 1。
- SET:用于设置一个键的值。例如,
哈希(Hash)
- 特点:是一个键值对的集合,适合存储对象。每个哈希可以包含多个字段和对应的值,字段和值都是字符串类型。
- 常见操作:
- HSET:用于设置哈希中一个字段的值。例如,
HSET user:1 name "John"
可以将哈希user:1
中字段name
的值设置为"John"
。 - HGET:用于获取哈希中一个字段的值。例如,
HGET user:1 name
可以获取哈希user:1
中字段name
的值。 - HGETALL:用于获取哈希中所有字段和值。例如,
HGETALL user:1
可以返回哈希user:1
中所有字段和对应的值。
- HSET:用于设置哈希中一个字段的值。例如,
列表(List)
- 特点:是一个有序的字符串列表,可以从列表的两端进行插入和删除操作。列表中的元素可以重复,并且可以按照插入的顺序进行访问。
- 常见操作:
- LPUSH:用于将一个或多个值插入到列表的头部。例如,
LPUSH mylist value1 value2
可以将value1
和value2
插入到列表mylist
的头部。 - RPUSH:用于将一个或多个值插入到列表的尾部。例如,
RPUSH mylist value3 value4
可以将value3
和value4
插入到列表mylist
的尾部。 - LPOP:用于从列表的头部移除并返回一个元素。例如,
LPOP mylist
可以从列表mylist
的头部移除并返回一个元素。 - RPOP:用于从列表的尾部移除并返回一个元素。例如,
RPOP mylist
可以从列表mylist
的尾部移除并返回一个元素。
- LPUSH:用于将一个或多个值插入到列表的头部。例如,
集合(Set)
- 特点:是一个无序且唯一的字符串集合,不允许有重复的元素。集合支持集合的交、并、差等操作。
- 常见操作:
- SADD:用于向集合中添加一个或多个元素。例如,
SADD myset value1 value2
可以将value1
和value2
添加到集合myset
中。 - SMEMBERS:用于获取集合中的所有元素。例如,
SMEMBERS myset
可以返回集合myset
中的所有元素。 - SINTER:用于计算多个集合的交集。例如,
SINTER set1 set2
可以返回集合set1
和set2
的交集。
- SADD:用于向集合中添加一个或多个元素。例如,
有序集合(Sorted Set)
- 特点:是一个有序的字符串集合,每个成员都有一个分数,根据分数进行排序。成员是唯一的,但分数可以相同。
- 常见操作:
- ZADD:用于向有序集合中添加一个或多个成员,并指定其分数。例如,
ZADD myzset 10 "member1" 20 "member2"
可以将成员"member1"
和"member2"
分别以分数 10 和 20 添加到有序集合myzset
中。 - ZRANGE:用于获取有序集合中指定范围的成员。例如,
ZRANGE myzset 0 -1
可以返回有序集合myzset
中所有成员,按照分数从小到大排序。 - ZREVRANGE:用于获取有序集合中指定范围的成员,按照分数从大到小排序。例如,
ZREVRANGE myzset 0 -1
可以返回有序集合myzset
中所有成员,按照分数从大到小排序。
- ZADD:用于向有序集合中添加一个或多个成员,并指定其分数。例如,
- 要点
- 应用场景选择:不同的数据类型适用于不同的应用场景,需要根据实际需求选择合适的数据类型。例如,字符串类型适用于缓存数据、计数器等;哈希类型适用于存储对象;列表类型适用于消息队列、任务队列等;集合类型适用于去重、交集计算等;有序集合类型适用于排行榜、热门列表等。
- 丰富的操作命令:Redis 对每种数据类型都提供了丰富的操作命令,可以高效地处理各种数据。掌握这些操作命令可以更好地利用 Redis 的功能。
- 应用
- 其他数据类型:Redis 还支持其他一些数据类型,如 HyperLogLog、Bitmap、Geo 等。
- HyperLogLog:用于进行基数统计,即估算一个集合中不重复元素的数量。它可以用很少的内存空间来统计大量的数据,误差率在 0.81% 左右。例如,可以用 HyperLogLog 来统计网站的日活跃用户数。
- Bitmap:是一种特殊的字符串类型,它可以将字符串中的每个位看作一个布尔值。可以用来进行位操作,如统计用户的登录天数、在线状态等。
- Geo:用于处理地理位置信息。可以将地理位置信息(经纬度)存储到 Redis 中,并进行距离计算、附近地点查找等操作。
4. 当散列类型的 value 值非常大的时候怎么进行压缩
当散列类型的 value
值非常大时,可以考虑以下几种压缩方法:
使用 Redis 内部压缩
- 原理:Redis 本身对散列类型提供了一定的压缩机制。当散列的字段数量和每个字段的值长度都小于配置的值时,Redis 会使用压缩列表(ziplist)来存储散列数据。压缩列表是一种连续的内存数据结构,它可以将多个字段和值紧凑地存储在一起,从而节省内存。
- 配置参数:可以通过配置
hash - max - ziplist - entries
和hash - max - ziplist - value
来控制是否使用压缩列表。hash - max - ziplist - entries
表示压缩列表中允许的最大字段数量,hash - max - ziplist - value
表示压缩列表中每个字段允许的最大长度。例如,将hash - max - ziplist - entries
设置为 512,hash - max - ziplist - value
设置为 64,表示当散列的字段数量不超过 512 且每个字段的值长度不超过 64 字节时,使用压缩列表存储。
应用层压缩
- 原理:在应用层对数据进行压缩,例如使用 Gzip、Snappy 等压缩算法对数据进行压缩后再存储到 Redis 中。在读取数据时,先进行解压缩操作。
- 示例代码(Java):
java
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;public class CompressionUtils {public static byte[] compress(byte[] data) throws IOException {ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length);GZIPOutputStream gzip = new GZIPOutputStream(bos);gzip.write(data);gzip.close();byte[] compressed = bos.toByteArray();bos.close();return compressed;}public static byte[] decompress(byte[] compressed) throws IOException {ByteArrayInputStream bis = new ByteArrayInputStream(compressed);GZIPInputStream gis = new GZIPInputStream(bis);ByteArrayOutputStream bos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len;while ((len = gis.read(buffer)) != -1) {bos.write(buffer, 0, len);}gis.close();bos.close();return bos.toByteArray();}
}
- 要点
- Redis 内部压缩:是一种简单有效的方法,但需要根据实际情况调整配置参数。如果配置不合理,可能会导致压缩效果不佳或性能下降。
- 应用层压缩:可以更灵活地控制压缩算法和压缩级别,但会增加应用程序的复杂度。在使用应用层压缩时,需要注意压缩和解压缩的性能,避免成为系统的瓶颈。
- 应用
- 压缩算法选择:在选择压缩算法时,需要考虑压缩比和压缩 / 解压缩的性能。例如,Gzip 压缩比高,但压缩和解压缩速度相对较慢;Snappy 压缩和解压缩速度快,但压缩比相对较低。可以根据实际需求选择合适的压缩算法。
5. 用 Redis 怎么实现摇一摇与附近的人功能
摇一摇功能
- 实现思路:可以使用 Redis 的有序集合(Sorted Set)来实现摇一摇功能。当用户摇一摇时,将用户的 ID 作为成员,当前时间戳作为分数,添加到有序集合中。每次用户摇一摇时,从有序集合中获取一定时间范围内(如最近 1 分钟)的用户列表,这些用户就是在同一时间段内摇一摇的用户。
- 示例代码(Java):
java
import redis.clients.jedis.Jedis;
import java.util.Set;public class ShakeFunction {private static final String SHAKE_KEY = "shake_users";public static void addShakeUser(Jedis jedis, String userId) {long timestamp = System.currentTimeMillis();jedis.zadd(SHAKE_KEY, timestamp, userId);}public static Set<String> getShakeUsersInRange(Jedis jedis, long startTime, long endTime) {return jedis.zrangeByScore(SHAKE_KEY, startTime, endTime);}
}
- 使用示例:
java
import redis.clients.jedis.Jedis;
import java.util.Set;public class Main {public static void main(String[] args) {Jedis jedis = new Jedis("localhost");// 用户摇一摇ShakeFunction.addShakeUser(jedis, "user1");// 获取最近 1 分钟内摇一摇的用户long currentTime = System.currentTimeMillis();long oneMinuteAgo = currentTime - 60 * 1000;Set<String> shakeUsers = ShakeFunction.getShakeUsersInRange(jedis, oneMinuteAgo, currentTime);System.out.println("最近 1 分钟内摇一摇的用户: " + shakeUsers);jedis.close();}
}
附近的人功能
- 实现思路:可以使用 Redis 的 Geo 数据类型来实现附近的人功能。当用户登录或更新位置时,将用户的经纬度信息添加到 Geo 集合中。当用户查询附近的人时,使用
GEORADIUS
命令根据用户的当前位置和指定的半径,获取附近的用户列表。 - 示例代码(Java):
java
import redis.clients.jedis.Jedis;
import java.util.List;public class NearbyPeopleFunction {private static final String NEARBY_KEY = "nearby_people";public static void addUserLocation(Jedis jedis, String userId, double longitude, double latitude) {jedis.geoadd(NEARBY_KEY, longitude, latitude, userId);}public static List<String> getNearbyPeople(Jedis jedis, double longitude, double latitude, double radius) {return jedis.georadius(NEARBY_KEY, longitude, latitude, radius, redis.clients.jedis.GeoUnit.KM);}
}
- 使用示例:
java
import redis.clients.jedis.Jedis;
import java.util.List;public class Main {public static void main(String[] args) {Jedis jedis = new Jedis("localhost");// 添加用户位置NearbyPeopleFunction.addUserLocation(jedis, "user1", 116.4074, 39.9042);NearbyPeopleFunction.addUserLocation(jedis, "user2", 116.41, 39.91);// 查询附近的人List<String> nearbyPeople = NearbyPeopleFunction.getNearbyPeople(jedis, 116.4074, 39.9042, 1);System.out.println("附近的人: " + nearbyPeople);jedis.close();}
}
- 要点
- 摇一摇功能:利用有序集合的时间排序特性,快速获取同一时间段内的用户列表。通过设置合适的时间范围,可以控制查询的精度。
- 附近的人功能:利用 Geo 数据类型的空间索引特性,高效地查询附近的用户。在使用
GEORADIUS
命令时,需要注意半径的单位和范围。
- 应用
- 结果处理:可以对查询结果进行进一步的处理,如过滤掉已经屏蔽的用户、按距离排序等。例如,在获取到附近的人列表后,可以通过数据库查询用户的屏蔽列表,将屏蔽的用户从结果中过滤掉。
- 数据清理:为了提高性能,可以定期清理有序集合和 Geo 集合中的过期数据。例如,对于摇一摇功能的有序集合,可以定期删除一段时间之前的记录。
6. Redis 主从复制过程
- 定义
Redis 主从复制是指将一个 Redis 实例(主节点)的数据复制到其他 Redis 实例(从节点)的过程,其主要目的是提高 Redis 的可用性和读写性能。主从复制的过程如下:
- 建立连接
- 从节点向主节点发送
SYNC
或PSYNC
命令,请求进行数据同步。在 Redis 2.8 之前,使用SYNC
命令进行全量同步;在 Redis 2.8 及之后,使用PSYNC
命令支持部分重同步,减少了全量同步的开销。
- 主节点生成 RDB 文件
- 主节点收到从节点的同步请求后,会执行
BGSAVE
命令生成一个 RDB 文件。在生成 RDB 文件的过程中,主节点会记录从现在开始执行的所有写命令。
- 主节点发送 RDB 文件
- 主节点将生成的 RDB 文件发送给从节点。从节点接收到 RDB 文件后,会将其加载到内存中。在加载 RDB 文件的过程中,从节点会阻塞,无法处理客户端的请求。
- 主节点发送增量数据
- 主节点将在生成 RDB 文件期间记录的写命令发送给从节点,从节点执行这些命令,以保证数据的一致性。这些增量数据可以是主节点在生成 RDB 文件时新产生的写操作,也可以是从节点断开连接期间主节点执行的写操作。
- 持续同步
- 主节点将后续的写命令实时发送给从节点,从节点执行这些命令,保持与主节点的数据一致。主从复制是异步的,从节点可能会有一定的数据延迟。
- 要点
- 提高可用性和性能:主从复制可以提高 Redis 的可用性和读写性能。读操作可以分散到从节点上执行,减轻主节点的负担;当主节点发生故障时,可以将从节点提升为主节点,继续提供服务。
- 异步复制:主从复制是异步的,从节点可能会有一定的数据延迟。在对数据一致性要求较高的场景中,需要考虑这种延迟带来的影响。
- 应用
- 部分重同步(PSYNC):Redis 2.8 之后引入了部分重同步机制,减少了全量同步的开销。当从节点与主节点断开连接后重新连接时,如果主节点的复制偏移量和从节点的复制偏移量相差不大,可以只进行部分数据的同步。部分重同步的过程如下:
- 从节点向主节点发送
PSYNC
命令,并携带自己的复制偏移量和运行 ID。 - 主节点根据从节点的复制偏移量和运行 ID 判断是否可以进行部分重同步。如果可以,主节点将从复制偏移量开始的增量数据发送给从节点;如果不可以,主节点将进行全量同步。
- 从节点向主节点发送
7. Redis 如何解决 key 冲突
- 定义
在 Redis 中,key 冲突通常是指不同的数据使用了相同的 key。Redis 本身并没有专门的机制来解决 key 冲突,因为 key 是唯一的,如果使用相同的 key 进行写入操作,会覆盖原来的值。为了避免 key 冲突,可以采取以下措施:
- 命名规范
- 制定规则:制定统一的命名规范,例如使用前缀来区分不同类型的数据。例如,
user:1:name
表示用户 ID 为 1 的用户的姓名,product:100:price
表示商品 ID 为 100 的商品的价格。通过使用前缀,可以将不同类型的数据区分开来,减少 key 冲突的可能性。 - 层次结构:可以使用层次结构来命名 key,例如使用冒号
:
来分隔不同的层次。这样可以使 key 的命名更加清晰,便于管理和维护。
- 使用哈希
- 哈希处理:对于可能会产生冲突的 key,可以使用哈希函数对 key 进行处理,然后将哈希值作为新的 key。例如,使用 MD5 或 SHA - 1 等哈希算法。哈希函数可以将任意长度的输入转换为固定长度的输出,通过哈希处理可以将不同的 key 映射到不同的哈希值,从而减少 key 冲突的概率。
- 示例代码(Java):
java
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class HashUtils {public static String hashKey(String key) {try {MessageDigest md = MessageDigest.getInstance("MD5");byte[] digest = md.digest(key.getBytes());StringBuilder sb = new StringBuilder();for (byte b : digest) {sb.append(String.format("%02x", b & 0xff));}return sb.toString();} catch (NoSuchAlgorithmException e) {e.printStackTrace();return key;}}
}
- 要点
- 命名规范:良好的命名规范是避免 key 冲突的基础。通过制定统一的命名规则,可以使 key 的命名更加清晰、有条理,减少人为因素导致的 key 冲突。
- 哈希函数:哈希函数可以在一定程度上减少 key 冲突的概率,但不能完全避免。因为哈希函数可能会产生哈希碰撞,即不同的输入可能会产生相同的哈希值。在使用哈希函数时,需要考虑哈希碰撞的处理方法。
- 应用
- 分布式唯一 ID 生成器:在分布式系统中,可以使用分布式唯一 ID 生成器来生成唯一的 key,如 Snowflake 算法。Snowflake 算法生成的 ID 是一个 64 位的长整型数字,由时间戳、工作机器 ID 和序列号组成,保证了在分布式环境下生成的 ID 是唯一的。
8. Redis 是怎么存储数据的
- 定义
Redis 是一个基于内存的键值对数据库,数据主要存储在内存中,但也支持持久化到磁盘。
- 内存存储
- 哈希表结构:Redis 使用哈希表来存储键值对,每个哈希表由多个哈希桶组成,每个哈希桶可以存储一个或多个键值对。当有新的键值对插入时,Redis 会根据键的哈希值计算出对应的哈希桶,然后将键值对插入到该哈希桶中。如果多个键的哈希值相同,会发生哈希冲突,Redis 采用链地址法来解决哈希冲突,即将冲突的键值对通过链表连接起来。
- 数据结构优化:对于不同的数据类型,Redis 采用了不同的内部数据结构来优化存储和操作。例如,对于字符串类型,如果值的长度较短,会使用简单动态字符串(SDS)来存储;对于哈希类型,如果字段数量较少且每个字段的值长度较短,会使用压缩列表(ziplist)来存储;对于有序集合类型,如果成员数量较少,会使用压缩列表来存储,当成员数量较多时,会使用跳跃表(skiplist)来存储。
- 持久化存储
- RDB 持久化:如前面所述,RDB 是将 Redis 在某一时刻的内存数据以快照的形式保存到磁盘文件中。在进行 RDB 持久化时,Redis 会执行
BGSAVE
命令,派生出一个子进程来生成 RDB 文件,主进程可以继续处理客户端的请求。RDB 文件是一个二进制文件,占用的磁盘空间相对较小,适合用于备份和灾难恢复。 - AOF 持久化:AOF 是将 Redis 执行的所有写命令追加到一个文件中。在 Redis 重启时,会重新执行这些命令来恢复数据。AOF 文件是一个文本文件,记录了 Redis 服务器接收到的每一个写操作。可以通过配置不同的同步策略来控制 AOF 文件的同步频率,如
appendfsync always
(每次写操作都同步到磁盘)、appendfsync everysec
(每秒同步一次)、appendfsync no
(由操作系统决定何时同步)。
- 要点
- 内存存储优势:内存存储使得 Redis 具有非常高的读写性能,因为内存的读写速度比磁盘快得多。但数据会在服务器重启后丢失,因此需要结合持久化机制来保证数据的安全性。
- 持久化权衡:持久化存储可以保证数据的安全性,但会增加磁盘 I/O 开销。在选择持久化方式时,需要根据实际需求权衡数据安全性和性能。例如,对于对数据安全性要求较高的场景,可以选择 AOF 持久化;对于对性能要求较高且可以容忍一定数据丢失的场景,可以选择 RDB 持久化。
- 应用
- 内存淘汰策略:Redis 还支持内存淘汰策略,当内存使用达到一定阈值时,会根据配置的策略淘汰一些数据,以释放内存空间。常见的内存淘汰策略有:
- volatile - lru:淘汰最近最少使用的过期键。
- allkeys - lru:淘汰最近最少使用的键。
- volatile - ttl:淘汰剩余生存时间最短的过期键。
- volatile - random:随机淘汰一个过期键。
- allkeys - random:随机淘汰一个键。
- noeviction:当内存不足时,不淘汰任何数据,直接返回错误。
9. Redis 使用场景
Redis 由于其高性能、丰富的数据类型和持久化机制,在很多场景中都有广泛的应用,以下是一些常见的使用场景:
- 缓存
- 原理:可以将经常访问的数据存储在 Redis 中,减少对数据库的访问压力,提高系统的响应速度。当客户端请求数据时,首先从 Redis 中查找,如果找到则直接返回;如果未找到,则从数据库中查询,并将查询结果存储到 Redis 中,以便下次使用。
- 示例:将用户信息、商品信息等缓存到 Redis 中。例如,在一个电商系统中,用户每次访问商品详情页时,先从 Redis 中获取商品信息,如果 Redis 中没有,则从数据库中查询,并将查询结果存储到 Redis 中。
- 会话管理
- 原理:可以使用 Redis 来存储用户的会话信息,如登录状态、购物车信息等。由于 Redis 的高性能和分布式特性,可以方便地实现会话的共享和管理。在分布式系统中,多个服务器可以共享同一个 Redis 实例,用户的会话信息可以在不同的服务器之间进行同步。
- 示例:在一个多节点的 Web 应用中,用户登录后,将用户的会话信息存储到 Redis 中。当用户访问其他页面时,服务器可以从 Redis 中获取用户的会话信息,判断用户的登录状态。
- 消息队列
- 原理:Redis 的列表数据类型可以用于实现简单的消息队列。生产者可以将消息添加到列表的一端,消费者从列表的另一端取出消息进行处理。列表的
LPUSH
和RPOP
或RPUSH
和LPOP
操作可以实现消息的先进先出(FIFO)或后进先出(LIFO)。 - 示例:在一个异步任务处理系统中,生产者将任务信息添加到 Redis 列表中,消费者从列表中取出任务进行处理。例如,在一个图片处理系统中,生产者将图片处理任务添加到 Redis 列表中,消费者从列表中取出任务,进行图片的裁剪、压缩等处理。
- 排行榜
- 原理:可以使用 Redis 的有序集合数据类型来实现排行榜功能。例如,根据用户的积分、活跃度等进行排名。将用户的 ID 作为成员,用户的积分或活跃度作为分数,添加到有序集合中,通过
ZRANGE
或ZREVRANGE
命令可以获取排行榜的前几名。 - 示例:在一个游戏系统中,根据玩家的得分进行排名。将玩家的 ID 作为成员,玩家的得分作为分数,添加到有序集合中。通过
ZREVRANGE
命令可以获取得分最高的前 10 名玩家。
- 分布式锁
- 原理:可以使用 Redis 的原子操作来实现分布式锁,保证在分布式系统中同一时间只有一个进程可以访问共享资源。Redis 的
SETNX
(Set if Not eXists)命令可以原子地设置一个键的值,如果键不存在,则设置成功;如果键已经存在,则设置失败。通过SETNX
命令可以实现简单的分布式锁。 - 示例:在一个分布式系统中,多个进程需要同时访问一个共享资源,如数据库的写操作。可以使用 Redis 的
SETNX
命令来获取锁,如果获取成功,则进行操作;如果获取失败,则等待一段时间后重试。
- 要点
- 数据类型选择:选择合适的 Redis 数据类型来满足不同的应用场景需求。例如,缓存场景可以使用字符串类型;会话管理场景可以使用哈希类型;消息队列场景可以使用列表类型;排行榜场景可以使用有序集合类型;分布式锁场景可以使用字符串类型。
- 性能和安全性:注意 Redis 的内存使用和持久化配置,以保证系统的稳定性和数据的安全性。例如,在使用缓存时,需要设置合理的过期时间,避免内存占用过高
- 应用
- 计数器
- 原理:利用 Redis 字符串类型的
INCR
和DECR
等原子操作,可轻松实现计数器功能。原子操作保证了在高并发环境下计数的准确性,多个客户端同时对计数器进行操作时不会出现数据不一致的问题。 - 示例:在网站中统计页面的访问量,每当有用户访问页面时,对相应的计数器键执行
INCR
操作。在电商系统中统计商品的销量,用户每下单一次,就对该商品对应的销量计数器执行INCR
操作。
- 原理:利用 Redis 字符串类型的
- 限流
- 原理:借助 Redis 的数据结构和原子操作来实现限流策略。例如,使用有序集合记录请求的时间戳,通过统计在一定时间窗口内的请求数量来判断是否超过限流阈值;也可以使用令牌桶算法,利用 Redis 的原子操作模拟令牌的生成和消耗。
- 示例:对于一个 API 服务,为了防止恶意攻击或过多请求导致服务崩溃,可以设置每分钟每个 IP 地址的请求次数上限。当有请求到来时,检查该 IP 对应的计数器是否超过上限,如果未超过则允许请求并更新计数器,否则拒绝请求。
- 社交关系处理
- 原理:利用 Redis 的集合和有序集合类型处理社交关系。集合类型可用于存储用户的好友列表、粉丝列表等,通过集合的交、并、差等操作可以方便地实现好友推荐、共同好友查找等功能;有序集合可以根据用户之间的互动频率、亲密度等进行排序。
- 示例:在社交平台中,使用集合存储每个用户的好友列表,通过
SINTER
命令可以快速找出两个用户的共同好友。使用有序集合记录用户之间的互动得分,根据得分对用户的推荐好友列表进行排序。
10. Tomcat 的结构
- 定义
Tomcat 是一个开源的 Servlet 容器,用于运行 Java Web 应用程序。其主要结构包括以下几个组件,这些组件相互协作,使得 Tomcat 能够高效地处理客户端请求。
- Server
- 定义:代表整个 Tomcat 服务器实例,是 Tomcat 结构的顶层组件。一个 Server 可以包含多个 Service,它负责管理和协调所有的 Service 组件。
- 作用:在启动时,Server 会加载配置文件,初始化各个 Service 组件,并启动相应的线程来处理客户端请求。当关闭 Tomcat 时,Server 会负责关闭所有的 Service 组件,释放资源。
- Service
- 定义:是 Server 中的一个逻辑组件,包含一个或多个 Connector 和一个 Engine。Service 的作用是将 Connector 接收到的请求转发给 Engine 进行处理。
- 作用:它将网络连接和请求处理的功能进行了分离,使得 Connector 专注于接收客户端的请求,而 Engine 专注于处理请求。一个 Server 中可以有多个 Service,每个 Service 可以有不同的配置,以满足不同的应用需求。
- Connector
- 定义:负责接收客户端的请求和发送响应。常见的 Connector 有 HTTP Connector 和 AJP Connector。HTTP Connector 用于处理 HTTP 请求,AJP Connector 用于与其他 Web 服务器(如 Apache)进行通信。
- 作用:HTTP Connector 监听指定的端口,接收客户端的 HTTP 请求,并将请求封装成相应的对象,然后将其传递给 Engine 进行处理。AJP Connector 则是为了与其他 Web 服务器集成,将接收到的 AJP 协议请求转换为 Tomcat 内部可以处理的请求格式。
- Engine
- 定义:是 Service 中的核心组件,负责处理 Connector 转发过来的请求。Engine 可以包含多个 Host。
- 作用:Engine 会根据请求的主机名和上下文路径,将请求转发给相应的 Host 和 Context 进行处理。它还可以进行一些全局的请求处理,如日志记录、错误处理等。
- Host
- 定义:代表一个虚拟主机,通常对应一个域名。一个 Host 可以包含多个 Context。
- 作用:Host 负责管理和部署多个 Web 应用程序(Context),它会根据请求的主机名来确定将请求转发给哪个 Context 进行处理。例如,在一个 Tomcat 服务器上部署了多个网站,每个网站对应一个不同的域名,这些域名就可以配置为不同的 Host。
- Context
- 定义:代表一个 Web 应用程序,每个 Context 都有一个唯一的路径。Context 包含了 Web 应用程序的所有资源,如 Servlet、JSP、静态文件等。
- 作用:Context 负责加载和管理 Web 应用程序的资源,处理客户端的请求。当接收到请求时,Context 会根据请求的路径和配置,将请求转发给相应的 Servlet 或 JSP 进行处理。
- 要点
- 分层架构优势:Tomcat 的结构采用了分层架构,各个组件之间职责明确,便于扩展和维护。例如,如果需要支持新的协议,可以通过添加新的 Connector 组件来实现;如果需要部署新的 Web 应用程序,只需要在相应的 Host 中添加新的 Context 即可。
- 配置灵活性:可以通过配置 Tomcat 的
server.xml
文件来调整各个组件的参数,如 Connector 的端口号、Engine 的默认主机等。通过合理的配置,可以优化 Tomcat 的性能,满足不同的应用需求。
- 应用
- 集群和负载均衡:Tomcat 支持集群和负载均衡功能,可以通过配置多个 Tomcat 实例来实现高可用和高性能的 Web 应用程序。在集群环境中,多个 Tomcat 实例可以共享会话信息,当一个实例出现故障时,其他实例可以继续提供服务。负载均衡器可以将客户端的请求均匀地分配到各个 Tomcat 实例上,提高系统的处理能力。
- 性能优化:可以通过调整 Tomcat 的各种参数来优化性能,如调整 Connector 的线程池大小、设置合适的缓存策略等。此外,还可以结合其他工具和技术,如 Apache HTTP Server 作为前端代理服务器,来进一步提高系统的性能和稳定性。
友情提示:本文已经整理成文档,可以到如下链接免积分下载阅读
https://download.csdn.net/download/ylfhpy/90521351
相关文章:
Java面试黄金宝典9
1. Redis 持久化机制 Redis 提供了两种主要的持久化机制:RDB(Redis Database)和 AOF(Append Only File),下面对这两种机制进行详细介绍。 RDB(Redis Database) 原理:RDB …...
【C#】WinForm自定义控件及窗体
前言 WinForm(Windows Forms)是Microsoft.NET框架中的技术,用于开发Windows桌面应用程序。它提供了一套丰富的控件和组件。通过拖放控件、编写事件处理程序等方式快速构建用户界面。 通过属性窗口定制这些控件的外观和行为。 通过数据绑定&am…...
VideoHelper 油猴脚本,重塑你的视频观看体验
VideoHelper 油猴脚本,重塑你的视频观看体验 在日常上网看视频时,你是否也被这些问题困扰:视频网站开头的广告又臭又长,找个合适的播放倍速要在一堆选项里翻半天,每次手动调音量、点全屏按钮繁琐又影响沉浸感…...
从收藏夹到知识图谱:书签管理器如何重塑你的信息获取方式?
在信息爆炸的今天,浏览器收藏夹早已沦为 “数字垃圾堆”—— 杂乱无章的网址、重复的标签、过期的链接,不仅降低效率,更成为信息焦虑的源头。智能书签管理器通过AI分类、跨平台同步、隐私保护等黑科技,重塑您的数字生活方式。书签…...
SOFABoot-07-版本查看
前言 大家好,我是老马。 sofastack 其实出来很久了,第一次应该是在 2022 年左右开始关注,但是一直没有深入研究。 最近想学习一下 SOFA 对于生态的设计和思考。 sofaboot 系列 SOFABoot-00-sofaboot 概览 SOFABoot-01-蚂蚁金服开源的 s…...
[极客大挑战 2019]Http_3.19BUUCTF练习day3(1)
BUUCTF练习day3(1)_[极客大挑战 2019]Http 打开靶场,查看源码(如果在做题时没有什么发现就查看源码) 打开Secret.php提示没有来自https://Sycsecret.buuoj.cn 添加Referer头为https://Sycsecret.buuoj.cn(提示说我们没有来自那个网址,那我们…...
golang Error的一些坑
golang Error的一些坑 golang error的设计可能是被人吐槽最多的golang设计了。 最经典的err!nil只影响代码风格设计,而有一些坑会导致我们的程序发生一些与我们预期不符的问题,开发过程中需要注意。 errors.Is判断error是否Wrap不符合预期 …...
弱网测试:全链路实战、高阶策略与自动化落地
在移动互联网时代,网络环境的不确定性成为用户体验的“隐形杀手”。弱网测试不仅是质量保障的必备环节,更是提升用户留存率和业务转化率的战略手段。 本文将从 工具链深度配置、复杂场景模拟、性能优化底层逻辑 和 自动化流水线集成 四个维度,彻底解析弱网测试的完整方法论…...
Ubuntu检查并启用 Nginx 的stream模块或重新安装支持stream模块的Nginx
stream 模块允许 Nginx 处理 TCP 和 UDP 流量,常用于负载均衡和端口转发等场景。本文将详细介绍如何检查 Nginx 是否支持 stream 模块,以及在需要时如何启用该模块。 1. 检查 Nginx 是否支持 stream 模块 首先,需要确认当前安装的 Nginx 是…...
mac brew 安装的php@7.4 打开redis扩展
1. 找到php7.4的pecl目录 一般在这个位置 cd /usr/local/Cellar/php7.4/7.4.33_8/pecl/20190902 ls 一下 有个 redis.so 于是 直接去php.ini编辑了 php.ini的路径 vim /usr/local/etc/php/7.4/php.ini 把938行添加进去 然后重启一下 php7.4 brew services restart ph…...
Redis 内存管理
Redis 内存管理 1. Redis 给缓存数据设置过期时间的作用 给缓存数据设置过期时间(TTL, Time-To-Live)有以下几个重要作用: (1) 自动释放内存 避免缓存数据无限增长,导致 Redis 内存溢出。例如,在 会话管理、短连接…...
学习CSS滤镜属性 `filter: invert()`
一、核心机制 数学原理 invert(1) 对每个像素的RGB通道执行 颜色反相计算: 新通道值 255 - 原通道值 例如 rgb(255,0,0)(纯红)会转换为 rgb(0,255,255)(青色)。 透明度处理 该滤镜会保留元素的Alpha通道(…...
网络空间安全专业发展历程及开设院校
一、专业发展历程 1. 早期探索阶段(1990年代末—2000年代初) (1)背景: 1990年代互联网进入中国,计算机病毒、黑客攻击等问题逐渐显现,社会对信息安全人才的需求开始萌芽。 (2&…...
Linux中mutex机制
在Linux中,mutex是一种用于多线程编程的同步机制,用于保护共享资源,防止多个线程同时访问或修改这些资源,从而避免竞态条件的发生。mutex 是“mutual exclusion”的缩写,意为“互斥”。 1. Mutex 的基本概念 互斥锁&…...
Web网页
1.结构与表现分离 HTML用于结构 css用于表现,增加了丰富的样式效果,极大满足了开发者的需求 选择器;用于指定css样式作用的html对象{}选择某个属性 p标签 color;本颜色 font-size:子属性 字大小 font-family;字体 font-…...
Redis 在windows下的下载安装与配置
参考链接:https://developer.aliyun.com/article/1395346 下载 Redis 访问 Redis 下载地址:https://github.com/tporadowski/redis/releases 下载 Redis 时,你可以选择 ZIP 包或 MSI 安装: ZIP包:需要手动解压、初始化、配置和…...
基于随机森林回归预测葡萄酒质量
基于随机森林回归预测葡萄酒质量 1.作者介绍2.随机森林算法与数据集介绍2.1定义2.2核心思想2.3主要步骤2.4数据集介绍 3.算法实现3.1数据加载与探索3.2数据可视化3.3数据预处理(标准化、划分训练/测试集)3.4模型训练与优化(随机森林回归 超参…...
在大数据开发中ETL是指什么?
hello宝子们...我们是艾斯视觉擅长ui设计和前端数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩! 在数字经济时代,数据已成为企业最核心的资产。然而,分散在业务系统、日志文件…...
Centos操作系统安装及优化
Centos操作系统安装及优化 零、环境概述 主机名 centos版本 cpu 内存 Vmware版本 ip地址 test CentOS Linux release 7.6.1810 (Core) 2C 2G 15.5.1 10.0.0.10 一、介质下载 1、7.6版本下载 CentOS7.6标准版下载链接: https://archive.kernel.org/centos-vault/7.6.1810/i…...
2025年03月10日人慧前端面试(外包滴滴)
目录 普通函数和箭头函数的区别loader 和 plugin 的区别webpack 怎么实现分包,为什么要分包webpack 的构建流程变量提升react 开发中遇到过什么问题什么是闭包vue 开发中遇到过什么问题vue中的 dep 和 watcher 的依赖收集是什么阶段什么是原型链react setState 是同…...
NLP高频面试题(十)——目前常见的几种大模型架构是啥样的
深入浅出:目前常见的几种大模型架构解析 随着Transformer模型的提出与发展,语言大模型迅速崛起,已经成为人工智能领域最为关注的热点之一。本文将为大家详细解析几种目前常见的大模型架构,帮助读者理解其核心差异及适用场景。 1…...
【数据结构】栈(Stack)、队列(Queue)、双端队列(Deque) —— 有码有图有真相
目录 栈和队列 1. 栈(Stack) 1.1 概念 1.2 栈的使用(原始方法) 1.3 栈的模拟实现 【小结】 2. 栈的应用场景 1、改变元素的序列 2、将递归转化为循环 3、逆波兰表达式求值 4、括号匹配 5、出栈入栈次序匹配 6、最小栈…...
windows清除电脑开机密码,可保留原本的系统和资料,不重装系统
前言 很久的一台电脑没有使用了,开机密码忘了,进不去系统 方法 1.将一个闲置u盘设置成pe盘(注意,这个操作会清空原来u盘的数据,需要在配置前将重要数据转移走,数据无价,别因为配置这个丢了重…...
NLP高频面试题(九)——大模型常见的几种解码方案
大模型常见的几种解码方案 在自然语言生成任务中,如何从模型生成的概率分布中选择合适的词汇,是影响文本质量的关键问题。常见的解码方法包括贪心搜索(Greedy Search)、束搜索(Beam Search)、随机采样&…...
「低延迟+快速集成:Amazon IVS如何重塑实时互动视频体验?」
引言:实时视频的爆发与开发痛点 随着直播电商、在线教育、云游戏的兴起,实时视频互动成为用户体验的核心。但自建视频服务面临高成本、高延迟、运维复杂等挑战。Amazon IVS(Interactive Video Service)作为亚马逊云科技推出的全托…...
JVM垃圾回收笔记02-垃圾回收器
文章目录 前言1.串行(Serial 收集器/Serial Old 收集器)Serial 收集器Serial Old 收集器相关参数-XX:UseSerialGC 2.吞吐量优先(Parallel Scavenge 收集器/Parallel Old 收集器)Parallel Scavenge 收集器Parallel Old 收集器相关参数-XX:UseParallelGC ~ -XX:UseParallelOldGC-…...
Agent Team 多智能体系统解析
引言 在人工智能技术高速发展的今天,"多智能体协作系统"(Agent Team)正成为突破效率瓶颈的关键技术。与传统的单体AI不同,这种由多个专业化智能体组成的协同网络,通过分工协作和动态调整,展现出…...
LintCode第1712题 - 和相同的二元子数组
描述 在由若干 0 和 1 组成的数组 A 中,有多少个和为 S 的非空子数组 样例 1: 输入:A [1,0,1,0,1], S 2 输出:4 解释: 如下面黑体所示,有 4 个满足题目要求的子数组: [1,0,1] [1,0,1] [1,0,1,0] [0,1,…...
网络HTTPS协议
Https HTTPS(Hypertext Transfer Protocol Secure)是 HTTP 协议的加密版本,它使用 SSL/TLS 协议来加密客户端和服务器之间的通信。具体来说: • 加密通信:在用户请求访问一个 HTTPS 网站时,客户端&#x…...
0322-数据库、前后端
前端 <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>Insert title here</title> <script srcjs/jquery-3.7.1.min.js></script> <script> //jquaryajax发起请求 //传参形式不同 post用data{}…...
六十天前端强化训练之第二十六天之Vue Router 动态路由参数大师级详解
欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗,谢谢大佬! 目录 一、知识讲解 1. Vue Router 核心概念 2. 动态路由参数原理 3. 参数传递方案对比 二、核心代码示例 1. 完整路由配置 2. 参数接收组件 3. 导航操作示例 三、实现效果示…...
L2TP实验
一、拓朴图 二、实验配置 1.基础配置 1.1接口IP及服务配置 [PPPoE Client]interface GigabitEthernet 0/0/0 [PPPoE Client-GigabitEthernet0/0/0]service-manage all permit [NAS]interface GigabitEthernet 0/0/0 [NAS-GigabitEthernet0/0/0]ip add 192.168.0.2 24 [NAS-Gi…...
uni-app——数据缓存API
数据缓存API 在 uni-app 开发中,数据缓存 API 起着重要作用,它能够将需要的数据保存到本地,同时也提供了获取本地缓存数据、移除缓存数据以及清理缓存数据的功能。在实际项目里,数据缓存 API 常被用于存储会员登录状态信息、购物…...
不做颠覆者,甘为连接器,在技术叠层中培育智能新物种
--- 一、技术融合的必然:从“非此即彼”到“兼容共生” 当大模型的热浪撞上传统IT的礁石,企业智能化的真相浮出水面: 新旧技术的“量子纠缠”:MySQL与向量数据库共享数据总线,规则引擎与大模型共处决策链路 需求进…...
尝试在软考65天前开始成为软件设计师-计算机网络
OSI/RM 七层模型 层次名功能主要协议7应用层实现具体应用功能 FTP(文件传输)、HTTP、Telnet、 POP3(邮件)SMTP(邮件) ------- DHCP、TFTP(小文件)、 SNMP、 DNS(域名) 6表示层数据格式,加密,压缩.....5会话层建立,管理&终止对话4传输层端到端连接TCP,UDP3网络层分组传输&a…...
JDBC 连接字连接 KingbaseES支持主从负载均衡参数说明。
JDBC 连接字符串是用于连接 KingbaseES(人大金仓数据库)的,支持主从负载均衡。让我们逐一解析各个参数的作用,并探讨如何调整到最优。 参数解析 jdbc:kingbase8://10.10.14.19:54321/xxx_onlinejdbc:kingbase8://:指定…...
OpenCV旋转估计(4)生成一个字符串表示的匹配图函数 matchesGraphAsString()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 matchesGraphAsString 函数是OpenCV库中的一部分,位于 cv::detail 命名空间下。这个函数的主要作用是生成一个字符串表示的匹配图&am…...
扣子平台知识库不能上传成功
扣子平台知识库不能上传成功 目录 扣子平台知识库不能上传成功查看模板复制头部到自己的excel中json数据转为excel或者csv(一定使用excel,csv总是报错) 查看模板复制头部到自己的excel中 json数据转为excel或者csv(一定使用excel&…...
CIFAR10 数据集自定义处理方法
CIFAR10 数据集自定义处理方法 可以自定义训练集和测试集中不同类别的样本的数量。可用于模拟类别不平衡问题,存在混淆数据问题。 import torch import torchvision.datasets as dsets import torchvision.transforms as transforms from torch.utils.data import…...
当发现提示少文件,少目录时时,external.css的内容
[ERROR ]17:30:44| Loger: 处理群消息时发生错误:[Errno 2] No such file or directory: \\venv\\lib\\site-packages\\ncatbot\\utils\\template/external.css venv\\lib\\site-packages\\ncatbot\\utils\\template/external.css ["https://stackpath.boots…...
OpenHarmony 开源鸿蒙北向开发——linux使用make交叉编译第三方库
这几天搞鸿蒙,需要编译一些第三方库到鸿蒙系统使用。 头疼死了,搞了一个多星期总算搞定了。 开贴记坑。 一、SDK下载 1.下载 在linux下使用命令 wget https://cidownload.openharmony.cn/version/Master_Version/OpenHarmony_5.1.0.54/20250313_02…...
【计算机网络】网络简介
文章目录 1. 局域网与广域网1.1 局域网1.2 广域网 2. 路由器和交换机3. 五元组3.1 IP和端口3.2 协议3.3 协议分层 4. OSI七层网络协议5. TCP/IP五层模型5.1 TCP/IP模型介绍5.2 网络设备所在分层 6. 封装与分用6.1 数据包的称谓6.2 封装6.3 分用 1. 局域网与广域网 1.1 局域网 …...
k8s--集群内的pod调用集群外的服务
关于如何让同一个局域网内的Kubernetes服务的Pod访问同一局域网中的电脑上的服务。 可能的解决方案包括使用ClusterIP、NodePort、Headless Service、HostNetwork、ExternalIPs,或者直接使用Pod网络。每种方法都有不同的适用场景,需要逐一分析。 例如&…...
高性能边缘计算网关-高算力web组态PLC网关
高性能EG8200Pro边缘计算算力网关-超强处理能力 样机申请测试:免费测试超30天(https://www.iotrouter.com/prototype/) 产品主要特点和特色功能 设备概览与连接能力 设备型号:EG8200P。主要特点: 支持多种工业协议&am…...
计算机视觉总结
以下是针对上述问题的详细解答,并结合代码示例进行说明: 1. 改进YOLOv5人脸检测模块,复杂光照场景准确率从98.2%提升至99.5% 优化具体过程: 光照补偿:在数据预处理阶段,采用自适应光照补偿算法,对图像进行实时增强,以减少光照变化对人脸检测的影响。数据增强:在训练…...
【Golang】defer与recover的组合使用
在Go语言中,defer和recover是两个关键特性,通常结合使用以处理资源管理和异常恢复。以下是它们的核心应用场景及使用示例: 1. defer 的应用场景 defer用于延迟执行函数调用,确保在函数退出前执行特定操作。主要用途包括ÿ…...
Beyond Compare 4注册激活方法
Beyond Compare 4 注册码 --- BEGIN LICENSE KEY --- H1bJTd2SauPv5Garuaq0Ig43uqq5NJOEw94wxdZTpU-pFB9GmyPk677gJ vC1Ro6sbAvKR4pVwtxdCfuoZDb6hJ5bVQKqlfihJfSYZt-xVrVU270Ja hFbqTmYskatMTgPyjvv99CF2Te8ecYs2SPxyZAF0YwOCNOWmsyqN5y9t q2Kw2pjoiDs5gIH-uw5U49JzOB6otS7kT…...
[C++游戏开发基础]:构造函数浅析,8000+字长文
构造函数 构造函数是一种特殊的成员函数,在创建非聚合类类型对象后会自动被调用。当定义一个非聚合类类型对象时,编译器会检查是否能找到一个可以访问的构造函数,该构造函数与调用者提供的初始化值(如果有的情况下)相匹配。 如果找到一个可访问的匹配构造函数,将为…...
【Go】切片
知识点关键概念切片声明var slice []int初始化切片slice : []int{1,2,3}make() 创建切片make([]int, len, cap)获取长度和容量len(slice), cap(slice)追加元素slice append(slice, value)切片截取slice[start:end](返回子切片)拷贝切片copy(dest, src)&…...
MySQL 设置允许远程连接完整指南:安全与效率并重
一、为什么需要远程连接MySQL? 在分布式系统架构中,应用程序与数据库往往部署在不同服务器。例如: Web服务器(如NginxPHP)需要连接独立的MySQL数据库数据分析师通过BI工具直连生产库多服务器集群间的数据同步 但直接…...