python2018.06聚会笔记

2018-08-03 09:53:08 浏览数 (1)

聚会时间已经过去一个多月了, 当时做了笔记,就一直在闪念胶囊里面躺着了

,今天想起来整理了一下,算是有个交代吧.

一. 姚刚强分享的知乎feed流的优化

这个小哥哥身穿白色T恤, 下身穿粉红色短裤, 讲起话来很幽默,而且喜欢自嘲式的谦虚.

他讲了天下feed流都一样,无论是什么产品,基本都是那些套路,这点我觉得跟推荐系统差距比较大,推荐系统更多可能结合业务,每一个业务的推荐系统最终采用的方案可能都不太一样.但是feed流最大的特征和推荐系统很一致,就是不同的人看到的feed流完全不一样,是个性化的展示.

一开始他们采用的是推模型.当一个被关注的人回答了问题或者发出了提问,就要像所有关注者推送消息.但是有的大V关注者成千上万, 就会想微博一样, 明星一出轨什么的服务器就崩了.

因此下面的优化方案就是由推模型改为拉模型.因为每一个人关注的人顶多几百个, 拉的时候要查的数据没有多少, 不会有太大性能问题,

另一个优化方案是采用离线计算,这点和我做的推荐系统思路是一致的.知乎的做法一开始是想预判这个人是活跃用户还是非活跃用户,对于活跃用户就进行离线计算,把他下一次要拉的数据提前计算出来. 但是怎么判断是不是活跃用户呢,就是当用户拉的时候不光把他要的20条数据拉出来,同时把预测他下次拉的数据都拉出来,拉出100条等他再拉的时候直接给他. 这样确实提高了性能,但是有两个缺点. 一是实时性没有了,用户可能看到了一个话题明天就不感兴趣了,但是今天的feed流出不来,明天出来了有毛用. 第二个缺点是造成了性能上的浪费,如果我就拉一次,后面我不想看了呢,但是离线计算仍然计算了,这样就白白浪费了计算资源.

而优化有一个原则就是让计算接近存储,所以知乎研究了redis里面的redis module来实现计算功能.这是redis4.0版本新引入的特性.用redis作者原话说是 「At the same time, years of experience with scripting, demonstrated that scripting is a way to “compose” existing features, but not a way to extend the capabilities of a system towards use cases it was not designed to cover.」而redis模块提供了自定义命令和自定义数据结构的功能.知乎使用这个技术让计算接近存储.

需要注意的是, 所有的大型项目最后都走向了微服务,但是微服务一定要做降级处理.用在feed流里面就是当拉模型拉不出东西来了怎么办?让程序挂掉是会带来很大麻烦的.所以知乎的做法是提前准备一堆热门数据,可能跟用户关心的没有关系,但是当程序挂点了,用户可能感觉有几分钟拉出来的东西自己不感兴趣跟自己没关系而已,但是后来又好了,这比直接挂掉强太多了.

很多人想动态扩容多好啊, 服务器紧张了动态加机器,用户少了动态减机器等等.不要追求动态扩容,也做不到动态扩容,追求刚刚好,对于现在的业务来讲刚刚够就挺好的了.

今日头条的推荐系统做的那么棒,但是今日头条自己都说了,不是自己的推荐算法多么牛,而是在于头条有一套非常好的AB测试.就是随机把一些用户分成两个组, 测试性的使用一些算法,另一组用其他算法,有效的话就使用,AB测试才是最关键的.

二. 杨宏志分享的知乎首页新架构.

上面的介绍是知乎以前的做法, 杨宏志分享了一些现在的知乎新做的优化.杨宏志穿一个紫红色上衣,是我们大衡水人.

编程有一条原则就是对修改封闭,对扩展开放,所以接下来优化代码的方向是改变代码结构,让代码支持各种业务修改而不用改什么代码,干掉业务逻辑代码里面大量的if else. 变得可配置,扩展性强, 对扩展开放,但是对修改封闭.

但是支持稳步扩展就可以为所欲为了吗? 我们发现经常不同的职能部门会有不同的角度,优化又会有不同的方法.比如对于产品经理来讲, 很容易让应用变成一个杂货铺,什么功能都有, 所以要支持应用变成一个杂货铺. 从技术角度来讲, 希望数据库上线不会出事, 所以数据库方面需要很多优化.而从用户的角度来讲,更多的可能是希望应用能够快速响应.

三.manjusaka分享的python最新的特性:类型注解和aync await的一些看法.

python在PEP484和PEP256中对于类型注解提供了全面的支持.

之前我们用来检查python类型的工具有mypy pytype 或者pycharm

PEP563中的postponed evaluation of ananotation也就是注解的延迟执行被作为3.7的新特性被引入,到了4.0就会成为默认的选项.这样我们不用因为注解依赖了别的类而改变类的定义顺序了.

PEP544提出Protocols: Structual subtyping(static duck typing)的概念.nominal typing system是类型符合或者相等必须显式的声明才叫相等, id属性一致也不可以相等. structual typing system与之相反是运行时检查类型或者通过接口里的方法限制,norminal的方式java c采用, structual是python go采用的方式.PEP484只是做了nominal的方式,但是如果这样的话我们以前使用的魔法方法都要显示的继承typing.abc里面的类,这太不符合python程序员的愿望了,实现起来太难了,所以PEP544解决了这个问题, 不需要显式的声明,也可以查找到类型是否相符.

在3.5以前我们用yeild from 和send来实现了异步代码, 这里核心概念是委托生成器和子生成器的概念, python里通过委托生成器实现了调用方和子生成器之间的直接调用, 来让我们可以以同步的方式写异步代码,不需要写回调函数了,避免了回调地狱.而3.5新出的async await让异步代码和生成器彻底分开,避免了之前一眼看代码不知道到底是一个生成器还是个异步函数的头疼问题.

那async await代码适不适合上生产呢?但是由于存量代码太大,迁移成本太多.而且async await这个东西传染性太强,所有的数据库驱动等IO操作都需要改动,所有的驱动都要重写,有一个库没有重写,就容易造成阻塞问题.官方的事件驱动循环也不完善.事实上aiohttp库里面client端存在https握手的时候内存泄漏的问题. 而且使用async await了跟使用gevent的猴子补丁没有突出的点.这一切都导致async await可以上生产,但是不适合上生产,霸王硬上弓上了就等着加班解决问题吧.

0 人点赞