我的目标是在 Spring Boot 启动时在内存中存储一堆 uniqueId(大约 500k)。
尝试在这里探索我的选择。
我可以将 uniqueId 存储在像 HashSet 这样的数据结构中吗?所以这个HashSet会从spring boot初始化开始读取。
使用像 h2 或 sqllite 这样的内存数据库怎么样?
我觉得选项 1 更容易实现,它的依赖性更少,也可以节省一些内存。不确定选项 1 是否存在任何潜在问题。
非常感谢任何其他可行的选择。
谢谢!
在内存中存储 500k 个唯一 ID 并不是一个好主意,即使现在资源看起来很丰富。应该有效地使用内存,特别是对于像这样的只读数据。在启动时加载所有内容会带来不必要的延迟,并且随着时间的推移,JVM 调整将变得痛苦,尤其是在扩展时。这种设计将您锁定在一个僵化、脆弱的架构中,使未来的更改(例如跨多个实例的扩展)变得令人头痛。
更好的解决方案:不要将所有数据加载到内存中,而是使用 Redis 作为内存中的数据存储。 Redis 非常适合像您这样的快速查找,并且专为并发访问而构建。借助 Spring Boot 3.3.3 和 Java 21,通过 Spring Data Redis 使用 Redis 可以轻松集成,从而实现快速设置和高效查询。
添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
将此添加到 application.properties:
spring.redis.host=localhost
spring.redis.port=6379
也许可以做这样的事情:
@Autowired
private RedisTemplate<String, String> redisTemplate;
public void storeUniqueIds(Set<String> uniqueIds) {
redisTemplate.opsForSet().add("uniqueIds", uniqueIds.toArray(new String[0]));
}
public boolean existsInSet(String id) {
return redisTemplate.opsForSet().isMember("uniqueIds", id);
}
Redis 将处理并发性,提供恒定时间查找,并允许您的应用程序轻松跨实例扩展,而不会占用堆内存。另外,它是为像您这样的大量读取操作而构建的。
如果您决定犯这个错误并坚持使用内存存储,您可以将 H2 与基于文件的存储解决方案结合使用,以避免每次应用程序重新启动时重新加载数据(不过,使用文件,您'它们不再真正存在于内存中)。
出发:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
道具:
spring.datasource.url=jdbc:h2:file:./data/uniqueIds
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.h2.console.enabled=true
一些代码:
@Autowired
private JdbcTemplate jdbcTemplate;
public boolean idExists(String id) {
String query = "SELECT COUNT(*) FROM ids WHERE id = ?";
return jdbcTemplate.queryForObject(query, new Object[]{id}, Integer.class) > 0;
}
但是,如果您走这条路,您就可以有效地管理数据库,因此将其存储在“内存中”的说法不再有效。 Redis 仍然更适合您的使用场景,提供更快的查找、真正的内存性能和更好的可扩展性。