社区网站7.10 优化网站的性能

本文介绍了社区网站性能优化的方法,重点讨论了本地缓存(如Ehcache、Guava、Caffeine)和分布式缓存(如MemCache、Redis)的使用,以及如何构建多级缓存策略防止缓存雪崩。通过示例展示了Caffeine的集成步骤,并使用JMeter进行性能测试,结果显示启用Caffeine后,首页吞吐量显著提升,性能得到显著改善。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  本地缓存
(1)将数据缓存在应用服务器上,性能最好。
(2)常用缓存工具:Ehcache、Guava、Caffein等。
  分布式缓存
(1)将数据缓存在NoSQL数据库上,跨服务器。
(2)常用缓存工具:MemCache、Redis等。
  多级缓存
(1)>一级缓存(本地缓存)>二级缓存(分布式缓存)>DB
(2)避免缓存雪崩(缓存失效,大量请求直达DB,提高系统的可用性。
  本地缓存和redis缓存的示意图(本地缓存更普适,效率更高)
本地缓存比redis缓存效率高
缓存访问流程
  在github上搜Caffeine,第一个就是。在mvn库里搜caffeine,把com.github.ben-manes.caffeine粘贴到pom.xml。在application-properties里添加

# caffeine
# 15页,不一定是前15页,例如缓存热门帖子的15页,没必要缓存所有(浪费内存空间)
caffeine.posts.max-size=15
# 3分钟过期
caffeine.posts.expire-seconds=180

  在DiscussPostService类里,添加

	@Value("${caffeine.posts.max-size}")
    private int maxSize;

    @Value("${caffeine.posts.expire-seconds}")
    private int expireSeconds;

	//Caffeine核心接口:Cache,子接口LoadingCache(排队等),AsyncLoadingCache(异步,支持并发,不着急返回)

    //帖子列表缓存
    private LoadingCache<String,List<DiscussPost>> postListCache;

    // 帖子总数缓存
    private LoadingCache<Integer, Integer> postRowsCache;

	@PostConstruct
    public void init(){
        //初始化帖子列表缓存
        postListCache = Caffeine.newBuilder()    //先用caffine
                .maximumSize(maxSize)
                .expireAfterWrite(expireSeconds, TimeUnit.SECONDS)
                .build(new CacheLoader<String, List<DiscussPost>>() {
                    @Nullable
                    @Override
                    public List<DiscussPost> load(@NonNull String key) throws Exception {
                        if(key==null||key.length()==0){
                            throw new IllegalArgumentException("参数错误!");
                        }

                        String[] params = key.split(":");
                        if(params==null||params.length!=2){
                            throw new IllegalArgumentException("参数错误!");
                        }

                        int offset = Integer.valueOf(params[0]);
                        int limit = Integer.valueOf(params[1]);

                        //若有二级缓存:Redis -> mysql,而这里是直接就访问数据库了

                        logger.debug("load post list from DB.");
                        return discussPostMapper.selectDiscussPosts(0,offset,limit,1);
                        //只缓存不针对用户的所有帖子,且是“最热”模式
                    }
                });
        //初始化帖子总数缓存
        postRowsCache = Caffeine.newBuilder()
                .maximumSize(maxSize)
                .expireAfterWrite(expireSeconds, TimeUnit.SECONDS)
                .build(new CacheLoader<Integer,Integer>() {
                    @Nullable
                    @Override
                    public Integer load(@NonNull Integer key) throws Exception {
                        logger.debug("load post rows from DB.");
                        return discussPostMapper.selectDiscussPostRows(key);
                    }
                });
    }

并修改findDiscussPosts和findDiscussPostRows方法为

public List<DiscussPost> findDiscussPosts(int userId,int offset,int limit,int orderMode) {
        if(userId==0&&orderMode==1){
            return postListCache.get(offset+":"+limit);
        }

        logger.debug("load post list from DB.");
        return discussPostMapper.selectDiscussPosts(userId,offset,limit,orderMode);
    }

    public int findDiscussPostRows(int userId) {
        if(userId==0){
            return postRowsCache.get(userId);
        }

        logger.debug("load post rows from DB.");

        return discussPostMapper.selectDiscussPostRows(userId);
    }

  新建 CaffeineTests类,

@Test
    public void initDataForTest(){  //这个先初始化好
        for(int i=0;i<300000;i++){
            DiscussPost post = new DiscussPost();
            post.setUserId(111);
            post.setTitle("互联网求职暖春计划");
            post.setContent("今年的就业形势,确实不容乐观,21届要加油啊!");
            post.setCreateTime(new Date());
            post.setScore(Math.random()*2000);
            postService.addDiscussPost(post);
        }
    }

    
    @Test
    public void testCache(){
        System.out.println(postService.findDiscussPosts(0,0,10,1));
        System.out.println(postService.findDiscussPosts(0,0,10,1));
        System.out.println(postService.findDiscussPosts(0,0,10,1));
        System.out.println(postService.findDiscussPosts(0,0,10,0));//不走缓存
    }

  到jmeter.apache.org官网下载JMeter二进制包,解压缩即能用。进入安装目录的bin,双击jmeter.bat即能使用。
  首先添加线程组
添加线程组
  设置线程组的名字、线程数量、是否无限循环、明确线程生命时间。
设置线程组
  添加取样器
添加取样器
  设置取样器
设置取样器
  添加统一随机定时器
添加统一随机定时器
  设置随机定时器的随机时间间隔为1000(即0~1000)
设置随机时间间隔
  添加聚合报告监听器
添加聚合报告监听器
  点击开始,弹出窗口中设置聚合报告的保存路径和文件名字,开始测试。看到不加Caffeine缓存访问首页的吞吐量为12.9/sec。
不加caffeine的首页
  把caffeine加上,先清理掉上次的聚合报告,再次点击绿色箭头开始测试。
清理按钮
  可以看到,把caffeine加上之后首页的吞吐量为193.9/sec,性能提升不少。另外,对于性能欠佳的服务器,因为访问请求压力大,响应不过来的时候,可能会报异常。
加上caffeine之后的吞吐量

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值