• J2CACHE 两级缓存框架


    概述

    缓存框架我们有ehcache 和 redis 分别是 本地内存缓存和 分布式缓存框架。在实际情况下如果单台机器 使用ehcache 就可以满足需求了,速度快效率高,有些数据如果需要多台机器共享这个时候怎么办呢,我们需要通过redis,将缓存存放到redis上面。

    这也会导致一个问题,因为所有的请求都会到redis读取,当大量的读取会导致大量的网络流量,因此网络流量会成为访问的瓶颈。

    J2CACHE就是解决这个问题而生的,缓存分为两级

    L1: 进程内缓存(caffeineehcache)

    L2: Redis/Memcached 集中式缓存

    数据读取流程

    读取顺序 -> L1 -> L2 

    缓存先读取L1 ,不存在则读取L2

    数据更新

    1 从数据库中读取最新数据,依次更新 L1 -> L2 ,发送广播清除某个缓存信息
    2 接收到广播(手工清除缓存 & 一级缓存自动失效),从 L1 中清除指定的缓存信息

    测试J2CACHE

    创建一个maven 项目

    引入

    <dependency><!-- Ehcache 3.x //-->
            <groupId>org.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>3.4.0</version>
        </dependency>
        
        <dependency>
          <groupId>net.oschina.j2cache</groupId>  
          <artifactId>j2cache-core</artifactId>  
          <version>2.7.7-release</version>  
        </dependency>

    引入配置文件

    ehcache3.xml

    j2cache.properties

    这个配置文件配置如下:

    #J2Cache configuration
    
    
    #########################################
    # Cache Broadcast Method
    # values:
    # jgroups -> use jgroups's multicast
    # redis -> use redis publish/subscribe mechanism (using jedis)
    # lettuce -> use redis publish/subscribe mechanism (using lettuce, Recommend)
    # rabbitmq -> use RabbitMQ publisher/consumer mechanism
    # rocketmq -> use RocketMQ publisher/consumer mechanism
    # none -> don't notify the other nodes in cluster
    # xx.xxxx.xxxx.Xxxxx your own cache broadcast policy classname that implement net.oschina.j2cache.cluster.ClusterPolicy
    #########################################
    
    j2cache.broadcast = redis
    
    
    #########################################
    # Level 1&2 provider
    # values:
    # none -> disable this level cache
    # ehcache -> use ehcache2 as level 1 cache
    # ehcache3 -> use ehcache3 as level 1 cache
    # caffeine -> use caffeine as level 1 cache(only in memory)
    # redis -> use redis as level 2 cache (using jedis)
    # lettuce -> use redis as level 2 cache (using lettuce)
    # readonly-redis -> use redis as level 2 cache ,but never write data to it. if use this provider, you must uncomment `j2cache.L2.config_section` to make the redis configurations available.
    # memcached -> use memcached as level 2 cache (xmemcached),
    # [classname] -> use custom provider
    #########################################
    
    j2cache.L1.provider_class = ehcache3
    j2cache.L2.provider_class = redis
    
    # When L2 provider isn't `redis`, using `L2.config_section = redis` to read redis configurations
    # j2cache.L2.config_section = redis
    
    # Enable/Disable ttl in redis cache data (if disabled, the object in redis will never expire, default:true)
    # NOTICE: redis hash mode (redis.storage = hash) do not support this feature)
    j2cache.sync_ttl_to_redis = true
    
    # Whether to cache null objects by default (default false)
    j2cache.default_cache_null_object = true
    
    #########################################
    # Cache Serialization Provider
    # values:
    # fst -> using fast-serialization (recommend)
    # kyro -> using kyro serialization
    # json -> using fst's json serialization (testing)
    # fastjson -> using fastjson serialization (embed non-static class not support)
    # java -> java standard
    # [classname implements Serializer]
    #########################################
    
    j2cache.serialization = fst
    #json.map.person = net.oschina.j2cache.demo.Person
    
    #########################################
    # Ehcache configuration
    #########################################
    
    # ehcache.configXml = /ehcache.xml
    
    # ehcache3.configXml = /ehcache3.xml
    # ehcache3.defaultHeapSize = 1000
    
    
    
    #########################################
    # Redis connection configuration
    #########################################
    
    #########################################
    # Redis Cluster Mode
    #
    # single -> single redis server
    # sentinel -> master-slaves servers
    # cluster -> cluster servers (u93c1u7248u5d41u6434u64bbu53a4u7f03ue1bdu68e4u93c1u582cu7d1du6d63u8de8u6564 database = 0u951bufffd
    # sharded -> sharded servers  (u7035u55d9u721cu9286u4f79u669fu93b9ue1bcu7c31u8e47u5474u300fu9366ufffd hosts u6d93ue15fu5bdau7039u6c3eu7d1du6d93u65c7u7e5bu93bau30e6u775cu95b0u5d87u7586u93c3u72b3u6665 ; redis://user:password@127.0.0.1:6379/0u951bufffd
    #
    #########################################
    
    redis.mode = sentinel
    
    #redis storage mode (generic|hash)
    redis.storage = generic
    
    ## redis pub/sub channel name
    redis.channel = j2cache
    ## redis pub/sub server (using redis.hosts when empty)
    redis.channel.host =
    
    #cluster name just for sharded
    redis.cluster_name = mymaster
    
    ## redis cache namespace optional, default[empty]
    redis.namespace =
    
    ## connection
    # Separate multiple redis nodes with commas, such as 192.168.0.10:6379,192.168.0.11:6379,192.168.0.12:6379
    
    redis.hosts = 202.10.79.170:16001,202.10.79.170:16002,202.10.79.170:16003
    redis.timeout = 10000
    redis.password =
    redis.database = 0
    
    ## redis pool properties
    redis.maxTotal = 100
    redis.maxIdle = 10
    redis.maxWaitMillis = 5000
    redis.minEvictableIdleTimeMillis = 60000
    redis.minIdle = 1
    redis.numTestsPerEvictionRun = 10
    redis.lifo = false
    redis.softMinEvictableIdleTimeMillis = 10
    redis.testOnBorrow = true
    redis.testOnReturn = false
    redis.testWhileIdle = true
    redis.timeBetweenEvictionRunsMillis = 300000
    redis.blockWhenExhausted = false
    redis.jmxEnabled = false

        广播方式使用redis

    j2cache.broadcast = redis
    L1,L2 缓存实现方法
    j2cache.L1.provider_class = ehcache3
    j2cache.L2.provider_class = redis
    redis 使用哨兵模式进行配置。


    使用代码进行测试

    编写测试代码如下:

    读取缓存

    public static void main(String[] args) throws InterruptedException {
            
            CacheChannel cache = J2Cache.getChannel();
            while(true){
                System.out.println(cache.get("user", "name"));
                Thread.sleep(2000);
            }
        }

    这个代码会一直读取 user:name 的缓存。

    我们需要测试的是,当一个客户端设置一个 user:name 的缓存时,这个代码能反映缓存的变化。

    设置缓存:

    public static void main(String[] args) {
        
            CacheChannel cache = J2Cache.getChannel();
            cache.set("user", "name", "A");
            cache.close();
        }

    首先设置一个A的缓存。

    我们可以看到第一个代码返回的是如下情况

    [user,name,L2]=>A
    [user,name,L1]=>A
    [user,name,L1]=>A

    它会先从 redis读取,在读取本地。

    我们在设置一次:

    public static void main(String[] args) {
        
            CacheChannel cache = J2Cache.getChannel();
            cache.set("user", "name", "B");
            cache.close();
        }

    第二次我们这个name 为 B,这个时候我们可以发现:

    [user,name,L2]=>B
    [user,name,L1]=>B
    [user,name,L1]=>B

    缓存变成了B ,而且是先读取 REDIS ,在读取 EHCACHE缓存,即先读取 L2 再读取L1。

    这样我们的缓存就既能保证性能,有可以保证缓存及时被更新。

  • 相关阅读:
    13---Net基础加强
    12---Net基础加强
    11---Net基础加强
    10---Net基础加强
    09---Net基础加强
    08---Net基础加强
    07---Net基础加强
    06---Net基础加强
    05---Net基础加强
    04---Net基础加强
  • 原文地址:https://www.cnblogs.com/yg_zhang/p/10344519.html
Copyright © 2020-2023  润新知