美文网首页
SpringBoot使用Guava做内存缓存

SpringBoot使用Guava做内存缓存

作者: shiguangfeixu | 来源:发表于2018-12-30 23:01 被阅读0次

    基本原理

    • 如果某个请求需要频繁的去数据库中请求数据,当用户量较大且服务器性能较低的时候会导致服务效率低下,QPS较低


      image.png
    • 这时我们可以把这些固定的请求,先用一个线程去数据库里面查询,然后把他放入缓存中,这样后序的线程再请求的时候就会直接从缓存中取数据,从而提高了查询性能也缓解了数据库的压力


      image.png

    什么时候使用缓存

    如果你的需求满足以下条件可以使用Cahce缓存数据

    • 愿意消耗一些内存空间来提升速度
    • 预料到某些键会被查询一次以上
    • 缓存中存放的数据总量不会超过内存容量

    项目场景

    我们这里设计了一张图书信息表,用于查询,因为一般网站的主页上都会显示最新上架的一些图书,可以把这些固定的查询图书的信息放到缓存里,这里使用SpringBoot+Guava的技术方案;


    image.png

    基本配置

    pom.xml引入依赖“

    <dependency>
           <groupId>com.google.guava</groupId>
           <artifactId>guava</artifactId>
            <version>18.0</version>
     </dependency>
    

    application.yml中配置缓存大小和缓存时间

    # guava
    guava:
      cache:
        maximumSize: 10000
        expire: 15
    

    查询语句

    缓存设置

    private LoadingCache<Long, Book> booksCache = CacheBuilder.newBuilder()
                .recordStats()
                .maximumSize(1000)
                .expireAfterAccess(10, TimeUnit.DAYS)
                .build(
                        new CacheLoader<Long, Book>() {
                            @Override
                            public Book load(Long id) throws Exception {
                                List<Book> bookVOList = findAllBookById(Collections.singletonList(id));
                                if (bookVOList != null && bookVOList.size() != 0) {
                                    return bookVOList.get(0);
                                }
                                return new Book(BOOK_NAME, BOOK_AUTHOR, PUBLISH_HOUSE);
                            }
                        }
                );
    

    数据库查询请求

    public List<Book> findAllBookById(List<Long> ids) {
            List<Book> books = new ArrayList<>();
            Optional<List<Book>> booksOption = bookRepo.findAllById(ids);
            if (booksOption.isPresent()) {
                books = booksOption.get();
            }
            return books;
        }
    

    最终查询请求

    public Book fetchBookById(Long id) {
            if (id == null) {
                log.error("the id is null");
                throw new NullPointerException("the id is null");
            }
            //从缓存中获取
            try {
                Book book = booksCache.get(id);
                if (book != null) {
                    return book;
                }
            } catch (ExecutionException e) {
                log.error("take book from guava cache error, id : {}", id, e);
            }
            //从数据库中查询
            List<Book> vos = findAllBookById(Lists.newArrayList(id));
            if (vos.isEmpty()) {
                //返回默认值
                Book book = new Book();
                book.setId(id);
                book.setName(BOOK_NAME);
                book.setAuthor(BOOK_AUTHOR);
                book.setPublishHouse(PUBLISH_HOUSE);
                return book;
            }
            return vos.get(0);
        }
    

    外部请求Controller

    @RequestMapping(path = "/{id}", method = RequestMethod.GET)
        public Book findBookInfoById(@PathVariable("id")Long id){
            Book book = bookService.fetchBookById(id);
            if(book!=null){
                return book;
            }else{
                return null;
            }
        }
    

    请求结果查看

    直接测试查询一本书的数据:http://localhost:8080/booksys/book/3
    第一次查询现实数据库查询语句

    image.png

    第二次查询直接从内存中读取,SQL还是原来的一条


    image.png

    因此有了缓存,我们可以减少很多计算压力,提高应用程序的QPS。

    项目源码

    项目源码

    相关文章

      网友评论

          本文标题:SpringBoot使用Guava做内存缓存

          本文链接:https://www.haomeiwen.com/subject/lleblqtx.html