zoukankan      html  css  js  c++  java
  • 单例模式在生产环境jedis集群中的应用

    背景:不久前单位上线一款应用,上了生产环境之后,没过多久,便吃掉了服务器所有的内存,最后导致网站服务挂了。

    在解决了这一问题之后,我发现这其实是典型的一单例模式,现分享一下。

    之前存在问题的老代码如下:

    这是导致问题所在的那个关键方法

    public synchronized static JedisCluster getJedisCluster() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(MAX_ACTIVE);
        config.setMaxIdle(MAX_IDLE);
        config.setMaxWaitMillis(MAX_WAIT);
        config.setTestOnBorrow(TEST_ON_BORROW);
        
        // 集群模式
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        Set<HostAndPort> nodes = new HashSet<HostAndPort>();
    
        HostAndPort hostAndPort1 = new HostAndPort("服务器地址1", 端口1);
        HostAndPort hostAndPort2 = new HostAndPort("服务器地址2", 端口2);
        HostAndPort hostAndPort3 = new HostAndPort("服务器地址3", 端口3);
    
        nodes.add(hostAndPort1);
        nodes.add(hostAndPort2);
        nodes.add(hostAndPort3);
    
        JedisCluster jedisCluster = new JedisCluster(nodes, poolConfig);
        
        return jedisCluster;
    }

    以上这段代码是有问题的,大家看出来了吗?

    问题在于,虽然方法声明为synchronized static,但是在并发多线程的情况下,并不能保证每个用户线程只生成一个JedisCluster的实例。

    这样就会导致每个线程都会创建jedisCluster的实例,就会消耗内存,而且这块内存又没有被及时地释放掉,导致多用户并发以后,快速吃光了服务器的内存。

    解决方法就是使用单例模式,把JedisCluster作为static的类成员,且使用懒汉单例模式,代码如下:

    public class OuterClass{
        ...
        private static JedisCluster jedisCluster = null;
        ...
    
        public synchronized static JedisCluster getJedisCluster() {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxTotal(MAX_ACTIVE);
            config.setMaxIdle(MAX_IDLE);
            config.setMaxWaitMillis(MAX_WAIT);
            config.setTestOnBorrow(TEST_ON_BORROW);
            
            // 集群模式
            JedisPoolConfig poolConfig = new JedisPoolConfig();
            Set<HostAndPort> nodes = new HashSet<HostAndPort>();
    
            HostAndPort hostAndPort1 = new HostAndPort("服务器地址1", 端口1);
            HostAndPort hostAndPort2 = new HostAndPort("服务器地址2", 端口2);
            HostAndPort hostAndPort3 = new HostAndPort("服务器地址3", 端口3);
    
            nodes.add(hostAndPort1);
            nodes.add(hostAndPort2);
            nodes.add(hostAndPort3);
    
            // 只有当jedisCluster为空时才实例化
            if (jedisCluster == null) {
                jedisCluster = new JedisCluster(nodes, poolConfig);
            }
    
            return jedisCluster;
        }
    }

    这样就会保证即使在高并发的环境下,所有用户线程还是只会拥有一个JedisCluster的实例。

  • 相关阅读:
    设计模式:解释器模式???
    设计模式:访问者模式(Visitor)
    设计模式:享元模式(Flyweight)
    NHibernate
    设计模式:中介者模式(Mediator)
    设计模式:职责链模式(Chain Of Responsibility)
    反射
    设计模式:命令模式(Command)
    设计模式:桥连模式(Bridge)
    设计模式:组合模式(Composite)
  • 原文地址:https://www.cnblogs.com/davidgu/p/6277924.html
Copyright © 2011-2022 走看看