冬天 发表于 2024-10-31 10:06:36

2.5 万字详解 23 种设计模式及 Netty 搭建 websocket 集群实现服务器消息推送

在数字化浪潮席卷的当下,访问淘宝、京东、微博等网络平台时,热门搜索与近期搜索功能频繁出现。然而,这些便捷功能背后的技术支撑鲜有公众了解,其中蕴藏着不容忽视的潜在价值。

热门搜索与最近搜索功能简介

当前,众多网站普遍设有热门搜索与近期搜索两大功能。热门搜索功能允许用户迅速浏览当前的热门话题,对于商家而言,这构成了重要的流量来源。与此同时,近期搜索功能则便于用户迅速检索到先前搜索过的信息。以淘宝为例,作为一家电商平台,其每日处理的海量搜索数据中,这些功能的实现显得尤为关键。例如,许多用户在淘宝上会多次搜索同一商品,而近期搜索功能则能迅速引导用户回到之前浏览过的商品详情页面。

这两种搜索功能的实施,牵涉到复杂的技术原理,对性能标准有极高的要求。特别是对于热门搜索,在流量高峰时段,必须能够迅速作出响应。

MySQL的不适应性

在处理高并发搜索这一场景时,MySQL并不适宜。以京东等大型电商平台为例,其流量规模庞大。若以MySQL存储热门搜索数据,一旦流量激增,MySQL可能会面临崩溃风险。首先,MySQL在高并发读写情况下性能受限。其次,热门搜索与最近搜索的数据并不需要长期保存。从数据特性分析,采用其他缓存技术或许更为适宜。

Redis的特性与优势

Redis在处理相关问题方面展现出特有的优势。以单机版为例,其可承受高达10万每秒的查询次数(QPS),这一性能指标对于面临巨大流量的网站至关重要。其数据结构类型丰富,能够满足多样化的需求。例如,key-value对这种结构适用于存储结构化数据。以单点登录为例,通过该结构存储用户信息,以cookieId作为键,并设定30分钟的缓存过期时间,从而模拟出session的效果。

Redis确保了二进制数据的安全性,在数据交换过程中,客户端能够自主进行编码,而接收端负责对数据进行整理和存储。这一功能在处理多种复杂数据类型时显得尤为实用。

<p><pre>    <code class="prism language-java"><span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span> redis <span class="token operator">--</span><span class="token operator">></span>
<span class="token generics function"><span class="token punctuation"><</span>dependency<span class="token punctuation">></span></span>
    <span class="token generics function"><span class="token punctuation"><</span>groupId<span class="token punctuation">></span></span>org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>boot<span class="token operator"><</span><span class="token operator">/</span>groupId<span class="token operator">></span>
    <span class="token generics function"><span class="token punctuation"><</span>artifactId<span class="token punctuation">></span></span>spring<span class="token operator">-</span>boot<span class="token operator">-</span>starter<span class="token operator">-</span>data<span class="token operator">-</span>redis<span class="token operator"><</span><span class="token operator">/</span>artifactId<span class="token operator">></span>
    <span class="token generics function"><span class="token punctuation"><</span>version<span class="token punctuation">></span></span><span class="token number">2.1</span><span class="token number">.8</span><span class="token punctuation">.</span>RELEASE<span class="token operator"><</span><span class="token operator">/</span>version<span class="token operator">></span>
<span class="token operator"><</span><span class="token operator">/</span>dependency<span class="token operator">></span>
</code></pre></p>
ZSet用于解决搜索问题

<p><pre>    <code class="prism language-java">server<span class="token operator">:</span>
port<span class="token operator">:</span> <span class="token number">8889</span>
servlet<span class="token operator">:</span>
    context<span class="token operator">-</span>path<span class="token operator">:</span> <span class="token operator">/</span>
spring<span class="token operator">:</span>
redis<span class="token operator">:</span>
    host<span class="token operator">:</span> <span class="token number">192.168</span><span class="token number">.0</span><span class="token number">.41</span>
    port<span class="token operator">:</span> <span class="token number">6379</span>
    password<span class="token operator">:</span> wdy
    database<span class="token operator">:</span> <span class="token number">2</span>
    timeout<span class="token operator">:</span> <span class="token number">5000</span>
</code></pre></p>
针对当前热门搜索和近期搜索的去重及排序需求,Redis的有序集合(ZSet)是最为适宜的选择。在处理热门搜索时,可以依据点击量将点击次数最高的内容置于首位。至于最近搜索,则应将最近的搜索记录排在最前面。若采用列表(List)来执行最近搜索功能,虽然技术上可行,但其删除效率却不如ZSet,且还需额外处理去重问题。ZSet的天然有序属性和高效的操作性能,能够充分满足上述两项搜索功能的需求。

<p><pre>    <code class="prism language-java"><span class="token annotation punctuation">@Data</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Product</span> <span class="token keyword">implements</span> <span class="token class-name">Serializable</span> <span class="token punctuation">{</span>
        <span class="token comment">//商品id</span>
    <span class="token keyword">private</span> Long id<span class="token punctuation">;</span>
        <span class="token comment">//商品名称</span>
    <span class="token keyword">private</span> String productName<span class="token punctuation">;</span>
    <span class="token comment">//.....等属性</span>
<span class="token punctuation">}</span>
</code></pre></p>
控制最近搜索的规模

<p><pre>    <code class="prism language-java"><span class="token annotation punctuation">@Data</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserRecentSearch</span> <span class="token keyword">implements</span> <span class="token class-name">Serializable</span> <span class="token punctuation">{</span>
    <span class="token comment">/**
   * 搜索信息
   */</span>
    <span class="token keyword">private</span> String searchInfo<span class="token punctuation">;</span>
    <span class="token comment">/**
   * 用户id
   */</span>
    <span class="token keyword">private</span> Long unionId<span class="token punctuation">;</span>
</code></pre></p>
近期搜索功能实施限制,禁止ZSet数据无限制添加。考虑到用户可能进行无限次浏览,网站需设定仅保存N条最新浏览记录。一旦数据量达到N+1条,系统将自动删除最早的一条记录。此措施既满足用户对最近搜索结果的需求,又确保了数据存储的合理性和空间的高效利用。

http://www.qianxianly.com/data/attachment/forum/20241031/1730340396589_1.jpg

一个普通用户在短短数小时内可能对数十乃至上百种商品进行检索,若不加以规模限制,将可能过度占用系统资源。

<p><pre>    <code class="prism language-java"><span class="token annotation punctuation">@Component</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SearchRedisHelper</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Resource</span>
    <span class="token keyword">private</span> RedisTemplate redisTemplate<span class="token punctuation">;</span>
    <span class="token comment">/**
   * 热搜的key
   */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">final</span> String HOT_SEARCH <span class="token operator">=</span> <span class="token string">"product_hot_search"</span><span class="token punctuation">;</span>
    <span class="token comment">/**
   * 最近搜索的key
   */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">final</span> String RECENT_SEARCH <span class="token operator">=</span> <span class="token string">"product_recent_search"</span><span class="token punctuation">;</span>
    <span class="token comment">/**
   * 最近搜索的大小
   */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">final</span> Integer CURRENT_SEARCH_SIZE <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
    <span class="token comment">/**
   * 热搜key的过期时间
   */</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">final</span> Integer HOT_SEARCH_EXPIRE_TIME <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
    <span class="token comment">/**
   * 设置redis的过期时间
   * expire其实是懒加载,不设置key的时候是不会执行的
   */</span>
    <span class="token annotation punctuation">@PostConstruct</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setHotSearchExpireTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      redisTemplate<span class="token punctuation">.</span><span class="token function">expire</span><span class="token punctuation">(</span>HOT_SEARCH<span class="token punctuation">,</span> HOT_SEARCH_EXPIRE_TIME<span class="token punctuation">,</span> TimeUnit<span class="token punctuation">.</span>SECONDS<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">/**
   * redis添加最近搜索
   * @param query
   */</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">addRedisRecentSearch</span><span class="token punctuation">(</span>String query<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      UserRecentSearch userRecentSearch <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserRecentSearch</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token comment">//用户id 当前用户 </span>
      userRecentSearch<span class="token punctuation">.</span><span class="token function">setUnionId</span><span class="token punctuation">(</span><span class="token number">100434</span>L<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token comment">//搜索信息</span>
      userRecentSearch<span class="token punctuation">.</span><span class="token function">setSearchInfo</span><span class="token punctuation">(</span>query<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token comment">//score为一个分值,需要把最近浏览的商品id 的分值设置为最大值,</span>
      <span class="token comment">//此处我们可以设置为当前时间Instant.now().getEpochSecond()</span>
      <span class="token comment">//这样最近浏览的商品id的分值一定最大,排在ZSet集合最前面。</span>
      ZSetOperations<span class="token generics function"><span class="token punctuation"><</span>String<span class="token punctuation">,</span> UserRecentSearch<span class="token punctuation">></span></span> zSet <span class="token operator">=</span> redisTemplate<span class="token punctuation">.</span><span class="token function">opsForZSet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token comment">//由于zset 的集合特性当插入已经存在的 v 值 (商品id) 时只会更新score 值,</span>
      zSet<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>RECENT_SEARCH<span class="token punctuation">,</span> userRecentSearch<span class="token punctuation">,</span> Instant<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getEpochSecond</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token comment">//获取到全部用户的最近搜索记录,用reverseRangeWithScores方法,可以获取到根据score排序之后的集合</span>
      Set<span class="token operator"><</span>ZSetOperations<span class="token punctuation">.</span>TypedTuple<span class="token generics function"><span class="token punctuation"><</span>UserRecentSearch<span class="token punctuation">></span></span><span class="token operator">></span> typedTuples <span class="token operator">=</span> zSet<span class="token punctuation">.</span><span class="token function">reverseRangeWithScores</span><span class="token punctuation">(</span>RECENT_SEARCH<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token comment">//只得到当前用户的最近搜索记录,注意这里必须保证set集合的顺序</span>
      Set<span class="token generics function"><span class="token punctuation"><</span>UserRecentSearch<span class="token punctuation">></span></span> userRecentSearches <span class="token operator">=</span> <span class="token function">listRecentSearch</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      
      <span class="token keyword">if</span> <span class="token punctuation">(</span>userRecentSearches<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">></span> CURRENT_SEARCH_SIZE<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">//获取到最开始浏览的第一条</span>
            UserRecentSearch userRecentSearchLast <span class="token operator">=</span> userRecentSearches<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">reduce</span><span class="token punctuation">(</span><span class="token punctuation">(</span>first<span class="token punctuation">,</span> second<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> second<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">orElse</span><span class="token punctuation">(</span>null<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment">//删除最开始浏览的第一条</span>
            zSet<span class="token punctuation">.</span><span class="token function">remove</span><span class="token punctuation">(</span>RECENT_SEARCH<span class="token punctuation">,</span> userRecentSearchLast<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token comment">/**
   * 热搜列表
   * @return
   */</span>
    <span class="token keyword">public</span> Set<span class="token generics function"><span class="token punctuation"><</span>Product<span class="token punctuation">></span></span> <span class="token function">listHotSearch</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">//0 5 表示0-5下标对应的元素</span>
      <span class="token keyword">return</span> redisTemplate<span class="token punctuation">.</span><span class="token function">opsForZSet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">reverseRangeWithScores</span><span class="token punctuation">(</span>HOT_SEARCH<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">/**
   * redis添加热搜
   * @param productList
   */</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">addRedisHotSearch</span><span class="token punctuation">(</span>List<span class="token generics function"><span class="token punctuation"><</span>Product<span class="token punctuation">></span></span> productList<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">//1:表示每调用一次,当前product的分数+1</span>
      productList<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>product <span class="token operator">-</span><span class="token operator">></span> redisTemplate<span class="token punctuation">.</span><span class="token function">opsForZSet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">incrementScore</span><span class="token punctuation">(</span>HOT_SEARCH<span class="token punctuation">,</span> product<span class="token punctuation">,</span> <span class="token number">1D</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">/**
   * 最近搜索列表
   * @return
   */</span>
    <span class="token keyword">public</span> Set<span class="token generics function"><span class="token punctuation"><</span>UserRecentSearch<span class="token punctuation">></span></span> <span class="token function">listRecentSearch</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      Set<span class="token operator"><</span>ZSetOperations<span class="token punctuation">.</span>TypedTuple<span class="token generics function"><span class="token punctuation"><</span>UserRecentSearch<span class="token punctuation">></span></span><span class="token operator">></span> typedTuples <span class="token operator">=</span> redisTemplate<span class="token punctuation">.</span><span class="token function">opsForZSet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">reverseRangeWithScores</span><span class="token punctuation">(</span>RECENT_SEARCH<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> Optional<span class="token punctuation">.</span><span class="token function">ofNullable</span><span class="token punctuation">(</span>typedTuples<span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>tuples <span class="token operator">-</span><span class="token operator">></span> tuples<span class="token punctuation">.</span><span class="token function">stream</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
                        <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>ZSetOperations<span class="token punctuation">.</span>TypedTuple<span class="token operator">:</span><span class="token operator">:</span>getValue<span class="token punctuation">)</span>
                        <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>Objects<span class="token operator">:</span><span class="token operator">:</span>nonNull<span class="token punctuation">)</span>
                        <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span>userRecentSearch <span class="token operator">-</span><span class="token operator">></span> Objects<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>userRecentSearch<span class="token punctuation">.</span><span class="token function">getUnionId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> ContextHolder<span class="token punctuation">.</span><span class="token function">getUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                        <span class="token punctuation">.</span><span class="token function">collect</span><span class="token punctuation">(</span>Collectors<span class="token punctuation">.</span><span class="token function">collectingAndThen</span><span class="token punctuation">(</span>
                              Collectors<span class="token punctuation">.</span><span class="token function">toCollection</span><span class="token punctuation">(</span>LinkedHashSet<span class="token operator">:</span><span class="token operator">:</span><span class="token keyword">new</span><span class="token punctuation">)</span><span class="token punctuation">,</span> LinkedHashSet<span class="token operator">:</span><span class="token operator">:</span><span class="token keyword">new</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">orElseGet</span><span class="token punctuation">(</span>LinkedHashSet<span class="token operator">:</span><span class="token operator">:</span><span class="token keyword">new</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></p>
提升用户体验

<p><pre>    <code class="prism language-java"><span class="token annotation punctuation">@Service</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ProductService</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Resource</span>
    <span class="token keyword">private</span> SearchRedisHelper searchRedisHelper<span class="token punctuation">;</span>
    <span class="token comment">/**
   * 搜索
   * @param query
   * @return
   */</span>
    <span class="token keyword">public</span> List<span class="token generics function"><span class="token punctuation"><</span>Product<span class="token punctuation">></span></span> <span class="token function">search</span><span class="token punctuation">(</span>String query<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token comment">//业务代码可用es.....此处略过....模拟数据库数据</span>
      List<span class="token generics function"><span class="token punctuation"><</span>Product<span class="token punctuation">></span></span> productList <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      Product product <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Product</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      product<span class="token punctuation">.</span><span class="token function">setId</span><span class="token punctuation">(</span><span class="token number">1</span>L<span class="token punctuation">)</span><span class="token punctuation">;</span>
      product<span class="token punctuation">.</span><span class="token function">setProductName</span><span class="token punctuation">(</span><span class="token string">"iphone13"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      productList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>product<span class="token punctuation">)</span><span class="token punctuation">;</span>
      searchRedisHelper<span class="token punctuation">.</span><span class="token function">addRedisRecentSearch</span><span class="token punctuation">(</span>query<span class="token punctuation">)</span><span class="token punctuation">;</span>
      searchRedisHelper<span class="token punctuation">.</span><span class="token function">addRedisHotSearch</span><span class="token punctuation">(</span>productList<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> productList<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">/**
   * 热搜列表
   * @return
   */</span>
    <span class="token keyword">public</span> Set<span class="token generics function"><span class="token punctuation"><</span>Product<span class="token punctuation">></span></span> <span class="token function">listHotSearch</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> searchRedisHelper<span class="token punctuation">.</span><span class="token function">listHotSearch</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">/**
   * 最近搜索列表
   * @return
   */</span>
    <span class="token keyword">public</span> Set<span class="token generics function"><span class="token punctuation"><</span>UserRecentSearch<span class="token punctuation">></span></span> <span class="token function">listRecentSearch</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> searchRedisHelper<span class="token punctuation">.</span><span class="token function">listRecentSearch</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></p>
网站采用Redis技术处理热门搜索与最近搜索功能,旨在增强用户使用体验。除数据处理逻辑外,还运用lrange命令实现Redis分页,从而改善数据展示效果。这些措施使得网页在用户搜索时能快速响应,有效提升了网页的流畅度和易用性。对于微博等重视信息时效性和搜索效率的平台,这一特性尤为关键。

<p><pre>    <code class="prism language-java"><span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">"/redis/test"</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@RestController</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">RedisController</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Resource</span>
    <span class="token keyword">private</span> RedisTemplate redisTemplate<span class="token punctuation">;</span>
    <span class="token annotation punctuation">@Resource</span>
    <span class="token keyword">private</span> ProductService productService<span class="token punctuation">;</span>
    <span class="token comment">/**
   * 删除redis
   * @param key
   * @return
   */</span>
    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">"/w/remove/redis"</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> Result <span class="token function">removeRedis</span><span class="token punctuation">(</span>String key<span class="token punctuation">)</span><span class="token punctuation">{</span>
      redisTemplate<span class="token punctuation">.</span><span class="token function">delete</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">return</span> Result<span class="token punctuation">.</span><span class="token function">success</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">/**
   * 搜索
   * @param query
   * @return
   */</span>
    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">"/r/search/product"</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> Result <span class="token function">listProduct</span><span class="token punctuation">(</span>String query<span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> Result<span class="token punctuation">.</span><span class="token function">success</span><span class="token punctuation">(</span>productService<span class="token punctuation">.</span><span class="token function">search</span><span class="token punctuation">(</span>query<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">/**
   * 热搜列表
   * @return
   */</span>
    <span class="token annotation punctuation">@ResponseBody</span>
    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">"/r/list/hot/search"</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> Result <span class="token function">listHotSearch</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> Result<span class="token punctuation">.</span><span class="token function">success</span><span class="token punctuation">(</span>productService<span class="token punctuation">.</span><span class="token function">listHotSearch</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token comment">/**
   * 最近搜索列表
   * @return
   */</span>
    <span class="token annotation punctuation">@ResponseBody</span>
    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">"/r/list/recent/search"</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> Result <span class="token function">recentHotSearch</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> Result<span class="token punctuation">.</span><span class="token function">success</span><span class="token punctuation">(</span>productService<span class="token punctuation">.</span><span class="token function">listRecentSearch</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></p>
你是否曾好奇,除了Redis,还有哪些技术能够类似地应对搜索类问题?如有见解,敬请留言、点赞并转发。
页: [1]
查看完整版本: 2.5 万字详解 23 种设计模式及 Netty 搭建 websocket 集群实现服务器消息推送