nnkwrik 6 лет назад
Родитель
Сommit
5762ef8a86

+ 7 - 0
goods-service/pom.xml

@@ -71,6 +71,13 @@
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
 
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>27.0-jre</version>
+        </dependency>
+
+
 
     </dependencies>
 

+ 71 - 0
goods-service/src/main/java/io/github/nnkwrik/goodsservice/cache/BrowseCache.java

@@ -0,0 +1,71 @@
+package io.github.nnkwrik.goodsservice.cache;
+
+import com.google.common.cache.*;
+import io.github.nnkwrik.goodsservice.dao.OtherMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * 商品浏览量的缓存,过期(10天)/超出缓存大小/超过10个时更新数据库
+ * 由于需要在非静态的RemovalListener才能调用mapper,做成单例
+ *
+ * @author nnkwrik
+ * @date 18/11/20 12:03
+ */
+@Slf4j
+@Component
+public class BrowseCache {
+
+    @Autowired
+    private OtherMapper otherMapper;
+
+    private static BrowseCache browseCache = new BrowseCache(); //单例
+
+
+    //过期(1天)/超出缓存队列大小(1000)/缓存超过10个时 会触发
+    RemovalListener<Integer, AtomicInteger> listener =
+            notification -> {
+                log.info("BrowseCache缓存刷入数据库,原因 :【{}】,数据 :【key={} , value={}】",
+                        notification.getCause(), notification.getKey(), notification.getValue().get());
+                otherMapper.addBrowseCount(notification.getKey(), notification.getValue().get());
+            };
+
+
+    /**
+     * @key 商品id
+     * @value 缓存的浏览量
+     */
+    private Cache<Integer, AtomicInteger> cache =
+            CacheBuilder.newBuilder()
+                    .maximumSize(1000)
+                    .expireAfterWrite(1, TimeUnit.DAYS)
+                    .removalListener(
+                            RemovalListeners.asynchronous(listener, Executors.newWorkStealingPool()))
+                    .build();
+
+
+    public static void add(Integer goodsId) {
+        Cache<Integer, AtomicInteger> singleCache =  browseCache.cache;
+        AtomicInteger browseCount = singleCache.getIfPresent(goodsId);
+        if (browseCount != null) {
+            int count = browseCount.incrementAndGet();
+            if (count > 10) {
+                //手动移除缓存,让他触发removalListener,刷新数据库
+                singleCache.invalidate(goodsId);
+            }
+        } else {
+            singleCache.put(goodsId, new AtomicInteger(1));
+        }
+
+        //检查过期的缓存,让他触发removalListener
+        //必须执行这个cache才会去检查是否过期, 否则尽管过期他也不会触发removalListener
+        singleCache.cleanUp();
+    }
+
+
+}

+ 54 - 0
goods-service/src/main/java/io/github/nnkwrik/goodsservice/cache/SearchCache.java

@@ -0,0 +1,54 @@
+package io.github.nnkwrik.goodsservice.cache;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+/**
+ * 热门关键字的缓存,超出缓存大小时会优先顶替掉最久没更新value的key
+ *
+ * @author nnkwrik
+ * @date 18/11/20 15:23
+ */
+@Slf4j
+public class SearchCache {
+    /**
+     * @key 搜索关键字 TODO 分词
+     * @value 搜索次数
+     */
+    private static Cache<String, AtomicInteger> cache =
+            CacheBuilder.newBuilder()
+                    .maximumSize(10000) //超出大小时,替换最久没更新value的key
+                    .expireAfterWrite(30, TimeUnit.DAYS)
+                    .build();
+
+    public static void add(String keyword) {
+
+        int count = 0;
+        AtomicInteger browseCount = cache.getIfPresent(keyword);
+        if (browseCount != null) {
+            count = browseCount.incrementAndGet();
+        } else {
+            cache.put(keyword, new AtomicInteger(1));
+        }
+
+        log.debug("SearchCache更新关键字【{}】的搜索次数为【{}】",keyword,count);
+    }
+
+    public static List<String> getHot(int num) {
+        log.debug("从SearchCache获取热门关键字列表");
+        return cache.asMap().entrySet().stream()
+                .sorted(Comparator.comparingInt(entry -> -entry.getValue().get()))
+                .limit(num)
+                .map(Map.Entry::getKey)
+                .collect(Collectors.toList());
+
+    }
+}

+ 5 - 0
goods-service/src/main/java/io/github/nnkwrik/goodsservice/dao/OtherMapper.java

@@ -3,7 +3,9 @@ package io.github.nnkwrik.goodsservice.dao;
 import io.github.nnkwrik.goodsservice.model.po.Ad;
 import io.github.nnkwrik.goodsservice.model.po.Channel;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
 
 import java.util.List;
 
@@ -23,4 +25,7 @@ public interface OtherMapper {
             "order by sort_order asc, `create` desc\n" +
             "limit 5")
     List<Ad> findAd();
+
+    @Update("update goods set browse_count = browse_count + #{add} where id = #{goodsId}")
+    void addBrowseCount(@Param("goodsId") int id, @Param("add") int add);
 }