去年,随着goodbre.ws的上线,迎来了一部分新用户,我认识到自己处在一个7000人的用户群之中,一个小的改变,不仅仅在是我的数百的好友,同学以及同事。无论怎样,随着这么多人的到来产生了一些小问题,首先,站点的刷新推荐任务(进程)变得很慢很慢,我终于发现这是站点后台的I/O瓶颈,这使得Postgre Redis访问超过了他们能够处理的能力,无论怎样,越来越多的人来获取他们的推荐页,很快的我看到我的服务器的内存使用变得越来越糟,这将不会需要太长时间Redis试图使用超过的我服务器的物理内存,所以我被迫无奈关掉了goobre.ws,也就是我们现在。
其它翻译版本 (1) 加载中我开始认真思考我的Redis数据库使用方法,是什么可能引起Redis使用了这么多的内存呢?我想到我的Key的长度,典型的Redis key的使用像这样:recommendable:users:1234:liked_beers,这样子来说,每个用户乘以5(如不喜欢,书签,隐藏喜好,等等)并且存在很多重复的Key names,他们都相当的长,或许正是因为使用了成千上万的长Key name 才使得Redis使用的大量的内存?我决定试着缩短他们并且使之为一个合理的格式,如:u:1234:lb
期望着,我重命名了Keys并且重启了Redis数据库,但是希望落空了,它的确减少了0.01GB的内存使用,对也就是10M,也许在以后这是一个值得尝试的方法,但是,显然这不是我的主要问题
其它翻译版本 (1) 加载中优化是个我很少问津的“兔子洞”,我不是这方面的专家。我的自我意识和自我怀疑妨碍了真实测试,让我立刻下了结论,或许Redis不是适合我的工具。也许我应该回归到把信息存储到PostgreSQL,但是在推荐产生时也会接收一个很大的性能压力。
我漫不经心的寻找其他的数据存储,最终也没能找到一个像Redis的key-value存储方式,有很多具备集合和分类集合,但是不像redis那样存储在内存里。我甚至想放弃内存存储,它只不过是快些而已嘛!再说了SET和ZSET的数据结构也不太适合我的用法。但是我能做啥呢?Redis对于我来说明显变得昂贵了。我需要寻找其他的替代品。
我曾考虑把评分信息换到Neo4j图形数据库。这会创建一个生成推荐的有趣方式:它可以简单遍历一个图—从一个用户连接到其他用户并找出用户喜欢最多的啤酒生成的图。这或许更快些,然而,推荐模块自身可能不会很好的支持。
我也想简单的把评分信息迁回到Postgres并且当Rails应用启动时初始化一些Ruby Set映射,但这有可能占用更多的内存。我只是把RAM占用从Redis转移到了Rails。
最后,昨天,我把我应该做的放到了首位。我下载了一个Redis的内存性能分析工具来帮助我分析每个key占用的空间统计。我的发现令我很惊讶,因为它大概是我很久前想到的一个问题。很久以前,实际上,我认为我已经解决了它。
我的问题是有多少数据存储在每个分类的集合(ZSET)里,每个用户需要获取两个ZSETs,一个用来存储用户相似性和通过计算相似度匹配的其他用户的IDs。另一个ZSET存储推荐,根据用户可能喜欢的啤酒匹配啤酒的IDs。在每个ZSET中,对于其他每一个用户和每一种类啤酒都保留这些值,再乘以7000用户和60000啤酒,好吧,可想而知了,很多集合已经超过了1MB。
其它翻译版本 (1) 加载中我以为我已经通过设置k-Nearest-Neighbor截断了相似属性的ZSETs,并且我已经在Recommendable引入了。这个设置当相对于每一个用户生成推荐时使用了一些指定数量的相似用户。启用这个设置减少了每一个相似集合大约从7000到200(100相似用户和100不同用户)的大小。
此外,我实现了一个设置指定同一时间对于每一个用户最多有多少推荐。我只显示10条推荐信息,因此对于每一种单独的啤酒保持这些概率是非常荒谬的。我减少到100条也一样,这样人们可以根据当前的评价快速的获取更多的信息。
等到把所有的sets截取成指定的长度后,怀着敬畏的心情我看到Redis使用的内存从1.5GB降到了50MB。我不认为我在处理Redis内存使用问题上花了很多时间。
如果你有一个推荐用户功能,我强烈建议你使用nearest_neighbors,furthest_neighbors, andrecommendations_to_store的设置。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务