llccing/FrontEnd

Jhipster Cache

Opened this issue · 0 comments

Background

参与 iCluster Web 项目一年的时间,80%时间在写前端Angular,20%时间在边学习边写Java,剩下10%也在思考和设计功能。

Jhipster 支持6种缓存

  1. Ehcache, https://www.cnblogs.com/bronya0/p/14715732.html
    1. 纯 Java 的进程内缓存,直接在 JVM虚拟机中缓存,速度非常快。缓存有两级,内存储存完自动存到磁盘上。数据可持久化到磁盘,VM(虚拟机)重启后数据恢复。
    2. 速度超过 Redis, Redis 通过 socket 访问缓存数据,效率没 Ehcache 高。
    3. 在分布式和集群情况下的缓存恢复、数据缓存的支持不是很好。
    4. 如果是大型缓存,存在缓存共享、分布式部署,建议用 Redis。
    5. 可以和 Redis 共同使用。
  2. Caffeine, https://ghh3809.github.io/2021/05/31/caffeine/
    1. Java 高性能的本地缓存库。缓存命中率已接近最优值。
    2. 支持并发,支持O(1)时间复杂度的数据存取。
    3. 提供以下功能
      1. 自动加载条目到缓存中,支持异步加载
      2. 根据频率和最近访问情况,支持将缓存数量设为移除策略
      3. 根据最近访问和修改时间,支持将时间设为移除策略
      4. 过期条目再次访问时异步加载
      5. key自动包装为弱引用
      6. value自动包装为弱引用/软引用
      7. 条目移除通知
      8. 对外部资源的写入
      9. 累计缓存使用统计
  3. Hazelcast, https://www.bianchengbaodian.com/hazelcast
    1. 分布式内存数据网格,用于存储键值对的分布式缓存、用于创建和使用分布式数据结构的构造,以及在集群中的节点之间分配计算和查询的方法。
    2. 支持多种数据结构,如锁、信号量、队列、列表等。
    3. 快速R/W访问
    4. 高可用性,支持跨机器分发数据以及额外的备份支持。
    5. 高性能,提供了可用于在多个工作机器之前分配负载/计算/查询的构造。
    6. 易于使用,hazelcast 实现并扩展了许多 java.util.concurrent 结构,使它非常容易使用和与代码集成。
    7. 与 Redis 相比
      1. 开始就是为分布式环境构建,而Redis开始作为单机缓存。
      2. Simple cluster scale in/out。维护添加或删除节点的集群非常简单。
      3. 支持故障转移所需的资源更少。Redis 主从节点,hazelcast所有节点平等。
      4. 简单分布式计算。hazelcast 提供了一个简单的接口来将代码发送到数据以进行并行处理,减少在线数据传输。Redis 也支持,但是需要需要 Lua 脚本。
  4. Infinispan, https://www.infoq.cn/article/infinispan-gridfs
    1. Infinispan, 是 JBoss Cache 缓存框架的后续项目,是一个开源的数据网格平台,用于访问分布式状态的集群节点。
  5. Memcached, https://www.cnblogs.com/davidesun/p/12770114.html
    1. 自由开源,高性能,分布式内存键值对缓存系统,用来存储小块的任意数据(字符串、对象),可以是数据库调用、API 调用或者是页面渲染的结果。
    2. 协议简单,使用文本协议,使用换行符作为命令结束
    3. 基于 libevent 的事件处理
    4. 内置内存存储方式
    5. 使用客户端哈希的不互相通信的方式。
    6. 和 Redis 比较如下,http://www.yunweipai.com/35551.html
  6. Redis, https://www.yiibai.com/redis/redis_quick_guide.html
    1. 开源,高级的键值存储解决方案
      1. Redis 将其数据库完全保存在内存中,仅使用磁盘进行持久化。
      2. Redis 提供相对丰富的数据类型
      3. Redis 可以将数据复制到任意数量的从机中。
    2. 优点
      1. 异常快。每秒可以执行11万次SET操作,每秒可以执行81000次的GET操作。
      2. 支持丰富的数据类型。列表,集合,排序集和散列等
      3. 操作具有原子性。所有操作都是原子操作,确保了两个客户端并发访问,Redis 服务器能够接收到新的值。
      4. 多实用工具。如缓存,消息队列(Redis本地支持发布/订阅);应用中任何短期数据,如会话,网页命中计数等。
    3. 竞品比较
      1. 包含更多复杂数据类型
      2. 内存数据库,实现非常高的读写速度。
      3. 复杂数据结构和内存中存储表示更容易操作。

项目分析

import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.io.Serializable;

@CacheConfig(cacheNames = {"replGroupsCaches"})
@Service
public class ReplGroupsCacheService implements Serializable {
    private final static Logger logger = LoggerFactory.getLogger(ReplGroupsCacheService.class);
    private static final long serialVersionUID = -2433804034194454964L;
    public final static String REPLGROUPSCACHE = "replgroups";

		// 这里的 #clusterId 是从参数取出来的值,
		// 这样key/value就和cluster绑定在一起了,是个聪明的做法。
		// 猜测这里使用 @Cacheable 注解后,response值会被自动缓存。
    @Cacheable(cacheNames="replgroups", key="#clusterId")
    public IcAgentService.GetReplicationGroupsResponse getCachedReplGroups(String clusterId, ICAgentServiceGrpc.ICAgentServiceBlockingStub agentStub) {
        Empty request = Empty.newBuilder().build();
        IcAgentService.GetReplicationGroupsResponse response;
        try {
            response = agentStub.getReplicationGroups(request);
        } catch (StatusRuntimeException e) {
            logger.error("getReplGroups RPC call failed: {}, {}", e.getStatus(), e.getMessage());
            Status status = e.getStatus();
            logger.debug("get groups gRPC failed: {}, {}", status.getCode(), status.getDescription());
            throw new GetReplicationGroupsException(status.getDescription());
        }

        return response;
    }
}

iCluster 中缓存使用的方式可能有些繁琐,暂时是这么觉得。待研究几个 Jhipster Redis best practise 后再回头看此结论是否能站住脚。

Summary

行文到此,初步发现项目中用的是 Redis,然后有一个 Groups 的使用例子。基于自己目前的认知,觉得使用方式还是不够简洁。后续在了解更多例子后,再看此结论是否能站住脚。