本节书摘来异步社区《Redis实战》一书中的第2章,第2.5节,作者: 【美】Josiah L. Carlson(约西亚 L.卡尔森)译者: 黄健宏 责编: 杨海玲,更多章节内容可以访问云栖社区“异步社区”公众号查看。
网站可以从用户的访问、交互和购买行为中收集到有价值的信息。例如,如果我们只想关注那些浏览量最高的页面,那么我们可以尝试修改页面的格局、配色甚至是页面上展示的其他链接。每一个修改尝试都能改变用户对一个页面或者后续页面的体验,或好或坏,甚至还能影响用户的购买行为。
前面的2.1节和2.2节中介绍了如何记录用户浏览过的商品或者用户添加到购物车中的商品,2.3节中则介绍了如何通过缓存Web页面来减少页面载入时间并提升页面的响应速度。不过遗憾的是,我们对Fake Web Retailer采取的缓存措施做得过了火:Fake Web Retailer总共包含100 000件商品,而冒然地缓存所有商品页面将耗尽整个网站的全部内存!经过一番调研之后,我们决定只对其中10 000件商品的页面进行缓存。
前面的2.1节中曾经介绍过,每个用户都有一个相应的记录用户浏览商品历史的有序集合,尽管使用这些有序集合可以计算出用户最经常浏览的商品,但进行这种计算却需要耗费大量的时间。为了解决这个问题,我们决定在update_token()函数里面添加一行代码,如代码清单2-9所示。
代码清单2-9 修改后的update_token()函数
新添加的代码记录了所有商品的浏览次数,并根据浏览次数对商品进行了排序,被浏览得最多的商品将被放到有序集合的索引0位置上,并且具有整个有序集合最少的分值。随着时间的流逝,商品的浏览次数会呈现两极分化的状态,一些商品的浏览次数会越来越多,而另一些商品的浏览次数则会越来越少。除了缓存最常被浏览的商品之外,程序还需要发现那些变得越来越流行的新商品,并在合适的时候缓存它们。
为了让商品浏览次数排行榜能够保持最新,我们需要定期修剪有序集合的长度并调整已有元素的分值,从而使得新流行的商品也可以在排行榜里面占据一席之地。之前的2.1节中已经介绍过从有序集合里面移除元素的方法,而调整元素分值的动作则可以通过ZINTERSTORE命令来完成。ZINTERSTORE命令可以组合起一个或多个有序集合,并将有序集合包含的每个分值都乘以一个给定的数值(用户可以为每个有序集合分别指定不同的相乘数值)。每隔5分钟,代码清单2-10展示的函数就会删除所有排名在20 000名之后的商品,并将删除之后剩余的所有商品的浏览次数减半。
代码清单2-10 守护进程函数rescale_viewed()
通过记录商品的浏览次数,并定期对记录浏览次数的有序集合进行修剪和分值调整,我们为Fake Web Retailer建立起了一个持续更新的最常浏览商品排行榜。接下来要做的就是修改之前介绍过的can_cache()函数,让它使用新的方法来判断页面是否需要被缓存,如代码清单 2-11所示。
代码清单2-11 can_cache()函数
通过使用前面介绍的几个函数,Fake Web Retailer现在可以统计商品被浏览的次数,并以此来缓存用户最经常浏览的10 000个商品页面。如果我们想以最少的代价来存储更多页面,那么可以考虑先对页面进行压缩,然后再缓存到Redis里面;或者使用Edge Side Includes技术移除页面中的部分内容;又或者对模板进行提前优化(pre-optimize),移除所有非必要的空格字符。这些技术能够减少内存消耗并增加Redis能够缓存的页面数量,为访问量不断增长的网站带来额外的性能提升。