单例模式在生产环境jedis集群中的应用

简介: 背景:不久前单位上线一款应用,上了生产环境之后,没过多久,便吃掉了服务器所有的内存,最后导致网站服务挂了。   在解决了这一问题之后,我发现这其实是典型的一单例模式,现分享一下。 之前存在问题的老代码如下: 这是导致问题所在的那个关键方法 public synchronized sta...

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

 

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

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

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

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的实例。

 

目录
相关文章
|
2月前
|
NoSQL Linux Redis
06- 你们使用Redis是单点还是集群 ? 哪种集群 ?
**Redis配置:** 使用哨兵集群,结构为1主2从,加上3个哨兵节点,总计分布在3台Linux服务器上,提供高可用性。
411 0
|
10月前
|
缓存 运维 NoSQL
Redis在生产环境中是怎么部署的?
Redis在生产环境中是怎么部署的?
124 0
|
10天前
|
Java Redis 数据安全/隐私保护
Redis14----Redis的java客户端-jedis的连接池,jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,最好用jedis连接池代替jedis,配置端口,密码
Redis14----Redis的java客户端-jedis的连接池,jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,最好用jedis连接池代替jedis,配置端口,密码
|
2月前
|
缓存 NoSQL Java
使用Redis进行Java缓存策略设计
【4月更文挑战第16天】在高并发Java应用中,Redis作为缓存中间件提升性能。本文探讨如何使用Redis设计缓存策略。Redis是开源内存数据结构存储系统,支持多种数据结构。Java中常用Redis客户端有Jedis和Lettuce。缓存设计遵循一致性、失效、雪崩、穿透和预热原则。常见缓存模式包括Cache-Aside、Read-Through、Write-Through和Write-Behind。示例展示了使用Jedis实现Cache-Aside模式。优化策略包括分布式锁、缓存预热、随机过期时间、限流和降级,以应对缓存挑战。
|
2月前
|
NoSQL Java Redis
springboot之RedisTemplate的访问单机,哨兵,集群模式
以上是配置RedisTemplate以连接到单机、哨兵和集群模式的示例。在实际应用中,还可以根据需求配置连接池、序列化方式、超时等其他参数。
91 0
|
2月前
|
存储 负载均衡 NoSQL
Redis的集群模式是什么?它的优点和缺点是什么?
Redis的集群模式是什么?它的优点和缺点是什么?
77 0
|
NoSQL 算法 Java
Redis进阶-JedisCluster初始化 & 自动管理连接池中的连接 _ 源码分析
Redis进阶-JedisCluster初始化 & 自动管理连接池中的连接 _ 源码分析
486 0
|
存储 NoSQL Java
Redis(三十)- Redis集群操作和故障恢复&集群的Jedis开发
上一篇文章我们介绍了集群的基本概念,以及如何搭建一个简单的Redis集群。Redis(二十九)- Redis集群的介绍以及搭建,这篇文章我们接着来学习Redis集群。
215 0
Redis(三十)- Redis集群操作和故障恢复&集群的Jedis开发
|
NoSQL 测试技术 Redis
Redis多实例部署
测试环境中经常使用多实例,需要指定不同实例的相应的端口,配置文件,日志文件等相关配置
154 0
Redis多实例部署