网站可以从用户的访问、交互、购买行为中收集到有价值的信息。例如:如果我们只想关注那些浏览量最高的页面,那么我们可以尝试修改页面的格局、配色甚至是页面上展示的其他链接。每一个修改尝试都能改变用户对一个页面或者后续页面的体验,或好或坏,甚至还能影响用户的购买行为。
前面介绍了如果记录用户浏览过的商品或者用户添加到购物车中的商品、如何通过缓存web页面来减少页面载入时间并提升页面的响应速度。不过遗憾的是,我们对我们的网站做的过了火:我们网站总共包含100 000件商品,而冒然的缓存所有商品页面将耗尽整个网站的全部内存!经过一番调研之后,我们决定只对其中10 000件商品的页面进行缓存。
前面曾经介绍过,每个用户都有一个相应的记录用户浏览商品历史的有序集合,尽管使用这些有序集合可以计算出用户最近浏览的商品,但进行这种计算却需要消耗大量的时间。为了解决这个问题,我们决定在update_token()
函数里面添加一行代码:
#更新令牌
import time
def update_token(conn,token,user,item=None):
timestamp=time.time() #h获取当前时间戳
conn.hset('login:',token,user) #维持令牌与已登陆用户之间的映射
conn.zadd('recent:',token,timestamp) #记录领哦哎最后一次出现的时间
if item:
conn.zadd('viewed:'+token,item,timestamp) #记录用户浏览郭的商品
conn.zremrangebyrank('viewed:'+token,0,-26) #移除旧的记录,值保留用户最近浏览过的25个商品
#新增下面一行代码
conn.zincrby('viewed:',item,-1)
新增加的代码记录了所有商品的浏览次数,并根据浏览次数对商品进行了排序,被浏览得最多的商品将被放到有序集合的索引0位置上,并且具有整个有序集合最少的分值。随着时间的流逝,商品的浏览次数会呈现两极分化的状态,一些商品的浏览次数越来越多,而另一些商品的浏览次数则越来越少。除了缓存最常被浏览得商品之外,程序还需要发现那些变得越来越流行的新商品,并在合适的时候缓存他们。
为了让商品浏览次数排行榜能够保持最新,我们需要定期修剪有序集合的长度并调整已有元素的分值,从而使得新流行的商品也可以在排行榜里面占据一席之地。之前已经介绍过从有序集合里面移除元素的方法,而调整元素分值的动作则可以通过zinterstore命令来完成。zinterstore命令可以组合起一个或多个有序集合,并将有序集合包含的每个分值都乘以一个给定的数值【用户可以为每个有序集合分别指定不同的相乘数值】。每个5分值,函数就会删除所有排名在20 000名之后的商品,并将删除之后剩余的所有商品的浏览次数减半。
def rescale_viewed(conn):
while not QUIT:
#删除所有排名在20 000名之后的商品
conn.zremrangebyrank('viewed:',0,-20001)
#将浏览次数降低为原来的一半
conn.zinterstore('viewed:',{'viewed:':.5})
#5分钟之后再次执行该操作
time.sleep(300)
通过记录商品的浏览次数,并定期对记录浏览次数的有序集合进行修剪和分值调整,我们为我们的网站建立起了一个持续更新的最常浏览商品的排行榜。
#判断页面是否需要被缓存
def can_cache(conn,request):
#尝试从页面里面取出商品ID
item_id=extract_item_id(request)
#检查这个页面能否额比缓存以及这个页面是否为商品页面
if not item_id or is_dynamic(request):
return False
#取得商品的浏览次数排名
rank=conn.zrank('viewed:',item_id)
#根据商品的浏览次数排名来判断是否需要缓存这个页面
return rank is not None and rank<10000
通过使用前面介绍的几个函数,我们的网站现在可以统计商品被浏览的次数,并以此来缓存用户经常浏览的10 000个商品页面。如果我们想以最少的代价来存储更多的页面,那么可以考虑先对页面进行压缩,然后再缓存到Redis里面;或者使用【Edge Side Includes】计数移除页面中的部分内容;又或者对模板进行提前优化【pre-optimize】,移除所有非必要的空格字符。这些技术能够减少内存消耗并增加Redis能够缓存的页面数量,为访问量不断增长的网站带来额外的性能提升。
本章小结
本章介绍了几种用于降低网站数据库负载和Web服务器负载的方法,这些例子里面介绍的都是真实的Web应用程序当今正在使用的思路和方法。