AD管理时,IT人员如何分权进行空压机日常维护护

&figure&&img src=&https://pic3.zhimg.com/v2-c3e16c12c0fb0db977bc256eda9415db_b.jpg& data-rawwidth=&650& data-rawheight=&310& class=&origin_image zh-lightbox-thumb& width=&650& data-original=&https://pic3.zhimg.com/v2-c3e16c12c0fb0db977bc256eda9415db_r.jpg&&&/figure&&blockquote&本文引用了架构师之路公众号作者沈剑的文章,内容有改动,感谢原作者。&/blockquote&&h2&1、前言&/h2&&p&&br&&/p&&p&我们平时在使用即时通讯应用时候,每当发出一条聊天消息,都希望对方尽快看到,并尽快回复,但对方到底有没有真的看到?我却并不知道。&/p&&p&一个残酷的现实是,很多时候对方其实是早就已经看到了这条消息,但出出种种原因(大家都懂的),通常都是默默返回——假装没看见。&/p&&p&像微信这样的熟人社交工具,在产品的设计理念上,为了保持使用者的隐私性,在线状态、已读回执等涉及隐私的功能,都没有提供。但很多时候,尤其商务、办公场合下,特别需要一种强反馈的工具,这对于打造高效的团队很有帮助(虽然员工很反感,但老板都喜欢这样的功能,哈哈)。&/p&&p&&b&目前市面上主流的移动端IM里,提供了已读回执的主要有阿里的钉钉、网易的易信、阿里的旺旺,如下图所示:&/b&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-070ed9a56bf209c9bad9_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&288& data-rawheight=&511& class=&content_image& width=&288&&&/figure&&figure&&img src=&https://pic3.zhimg.com/v2-36eb758fa84acf5c28bd3_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&288& data-rawheight=&511& class=&content_image& width=&288&&&/figure&&figure&&img src=&https://pic2.zhimg.com/v2-bb8cc4bcceb9f_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&288& data-rawheight=&511& class=&content_image& width=&288&&&/figure&&p&&br&▲ 上图从左至右分别为:钉钉、易信、旺旺(千牛)&/p&&p&以阿里的钉钉为例,钉钉的产品定位是用于商务交流,其“强制已读回执”功能,让职场人无法再“假装不在线”、“假装没收到”。更有甚者,钉钉的群聊“强制已读回执”功能,甚至能够知道谁读了消息,谁没有读消息(老板的福音啊)。&/p&&p&那么群聊消息的收发流程、消息的送达保证、已读回执机制,到底该怎么实现呢?这就是今天要讨论的话题。&/p&&p&&b&学习交流:&/b&&/p&&blockquote&- 即时通讯开发交流3群:&a href=&https://link.zhihu.com/?target=https%3A//link.jianshu.com/%3Ft%3Dhttp%253A%252F%252Fshang.qq.com%252Fwpa%252Fqunwpa%253Fidkey%253D051ed62f79eaf622dd5b1c87b26bedb890b068be79dd2006fc80ccf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&&/a&[推荐]&br&- 移动端IM开发入门文章:《&a href=&https://link.zhihu.com/?target=https%3A//link.jianshu.com/%3Ft%3Dhttp%3A//www.52im.net/thread-464-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&新手入门一篇就够:从零开发移动端IM&/a&》&/blockquote&&p&(本文同步发布于:&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&52im.net/thread-1611-1-&/span&&span class=&invisible&&1.html&/span&&span class=&ellipsis&&&/span&&/a&)&/p&&h2&2、IM开发干货系列文章&/h2&&p&&br&&/p&&p&&b&本文是系列文章中的第14篇,总目录如下:&/b&&/p&&ul&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-294-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IM消息送达保证机制实现(一):保证在线实时消息的可靠投递&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-594-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IM消息送达保证机制实现(二):保证离线消息的可靠投递&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-714-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&如何保证IM实时消息的“时序性”与“一致性”?&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-715-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IM单聊和群聊中的在线状态同步应该用“推”还是“拉”?&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-753-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IM群聊消息如此复杂,如何保证不丢不重?&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-783-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&一种Android端IM智能心跳算法的设计与实现探讨(含样例代码)&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-787-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&移动端IM登录时拉取数据如何作到省流量?&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-802-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&通俗易懂:基于集群的移动端IM接入层负载均衡方案分享&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-867-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&浅谈移动端IM的多点登陆和消息漫游原理&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IM开发基础知识补课(一):正确理解前置HTTP SSO单点登陆接口的原理&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IM开发基础知识补课(二):如何设计大量图片文件的服务端存储架构?&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IM开发基础知识补课(三):快速理解服务端数据库读写分离原理及实践建议&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IM群聊消息的已读回执功能该怎么实现?&/a&》(本文)&br&&/li&&/ul&&p&&br&&/p&&p&另外,如果您是IM开发初学者,强烈建议首先阅读《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-464-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&新手入门一篇就够:从零开发移动端IM&/a&》。&/p&&h2&3、正文引言&/h2&&p&&br&&/p&&p&首先我们需要了解一下群消息的设计、投递流程以及可达性保证机制,因不是本文要讨论的重点,所以尽量言简意赅,更详细的资料请见下方的推荐文章列表。&/p&&p&&b&如您对聊天消息的投递和送达机制等尚无概念,可先读本系列文章的以下几篇,有助于您详细掌握这方面的内容:&/b&&/p&&ul&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-294-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IM消息送达保证机制实现(一):保证在线实时消息的可靠投递&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-594-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IM消息送达保证机制实现(二):保证离线消息的可靠投递&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-714-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&如何保证IM实时消息的“时序性”与“一致性”?&/a&》&/li&&li&《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-753-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IM群聊消息如此复杂,如何保证不丢不重?&/a&》&br&&/li&&/ul&&p&&br&&/p&&h2&4、群消息怎么设计?&/h2&&p&&br&&/p&&p&大家一起跟着楼主的节奏,一步一步来看群消息怎么设计。&/p&&p&&b&核心问题1:&/b&群消息,只存一份?还是,每个成员存一份?&br&&b&答:&/b&存一份,为每个成员设置一个群消息队列,会有大量数据冗余,并不合适。&/p&&p&&b&核心问题2:&/b&如果群消息只存一份,怎么知道每个成员读了哪些消息?&br&&b&答:&/b&可以利用群消息的偏序关系,记录每个成员的last_ack_msgid(last_ack_time),这条消息之前的消息已读,这条消息之后的消息未读。该方案意味着,对于群内的每一个用户,只需要记录一个值即可。&/p&&p&解答上述两个核心问题后,很容易得到群消息的核心数据结构。&/p&&p&&b&群消息表:&/b&记录群消息&/p&&p&group_msgs(msgid, gid, sender_uid, time, content);&/p&&p&&br&&/p&&p&各字段的含义为:消息ID,群ID,发送方UID,发送时间,发送内容。&/p&&p&&b&群成员表:&/b&记录群里的成员,以及每个成员收到的最后一条群消息&/p&&p&group_users(gid, uid, last_ack_msgid);&/p&&p&&br&&/p&&p&各字段的含义为:群ID,群成员UID,群成员最后收到的一条群消息ID。&/p&&h2&5、了解一下群消息发送的流程&/h2&&p&&br&&/p&&p&在核心数据结构设计完之后,一起来看看群消息发送的流程(本系列中的文章《&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-753-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&IM群聊消息如此复杂,如何保证不丢不重?&/a&》详细讲解了这个过程,可以深入读一读)。&/p&&p&&b&业务场景:&/b&&/p&&ul&&li&1)一个群中有A, uid1, uid2, uid3四名成员;&/li&&li&2)A, uid1, uid2在线,期望实时收到在线消息;&/li&&li&3)uid3离线,期望未来拉取到离线消息。&/li&&/ul&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-e71f67b7cb76d3aa128b9d63a54177d6_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&404& data-rawheight=&211& class=&content_image& width=&404&&&/figure&&p&&b&其整个消息发送的流程1-4如上图:&/b&&/p&&ul&&li&1)A发出群消息;&/li&&li&2)server收到消息后,一来要将群消息落地,二来要查询群里有哪些群成员,以便实施推送;&/li&&li&3)对于群成员,查询在线状态;&/li&&li&4)对于在线的群成员,实施推送。&br&&/li&&/ul&&p&这个流程里,只要第二步消息落地完成,就能保证群消息不会丢失。&/p&&p&&b&核心问题3:&/b&如何保证接收方一定收到群消息?&br&&b&答:&/b&各个收到消息后,要修改各群成员的last_ack_msgid,以告诉系统,这一条消息确认收到了。&/p&&p&在线消息,离线消息的last_ack_msgid的修改,又各有不同。&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-01fcbd55b198cedfda475e4f7b75cb7c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&403& data-rawheight=&215& class=&content_image& width=&403&&&/figure&&p&&br&对于在线的群友,收到群消息后,第一时间会ack、修改last_ack_msgid。&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-cc5df54e6be3bef17d4dbc_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&399& data-rawheight=&209& class=&content_image& width=&399&&&/figure&&p&&br&对于离线的群友,会在下一次登录时,拉取未读的所有群离线消息,并将last_ack_msgid修改为最新的一条消息。&/p&&p&&b&核心问题4:&/b&如果ack丢失,群友会不会拉取重复的群消息?&br&&b&答:&/b&会,可以根据msgid在客户端本地做去重,即使系统层面收到了重复的消息,仍然可以保证良好的用户体验。&/p&&p&上述流程,只能确保接收方收到消息,发送方仍然不知道哪些人在线阅读了消息,哪些人离线未阅读消息,并没有实现已读回执,那已读回执会对系统设计产生什么样的影响呢?&/p&&h2&6、已读回执流程的设计&/h2&&p&&br&&/p&&p&前面的基础知识我们已经了解的差不多,本节来讨论本文的重点内容,即群聊已读回执流程到底该怎么设计。&/p&&p&对于发送方发送的任何一条群消息,都需要知道,这条消息有多少人已读多少人未读,就需要一个基础表来记录这个关系。&/p&&p&&b&消息回执表:&/b&用来记录消息的已读回执&/p&&p&msg_acks(sender_uid, msgid, recv_uid, gid,if_ack);&/p&&p&&br&&/p&&p&各字段的含义为:发送方UID,消息ID,回执方UID,群ID,回执标记。&/p&&p&&b&增加了已读回执逻辑后,群消息的流程会有细微的改变,见下图:&/b&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-b90bda631_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&404& data-rawheight=&253& class=&content_image& width=&404&&&/figure&&p&&b&接着,server收到消息后,除了要:&/b&&/p&&ul&&li&1)将群消息落地;&/li&&li&2)查询群里有哪些群成员,以便实施推送;&br&&/li&&/ul&&p&&b&之外,还需要:&/b&&/p&&ul&&li&3)插入每条消息的初始回执状态。&br&&/li&&/ul&&figure&&img src=&https://pic1.zhimg.com/v2-f61f251cd1ff0ad5cdb369_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&400& data-rawheight=&245& class=&content_image& width=&400&&&/figure&&p&&b&接收方修改last_ack_msgid的流程,会变为:&/b&&/p&&ul&&li&1)发送ack请求;&/li&&li&2)修改last_ack_msgid,并且,修改已读回执if_ack状态;&/li&&li&3)查询发送方在线状态;&/li&&li&4)向发送方实时推送已读回执(如果发送方在线);&br&&/li&&/ul&&p&&b&如果发送方不在线,ta会在下次登录的时候:&/b&&/p&&ul&&li&5)从关联表里拉取每条消息的已读回执。&br&&/li&&/ul&&p&&b&这里的初步结论是:&/b&&/p&&ul&&li&如果发送方在线:会实时被推送已读回执;&/li&&li&如果发送方不在线:会在下次在线时拉取已读回执。&br&&/li&&/ul&&h2&7、已读回执流程优化方案&/h2&&p&&br&&/p&&p&再次详细的分析下,群消息已读回执的“消息风暴扩散系数”,假设每个群有200个用户,其中20%的用户在线,即40各用户在线。&/p&&p&&b&那么,群用户每发送一条群消息,会有:&/b&&/p&&ul&&li&40个消息,通知给群友;&/li&&li&40个ack修改last_ack_msgid,发给服务端;&/li&&li&40个已读回执,通知给发送方。&br&&/li&&/ul&&p&可见,其消息风暴扩散系数非常之大。&/p&&p&&b&同时:&/b&&/p&&ul&&li&需要存储40条ack记录。&br&&/li&&/ul&&p&群数量,群友数量,群消息数量越来越多之后,存储也会成为问题。&/p&&p&是否有优化方案呢?&/p&&p&&b&群消息的推送,能否改为接收方轮询拉取?&/b&&br&&b&答:&/b&不能,消息接收,实时性是核心指标。&/p&&p&&b&对于last_ack_msgid的修改,真的需要每个群消息都进行ack么?&/b&&br&&b&答:&/b&其实不需要,可以批量ack,累计收到N条群消息(例如10条),再向服务器发送一次last_ack_msgid的修改请求,同时修改这个请求之前所有请求的已读回执,这样就能将40个发送给服务端的ack请求量,降为原来的1/10。&/p&&p&&b&会带来什么副作用?&/b&&br&&b&答:&/b&last_ack_msgid的作用是,记录接收方最近新取的一条群消息,如果不实时更新,可能导致,异常退出时,有一些群消息没来得及更新last_ack_msgid,使得下次登陆时,会拉取到重复的群消息。但这不是问题,客户端可以根据msgid去重,用户体验不会受影响。&/p&&p&&b&发送方在线时,对于已读回执的发送,真的需要实时推送么?&/b&&br&&b&答:&/b&其实不需要,发送方每发一条消息,会收到40个已读回执,采用轮询拉取(例如1分钟一次,一个小时也就60个请求),可以大大降低请求量。&br&(画外音:或者直接放到应用层keepalive请求里,做到0额外请求增加。)&/p&&p&&b&会带来什么副作用?&/b&&br&&b&答:&/b&已读回执更新不实时,最坏的情况下,1分钟才更新回执。当然,可以根据性能与产品体验来折衷配置这个轮询时间。&/p&&p&&b&如何降低数据量?&/b&&/p&&p&&b&答:&/b&回执数据不是核心数据&/p&&ul&&li&已读的消息,可以进行物理删除,而不是标记删除;&/li&&li&超过N长时间的回执,归档或者删除掉。&br&&/li&&/ul&&h2&8、本文小结&/h2&&p&&br&&/p&&p&&b&对于群消息已读回执,一般来说:&/b&&/p&&ul&&li&如果发送方在线,会实时被推送已读回执;&/li&&li&如果发送方不在线,会在下次在线时拉取已读回执。&br&&/li&&/ul&&p&&b&如果要对进行优化,可以:&/b&&/p&&ul&&li&接收方累计收到N条群消息再批量ack;&/li&&li&发送方轮询拉取已读回执。&/li&&/ul&&p&&br&&/p&&p&物理删除已读回执数据,定时删除或归档非核心历史数据。&/p&&p&(本文同步发布于:&a href=&https://link.zhihu.com/?target=http%3A//www.52im.net/thread-.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&52im.net/thread-1611-1-&/span&&span class=&invisible&&1.html&/span&&span class=&ellipsis&&&/span&&/a&)&/p&
本文引用了架构师之路公众号作者沈剑的文章,内容有改动,感谢原作者。1、前言 我们平时在使用即时通讯应用时候,每当发出一条聊天消息,都希望对方尽快看到,并尽快回复,但对方到底有没有真的看到?我却并不知道。一个残酷的现实是,很多时候对方其实是早…
&figure&&img src=&https://pic2.zhimg.com/v2-98d199413fbefa0f060f4a8_b.jpg& data-rawwidth=&1242& data-rawheight=&1017& class=&origin_image zh-lightbox-thumb& width=&1242& data-original=&https://pic2.zhimg.com/v2-98d199413fbefa0f060f4a8_r.jpg&&&/figure&&p&我还很清楚地记得几个月前看到那条“德国撒旦画”新闻时的感受。哪怕即使德国并非自己未来留学的目标国从而让我对其的了解要稍多一些,“警察/学校不管”这种有违常识的细节以及低级网络小说一般的手法也让整件事情的真实性显得足够可疑了。可之后的一天里,随着个大营销号的跟进,这条信息几乎出现在了所有身边人的主页上,我也收到了数条“太危险了还是别准备到那里上学了”的好心劝告。更让我吃惊的是,虽然早已有了众多理性者的分析甚至来自大使馆的辟谣与当事人的道歉,如果你现在去打开当初的爆料微博,你依然在评论区会看到@好友来围观的评论,并互相交换“天啊好恐怖好吓人我可不要去那里”的感慨。&/p&&p&翻翻我自己最近所写的内容,好像对我同龄人所发的牢骚占据了过大的篇幅。只是,一次又一次这样的瞬间,让我看到“常识”是个多么脆弱的东西——比如说,相信“夜晚的巴黎或慕尼黑是个危险到不应出门闲逛的地方”这种说法的人数,一定会大大超乎你的想象。不过,他们倒也不应因此受到过分的苛责,因为输出的前提是输入,做出判断的重要前提之一,就是获取及时、正确的信息。但以高考作为唯一导向的基础教育自然难以顾及信息的获取与处理,当终于拥有较多的自由时间时,不以生产优质内容为先反而忙于投喂情绪的营销号又显然拥有更高的吸引力。那么,作为普通人,我们应该如何高效地选择适合我们的新闻媒体呢?最近,我偶然在知乎上看到了一个叫做“能让你一直保留的新闻类app有哪些”的问题。因此,作为一个非新闻专业从业者,我希望从普通人应该从哪里获取新闻的角度,分享一点感受。&/p&&hr&&p&先说中文新闻。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-01f9a74fcfa6f3fbaf2232_b.jpg& data-rawwidth=&1242& data-rawheight=&1394& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1242& data-original=&https://pic4.zhimg.com/v2-01f9a74fcfa6f3fbaf2232_r.jpg&&&/figure&&p&其中,&b&FT中文网&/b&是我最想推荐的一个。它的内容以观点(Opinion)为主,且并非仅有财经领域的内容,涵盖时政、世界、生活、甚至教育等,十分中肯、清晰。当然,一部分作者的独家专栏,以及全部七天以前的文章,是需要付费成为会员才可以阅读的。这也是我目前唯一一个购买了Paywall的媒体(198元 / 年)。&b&不过,即使仅仅阅读免费内容,也能让人受益非浅&/b&。来自新加坡的《联合早报》也是我比较推荐的。这里更多的是不带评价立场的新闻报导,较为全面、及时。&/p&&p&作为上海报业集团将传统媒体市场化的成功尝试,&b&澎湃新闻由于其具备雄厚的财力以及颇具实力的采编团队,成为一部分相对而言较高质量新闻的生产平台&/b&,其中“思想市场”等原创栏目中的一些评论、原创深度报道以及纪录片等可以作为一种不花太多时间的参考。但相比之下,我更想推荐腾讯新闻的“大家”栏目,这里聚合了许多非常优秀的华语作者,可以在微信上关注小程序来阅读。善用它让用户自主选择关注作者的功能,为自己营造一个充满人文主义色彩的信息环境,这在中文互联网上已经是十分难得了。&/p&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-caf4ef606a812f027e62ddb_b.jpg& data-rawwidth=&1242& data-rawheight=&1819& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1242& data-original=&https://pic1.zhimg.com/v2-caf4ef606a812f027e62ddb_r.jpg&&&figcaption&“大家”栏目中我关注的作者&/figcaption&&/figure&&p&而门户网站的新闻客户端&b&抓取新闻范围更广、更加全面的特点&/b&也很重要,哪怕它们时常含有一些“营养价值”并不太高的内容,每天仅仅花上几分钟浏览一下标题还是有意义的。这一类我选择了网易,因为对它的一些原创栏目(如浪潮工作室)等比较有好感。&/p&&hr&&p&当然,说起优质信息,英文世界才是真正的重头戏。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-ac020d74e95_b.jpg& data-rawwidth=&1242& data-rawheight=&1398& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1242& data-original=&https://pic1.zhimg.com/v2-ac020d74e95_r.jpg&&&/figure&&p&这一组中的四个是我每天都会阅读的。它们的共同特点,是即时性强,任何特大的突发新闻(Breaking News) 都会第一时间播报;且虽然 CNN 有时会被人诟病信息的过度碎片化,但满足迅速准确地过去一手信息是完全没有问题的,相比 BBC,在叙述新闻的同时也会附带更多的 Opinion Piece ,但对我来说,它并非影响客观性的困扰,反而能当我对背景与影响了解不多的时候进行必要补充。最为“保险”的方法是,在你确定了最经常阅读的领域之后,结合你已有的背景知识,挑选一位你认为最专业的记者或制作人 (Producer),用以在自己把握不足的新闻中作为主要参考。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-53e5b53c92bdd864e92cb8dc_b.jpg& data-rawwidth=&1242& data-rawheight=&841& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1242& data-original=&https://pic1.zhimg.com/v2-53e5b53c92bdd864e92cb8dc_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-a086eb9b95826efc0a189dca1733472e_b.jpg& data-rawwidth=&1242& data-rawheight=&1471& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1242& data-original=&https://pic2.zhimg.com/v2-a086eb9b95826efc0a189dca1733472e_r.jpg&&&/figure&&p&&br&&/p&&p&格外值得一题的,是来自美国的数字媒体 SupChina 。它成立的时间并不长,采编团队的人数目前也较少,但亮点是对国内新闻的选题非常详细而全面,别说那些值得一看却并没有重要到出现在主要英文媒体上的新闻,就连“某地成功制作出长达数米的蛋糕”这样的内容都能看到,还时常有富于趣味性的小测试、电影音乐推荐等。&/p&&p&由于我目前还对日韩媒体了解不多,开始使用 NHK 可以说是纯属意外:因为今年寒假去日本旅游在大阪机场候机时看到了 NHK 英语频道的广告,才产生了“试试读一读”的想法。相比欧美英文媒体,它对亚洲新闻的报道自然更加详细,是一个不同视角的很好补充。&/p&&hr&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-76fffec476c17f69eec89_b.jpg& data-rawwidth=&1235& data-rawheight=&1379& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1235& data-original=&https://pic1.zhimg.com/v2-76fffec476c17f69eec89_r.jpg&&&/figure&&p&这个文件夹下的APP,都是用来“听”和“看”的。&/p&&p&&b&“听”真的是一种经常被人忽略,实际上却十分高效的输入方式&/b&:上下课堵在人群中奔向食堂的路上,高峰期的地铁公交车厢里,比起玩几局微信小游戏,听些 Podcast (播客节目)既不伤害眼睛又补充了阅读文字新闻时间不足的遗憾。&/p&&p&iOS 自带的播客商店是个非常好用的工具,在其中你能搜索到海量的、几乎覆盖全部类型与主题的 Podcast 。&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-81d99e522fa4cae3e15b_b.jpg& data-rawwidth=&1242& data-rawheight=&1867& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1242& data-original=&https://pic2.zhimg.com/v2-81d99e522fa4cae3e15b_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-8bd40b05f3947918eebdcd353142cdfa_b.jpg& data-rawwidth=&1242& data-rawheight=&1544& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1242& data-original=&https://pic1.zhimg.com/v2-8bd40b05f3947918eebdcd353142cdfa_r.jpg&&&/figure&&p&&br&&/p&&p&我希望特别推荐的,有 BBC 的 World News 与 NPR 的 Planet Money,前者会把每天你有必要知道的新闻总结在一起用二十分钟左右播报出来,后者是一档科普型的经济节目,用通俗易懂又有趣的方式每期介绍一个经济主题。如果你对美国政治有兴趣,那么由 CNN 明星主播 Kate Bolduan 主持的 State of America 是个不错的选择。&br&&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-42eff99f6d9abc53e6e7ce_b.jpg& data-rawwidth=&1242& data-rawheight=&1016& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1242& data-original=&https://pic2.zhimg.com/v2-42eff99f6d9abc53e6e7ce_r.jpg&&&/figure&&p&NPR 的网页版也是一个“宝库”,作为一个广播电台,其相当多的内容,是既有文字又有音频的,从而让你便于选择最为方便的形式;&b&从内容的角度上讲, NPR 不仅准确、迅速,高度中立性、对左右红蓝没有明显地偏袒也是它经常被人提及的特点。&/b&&/p&&p&除此以外,上文提到过的 SupChina 也是一个创立于2009年的播客节目 Sinica 的播出平台,顾名思义,这是一个探讨中国相关话题的节目,涵盖包括科技、实事、经济、媒体等非常多的主题,两位主持人 Kaiser Kuo 和 Jeremy Goldkorn 是媒体领域非常受尊敬的学者。&/p&&p&如果你想找到一个随时可以通过手机收看的电视台,那么 NHK World 就是一个非常完美的选项。这里的节目以半小时为单位, Newsline新闻与其他一些以旅游、文化、科技等主题的内容交替播出,且拥有后台播放功能,即你可以在锁屏时当作没有画面的广播收听。&/p&&p&最后,如果你恰巧也有学习德语, 德国国家电视一台的 Tagesschau 栏目一定是被老师推荐过的德语学习材料。事实上,从新闻的角度来说,它可以说相当于 NHK 的德国版,是非营利性的公立机构,立场中立,如果你有相应的语言能力,它也是非常好的信息源。&/p&&hr&&figure&&img src=&https://pic3.zhimg.com/v2-eb337e090ecb92e91e0d516_b.jpg& data-rawwidth=&1242& data-rawheight=&1402& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1242& data-original=&https://pic3.zhimg.com/v2-eb337e090ecb92e91e0d516_r.jpg&&&/figure&&p&如果说前文中的即时新闻APP算是工作餐或者家常菜,营养勉强均衡味道也中规中矩但是吃多了难免无聊,&b&那么这一栏里则可以算是精致美味的米其林餐厅料理了&/b&。在我的阅读选择中,既有老牌的《华盛顿邮报》、《纽约客》和《外交政策》,也有新兴的网络杂志 Slate、Politico等——&b&后者有力地证明了即便在网络与社交媒体的冲击之下,极富专业主义的新闻报道依然有广泛的受众&/b&。其中,Sixth Tone 是澎湃新闻的“姐妹媒体”,与澎湃共享新闻资源,时常可见一些质量颇高的报道与评论。&/p&&p&它们的内容分类众多,有即时新闻,有特约作者专栏,有本地/国际之分,也有作者门槛较低的博客区,以及一些高质量 Podcast 。通过阅读它们,你所获得的是对时间全面而深度的理解,有时还可以通过个案来学习一些社会学等领域的专业概念。不过说来惭愧,我还没有购买任何一家媒体的 Paywall(付费门槛),而是“蹭”读它们每月数量有限的免费阅读文章数;一方面是因为作为学生毕竟财力有限,另一方面也是在这个前提下,我还没有找到自己最适合的一到两种杂志。就算如此,它们为我带来的收获也是十分巨大的。在做选择时,大可不必太过着急,也不必心怀太多“愧对创作者”的内疚,顺其自然,最适合自己口味的一家总会出现。&/p&&hr&&p&当然,如果你读到这里,已经准备进入评论区里吐出一些诸如“BBC全是偏见”、“CNN全是谣言”之类的无意义条件反射,那么看来你短期内还并没有走出反智舒适圈的欲望,这些推荐也不太适合你。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-42d8ebc8e_b.jpg& data-rawwidth=&1242& data-rawheight=&1000& data-size=&normal& class=&origin_image zh-lightbox-thumb& width=&1242& data-original=&https://pic2.zhimg.com/v2-42d8ebc8e_r.jpg&&&figcaption&在想法评论区中问过方可成老师一次,为什么有些人会对这些媒体带有这么强的偏见和误解&/figcaption&&/figure&&p&对于其他人来说,选好了合适的途径,接下来需要的就是不小的恒心、毅力来坚持下去、养成习惯了。毕竟,除了语言方面的不熟练会加大阅读难度以外,这些媒体的作品也并不会像大多数营销号一样,两行一个回车键,最精确地揣测你的情绪以挑逗出(大多数情况下)廉价的共鸣,浓厚的专业主义色彩毕竟会让内容有些生涩。&b&坚持下去最大的动力,大概来自随时回想自己的初心&/b&,一方面,你是这个世界的一员,每个角落发生的苦难或进步都通过人类文明和你产生着千丝万缕的联系,&b&获取高质量信息是它们得以维系的重要源泉&/b&;另一方面,我相信你也并不希望自己过早地变得“油腻”——相比去年这个标签红极一时时各大博主争相拿出的健身指导与着装指南,&b&保持需要“用力”的阅读与思考所营造的精神世界也同样重要。&/b&&/p&&p&&i&本文已发表于虎嗅网:&/i&&/p&&a data-draft-node=&block& data-draft-type=&link-card& href=&https://link.zhihu.com/?target=https%3A//www.huxiu.com/article/243942.html& data-image=&https://pic2.zhimg.com/v2-f15d7bc8c31_180x120.jpg& data-image-width=&935& data-image-height=&702& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&战胜反智,从选择新闻开始&/a&&p&&i&欢迎关注我的个人公众号,一个友善分享观点与见解的地方:程贤Allen(ID: allenchan157)&/i&&/p&
我还很清楚地记得几个月前看到那条“德国撒旦画”新闻时的感受。哪怕即使德国并非自己未来留学的目标国从而让我对其的了解要稍多一些,“警察/学校不管”这种有违常识的细节以及低级网络小说一般的手法也让整件事情的真实性显得足够可疑了。可之后的一天里…
&p&刚刚接触数据库的时候,我也有和你一样的困惑。现在想起来,主要还是因为教学模式存在一定的问题,没有把来龙去脉讲清楚,没头没脑的灌输知识,最后不知为何而学,没动力,学着也痛苦。&/p&&p&很多老师也没有想清楚这一点,照本宣科罢了。毕业几年之后,现在我也算是个数据库领域的工程师,来分享我个人的一点见解,结合我个人学习的经验和现在的理解谈谈为什么要学习数据库。&/p&&p&简而言之,因为你学的是《数据库系统&b&原理&/b&》,而不是《数据库系统应用》,更不是《SQL从入门到精通》。只有掌握了原理,才能了解当前的数据库是如何实现的,存在哪些问题,进而不断优化,突破当前数据库系统的局限性,做出更优秀的数据库。&/p&&p&下面的内容会比较长,我会利用一些比较基础地例子和常见事物的类比,给你一个从感性到理性的认识,了解引入这些概念带来的&b&优势&/b&以及这些概念的&b&局限性&/b&。其中也包含很多我个人的理解,不一定对,权当抛砖引玉,是希望能够对你有所帮助。&/p&&h2&&b&什么叫数据库?&/b&&/h2&&p&常说,要“知其然还要知其所以然”。从你的提问来看,你已经初步做到了“知其然”,对数据库的功能有了一个初步的了解,知道数据库的基本功能就是“增删改查”。但是你要知道,关系型数据库只是数据库中的一种。广义上,任何能够满足对数据进行“增删改查”功能的程序,都叫数据库。这世界上就有很多数据库不是关系型数据库,你一定听说过『NoSQL』这个概念. 搜索引擎文档的存储、多媒体和地理信息的数据库,往往都不是使用关系型数据库。另外,最近正逐渐流行的图数据库,也是另一个门类。&/p&&p&这里插播几个趣闻吧,远在计算机庞大而夸张,数据库理论尚未普及的年代,就有了一些充满智慧的数据库技术的应用。下面举两个令我惊叹的例子。&/p&&p&在刘慈欣的小说《三体》中,有一段非常经典的人列计算机描写:&/p&&blockquote&  下面,贯穿人列计算机的系统总线上的轻转兵快速运动起来,总线立刻变成了一条湍急的河流.这河流沿途又分成无数条细小的支流,渗入到各个模块阵列之中。很快,黑白旗的涟漪演化成汹涌的浪潮,激荡在整块主板上。中央的CPU区激荡最为剧烈,像一片燃烧的火药。突然,仿佛火药燃尽,CPU区的扰动渐渐平静下来,最后竟完全静止了,以它为圆心,这静止向各个方向飞快扩散开来,像快速封冻的海面,最后整块主板大部分静止了,其间只有一些零星的死循环在以不变的节奏没有生气地闪动着,显示阵列中出现了闪动的红色。 &br&——《三体》·刘慈欣&/blockquote&&p&书中的描写通过形象地对计算机系统微观世界的类比,展示了一个宏大的场面。但是实际上,小说中用三千万人打造的人列计算机实在太浪费资源了,总共三千万士兵,一个人只表示一个比特位。实际上,以人的智商完全可以执行更复杂的指令,让这套系统的运转更加高效。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-5aff03f0679d_b.jpg& data-size=&normal& data-rawwidth=&434& data-rawheight=&314& class=&origin_image zh-lightbox-thumb& width=&434& data-original=&https://pic3.zhimg.com/v2-5aff03f0679d_r.jpg&&&figcaption&1920年美国指纹数据库&/figcaption&&/figure&&p&先来看一张图吧,估计第一眼大家一定不知道这个图是干什么的——这是1920年代的美国指纹数据库:&a href=&//link.zhihu.com/?target=http%3A//www.wenxuecity.com/news//gossip-116772.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&美国“指纹工厂”:2万人管理着全国7000万指纹(组图)&/a&。&/p&&p&没错,现在我们去美国领事馆签证,或者入境美国的时候摁的指纹信息,早在100年前美国就开始收集了。这是现实版的人列计算机啊!&/p&&figure&&img src=&https://pic3.zhimg.com/v2-5d27d4441be3cfc27a2aba_b.jpg& data-size=&normal& data-rawwidth=&449& data-rawheight=&443& class=&origin_image zh-lightbox-thumb& width=&449& data-original=&https://pic3.zhimg.com/v2-5d27d4441be3cfc27a2aba_r.jpg&&&figcaption&1920年美工指纹数据库工人&/figcaption&&/figure&&figure&&img src=&https://pic3.zhimg.com/v2-46aeb53d1ec399f9ec6c6_b.jpg& data-size=&small& data-rawwidth=&640& data-rawheight=&466& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic3.zhimg.com/v2-46aeb53d1ec399f9ec6c6_r.jpg&&&figcaption&指纹特征分类&/figcaption&&/figure&&p&严格来说, 这个数据库不叫关系型数据库——至少,你不能简单地用MySQL去替代人力的查询。至于什么是关系型数据库,我们稍后再说。&/p&&p&下面来讲另一个,一个叫&a href=&//link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Calvin_Mooers& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Calvin Mooers&/a&的计算机科学家,这个Mooers跟那个提出摩尔定律的 Moore不是一个摩尔。早在二战期间,电子计算机还有两层楼那么大的时候,他就发明了一套编码系统叫做Zatocoding,用来索引海量的文档——而且是纸质文档。&/p&&p&怎么做的呢?它先把相关文档的边缘统一打上洞:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-12fd2ef673fdeb030c054c558ee890d0_b.jpg& data-size=&normal& data-rawwidth=&214& data-rawheight=&220& class=&content_image& width=&214&&&figcaption&采用Zatocoding的文档&/figcaption&&/figure&&p&每一个孔代表的是一个布尔表达式,也就是一个答案为『是』或者『否』的问题。举个例子,这些文档是关于某些天天气状况的,那么每个孔的对应如下问题:&/p&&ol&&li&是否下雨&/li&&li&气温是否大于30℃&/li&&li&气温是否小于0℃&/li&&li&……&/li&&/ol&&p&以此类推,然后,对于每一个答案为『否』的孔,将其剪掉:&/p&&figure&&img src=&https://pic4.zhimg.com/v2-c02fa232efc758e510ddb_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&237& data-rawheight=&204& class=&content_image& width=&237&&&/figure&&p&最后把所有文档用线串起来,有孔的穿孔,没孔的穿洞,就像这样(示意图并没有画全):&/p&&figure&&img src=&https://pic1.zhimg.com/v2-cbb2bb0e2a38b8f65a257e0_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&273& data-rawheight=&194& class=&content_image& width=&273&&&/figure&&p&最后这所有文档将被40条线串起来。然后,当需要查找某个问题为『是』的文档,只需要将其对应的绳子给提起来即可(因为回答为否的洞已经被剪开,提绳子的时候会掉下去),这样绳子上挂着的就都是相关的文档了。同时,这个索引还支持逻辑或运算。利用布尔运算的定律,支持逻辑与运算也是非常简单的。&/p&&p&大名鼎鼎的&a href=&//link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Bloom_filter& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&bloom filter&/a&就是对这个原理的总结提炼。&/p&&p&由此可见,支持增删改查的数据库未必都有表,未必都是关系型数据。&/p&&h2&&b&关系型数据库为什么入选计算机科学与技术的基础课程?&/b&&/h2&&p&因为它“科学”,换句话说,理论发展得比较完善。尚处在发展中,有大量未知问题的领域不太适合作本科基础教学,那种感觉就像高中学物理和学化学的一样,物理把为数不多的几个定理和数据组合一下总能得到结果,而化学感觉是一堆『拍脑袋想出来的规则』加一堆『被疯狂打脸的例外』……这里不是我故意要『黑』一下化学,&a href=&//link.zhihu.com/?target=http%3A//www.sohu.com/a/416& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&大神Matrix67也有同样的感觉&/a&:&/p&&blockquote&之所以在高中时选择学文科,是因为他对化学“很不认同”。高一分专业考试时,他的化学不及格,为了进实验班,只好学了文科。“化学这门学科实在是太不科学了,缺乏内在美。”一提起化学,他总是不住地摇头。&/blockquote&&p&感兴趣的可以看看这个帖子里化学大神们的讨论:&a href=&https://www.zhihu.com/question/& class=&internal&&为什么中学化学给人一种不严谨的感觉?&/a&&/p&&p&注意我这里并不是要否定化学的科学性,因为即便是物理在深入到尚未完善的领域之后依然是一对规则加一堆例外——二十世纪初当人们一度认为物理学已经完备的时候,天空飘来了&a href=&//link.zhihu.com/?target=https%3A//baike.baidu.com/item/%25E7%%25E7%E4%25B8%25A4%25E6%259C%25B5%25E4%25B9%258C%25E4%25BA%2591& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&两朵乌云&/a&,然后引起了物理理论的一场革命。我这里只是想用两个学科学习的直观感受来说明从关系型数据库入手对学生来说更容易。&/p&&p&另一方面,教学配套材料很多,对于学生入门和老师教学来说非常方便,可以让教学更关注于&b&本质&/b&——数据库系统的构建思想。我以为,数据库原理课程的精髓,应当是数据库构建的过程,而数据库本身的使用反而是最不重要的一环。&/p&&p&我曾经在知乎上讨论过另一个问题:&a href=&https://www.zhihu.com/question/& class=&internal&&大学编程入门为什么不以C#作为首选?&/a&其实和这个问题有点类似。你说用C#来教操作系统我支不支持,如果有好的配套材料,比如用C#写好的教学操作系统,我当然支持。但是,现在绝大部分的操作系统底层无一例外是C写的,绝大部分操作系统课的课程作业也是C语言,工业界绝大部分系统级底层应用也是用C写的,而且操作系统课程的核心恰恰不是语言,而是架构的设计——既然如此,何必舍本逐末,舍近求远,把目光放在C还是C#上呢?&/p&&p&那么回到这个问题,同样的,学习数据库原理的目的是什么,是怎么使用吗?一部分目的是,学会了原理能够更好的使用;但是,另一个更重要的目的,是在现有的数据库解决方案不能满足需求的时候,如何利用在构建关系型数据库过程中积累的方法经验,开发在特定场景下更好的数据库应用。&/p&&p&先看看关系型数据库是什么——它是对一类数据库设计经验的总结和设计方法的抽象,以期得到一个通用的数据库的解决方法。&/p&&p&打个比方,小学奥数题鸡兔同笼问题:&/p&&blockquote&有若干只鸡兔同在一个笼子里,从上面数,有35个头,从下面数,有94只脚。问笼中各有多少只鸡和兔?&/blockquote&&p&小学的解法有很多种:&/p&&p&假设法&/p&&blockquote&假设全是鸡:2×35=70(只)&br&鸡脚比总脚数少:94-70=24 (只)&br&兔子比鸡多的脚数:4-2=2(只)&br&兔子的只数:24÷2=12 (只)&br&鸡的只数:35-12=23(只)&br&&br&假设全是兔子:4×35=140(只)&br&兔子脚比总数多:140-94=46(只)&br&兔子比鸡多的脚数:4-2=2(只)&br&鸡的只数:46÷2=23(只)&br&兔子的只数=35-23=12(只)&/blockquote&&p&抬腿法一&/p&&blockquote&假如让鸡抬起一只脚,兔子抬起2只脚,还有94÷2=47(只)脚。笼子里的兔就比鸡的脚数多1,这时,脚与头的总数之差47-35=12,就是兔子的只数。&/blockquote&&p&抬腿法二、抬腿法三……&/p&&p&你看,同一个问题,张三有张三的解法,李四有李四的解法。于是聪明的王五在观察所有方法之后,做了一个总结,解决这个问题我们可以使用一元一次方程:&/p&&blockquote&解:设兔有x只,则鸡有(35-x)只。&br&4x+2(35-x)=94&br&解得 x=12&/blockquote&&p&又进一步,有人发现,&a href=&//link.zhihu.com/?target=http%3A//mp.weixin.qq.com/s%3F__biz%3DMzIyODM2ODk1MA%3D%3D%26mid%3D%26idx%3D1%26sn%3D3ca0c7fb63b77da3bf5d1b%26chksm%3De853b5b9df243caf18fb06ba0b63f4e857cbb252984bfbb0c603a49dd3188f43ef%26scene%3D21%23wechat_redirect& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&牛吃草&/a&问题也可以用方程解,于是在这基础上发展了二元一次方程,甚至N元一次方程。进一步,当研究到更复杂的问题的时候,比如抛物线,行星轨道,发现一次方程不够用了,于是又进一步扩展出了高次方程……&/p&&p&于是,我们的代数系统渐渐发展,变成了如今这样庞大的体系,也足够应付相当一部分应用场景:小商小贩的价格计算、金融模型、天梯轨迹的预测……&/p&&p&数据库也是类似的发展轨迹。 &a class=&member_mention& href=&//www.zhihu.com/people/71d6bdbbaaec880ed62fc6& data-hash=&71d6bdbbaaec880ed62fc6& data-hovercard=&p$b$71d6bdbbaaec880ed62fc6&&@wivwiv&/a& 在回答里提到这样一个例子:&/p&&blockquote&去年作为大三学生去旁听毕业答辩,某同学作品是一个安卓端的英汉词典,支支吾吾吞吞吐吐说不清他数据的存储方式,老师只好降低难度让他把 Apple 的中文改为 梨。&br&他一番摸索,工程下找到了一个 txt 文件,ctrl + f 来把这个翻译对照改了。懂行的憋住笑,不懂行的觉得没毛病,答辩老师一致拍案叫绝,遂过。&br&不懂基本的数据库,你以后得工程要存数据是不是也这样?&/blockquote&&p&其实,这个同学的英汉词典采用这样的存储方式并没有太大的不妥,这恰恰是数据库的某种意义上的基本形态——二维表,也就是关系数据库中的『关系』,应付这种场景足矣。&/p&&p&那么我们先来看看关系型数据库到底试图解决一个什么样的问题?ACID:&/p&&ul&&li&Atomicity:原子性&/li&&li&Consistency:一致性&/li&&li&Isolation:隔离性&/li&&li&Duration:持久性&/li&&/ul&&p&这里我就不详细展开了,需要了解的去看课本。在这其中,『一致性』是重中之重。&/p&&h2&为什么要学范式?&/h2&&p&在你困惑的那些概念中,各种所谓的『范式』很大程度上就是为一致性提供服务的。&/p&&p&就拿&a href=&//link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/First_normal_form& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&1NF&/a&(关系中的每个属性都不可再分)来说吧,乍看好像没什么用,但是上次我看到这个问题的讨论就忍俊不禁:&a href=&https://www.zhihu.com/question/& class=&internal&&如何劝说后端开发不要拿变量命名 JSON 的key值?&/a&&/p&&p&&a class=&member_mention& href=&//www.zhihu.com/people/ec1c63ce73e8bc4f9c3b8& data-hash=&ec1c63ce73e8bc4f9c3b8& data-hovercard=&p$b$ec1c63ce73e8bc4f9c3b8&&@max poon&/a& 的回答:&/p&&blockquote&问问他,如果以后需要加多一个author属性,他准备如何拓展。&/blockquote&&p&&a class=&member_mention& href=&//www.zhihu.com/people/b364d5f692d& data-hash=&b364d5f692d& data-hovercard=&p$b$b364d5f692d&&@Axetroy&/a& 回复:&/p&&blockquote&然后后端一听, 这简单, 看我的 &br&[{'书籍1':&500|作者1&},{'书籍2':&180|作者2&},{...},...]&/blockquote&&p&你可以仔细思考一下,如果在创建表的时候不遵循1NF,查询的时候会导致什么样的后果?1NF又给我们查询带来了哪些方便?显然,其中一个好处就是,查询的时候不需要再对得到的内容进一步解析。&/p&&p&那么&a href=&//link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Second_normal_form& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&2NF&/a&、&a href=&//link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Third_normal_form& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&3NF&/a&乃至&a href=&//link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Boyce%25E2%Codd_normal_form& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&BCNF&/a&又是用来解决什么问题的呢? &a class=&member_mention& href=&//www.zhihu.com/people/0d99df288b4c7fe2eff8b851cac20807& data-hash=&0d99df288b4c7fe2eff8b851cac20807& data-hovercard=&p$b$0d99df288b4c7fe2eff8b851cac20807&&@刘慰&/a& 老师的回答非常清晰和详细,可以参阅:&a href=&https://www.zhihu.com/question/& class=&internal&&解释一下关系数据库的第一第二第三范式?&/a&如果认真读完,你应该能够有一个清晰的认识,限于篇幅和时间,我在这里就不展开了。&/p&&h2&为什么要学关系代数?&/h2&&p&简单来说,就是关系代数是对关系数据库查询所做的抽象。抽象的好处是减少人脑的负担,有了抽象之后,我们可以忽略掉工程上的细节,更清晰地看到某些问题的本质,从而从数学上做一些推理和优化:当一切都变成表达式之后,我们就可以利用数学性质做推理了,而不必去关心实现的细节——因为那都是抽象之后可以忽略的底层信息。&/p&&p&其实,从本质上来说,『关系代数』与『线性代数』和『布尔代数』并没有什么区别,如果你学过『抽象代数』的话应该会有更深的体会。&/p&&p&一个例子便是计算优化。线性代数是大学生的必修课程,在这里我就举一个简单的例子,线性代数中的&a href=&//link.zhihu.com/?target=https%3A//zh.wikipedia.org/wiki/%25E7%259F%25A9%25E9%%23%25E7%259F%25A9%25E9%%25E4%25B9%%25B3%2595& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&矩阵乘法&/a&运算满足结合律与左右分配律。对于多个矩阵连乘的计算,使用不同的计算顺序会导致计算量千差万别。如果能按照计算量最小的矩阵乘法顺序进行计算,可以大大加速矩阵乘法的计算——这是一个经典的动态规划算法应用:&a href=&//link.zhihu.com/?target=https%3A//blog.csdn.net/liufeng_king/article/details/8497607& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&0010算法笔记--【动态规划】矩阵连乘问题 - CSDN博客&/a&&/p&&p&同样的,在关系代数里,也有可以用类似的方法加速计算。比方说,『自然连接』,也就是SQL里的『natural join』操作也满足结合律,这样就大大方便了计算优化。如果你了解join的底层实现,不论是hash join,还是nested loop join,抑或是其他任何算法,一般来说,需要join的两个表行数越多,计算量越大。那么,越早做哪些让行数减少的join,之后的join的计算量就越小,而连续join的次数越多,这个差异就越大。&/p&&p&对于如下这个稍微复杂一点的SQL查询:&/p&&div class=&highlight&&&pre&&code class=&language-plpgsql&&&span class=&k&&SELECT&/span&
&span class=&n&&people&/span&&span class=&mf&&.&/span&&span class=&k&&name&/span&&span class=&p&&,&/span&
&span class=&n&&orgunits&/span&&span class=&mf&&.&/span&&span class=&n&&longname&/span&&span class=&p&&,&/span&
&span class=&n&&people&/span&&span class=&mf&&.&/span&&span class=&n&&email&/span&&span class=&p&&,&/span&
&span class=&n&&affiliations&/span&&span class=&mf&&.&/span&&span class=&n&&starting&/span&&span class=&p&&,&/span&
&span class=&n&&count&/span&&span class=&p&&(&/span&&span class=&k&&DISTINCT&/span& &span class=&n&&subjects&/span&&span class=&mf&&.&/span&&span class=&n&&code&/span&&span class=&p&&)&/span&
&span class=&k&&FROM&/span&
&span class=&n&&staff&/span&
&span class=&k&&JOIN&/span& &span class=&n&&people&/span& &span class=&k&&ON&/span& &span class=&n&&staff&/span&&span class=&mf&&.&/span&&span class=&n&&id&/span& &span class=&o&&=&/span& &span class=&n&&people&/span&&span class=&mf&&.&/span&&span class=&n&&id&/span&
&span class=&k&&JOIN&/span& &span class=&n&&affiliations&/span& &span class=&k&&ON&/span& &span class=&n&&affiliations&/span&&span class=&mf&&.&/span&&span class=&n&&staff&/span& &span class=&o&&=&/span& &span class=&n&&people&/span&&span class=&mf&&.&/span&&span class=&n&&id&/span&
&span class=&k&&JOIN&/span& &span class=&n&&staff_roles&/span& &span class=&k&&ON&/span& &span class=&n&&staff_roles&/span&&span class=&mf&&.&/span&&span class=&n&&id&/span& &span class=&o&&=&/span& &span class=&n&&affiliations&/span&&span class=&mf&&.&/span&&span class=&k&&role&/span&
&span class=&k&&JOIN&/span& &span class=&n&&orgunits&/span& &span class=&k&&ON&/span& &span class=&n&&orgunits&/span&&span class=&mf&&.&/span&&span class=&n&&id&/span& &span class=&o&&=&/span& &span class=&n&&affiliations&/span&&span class=&mf&&.&/span&&span class=&n&&orgunit&/span&
&span class=&k&&JOIN&/span& &span class=&n&&orgunit_types&/span& &span class=&k&&ON&/span& &span class=&n&&orgunits&/span&&span class=&mf&&.&/span&&span class=&n&&utype&/span& &span class=&o&&=&/span& &span class=&n&&orgunit_types&/span&&span class=&mf&&.&/span&&span class=&n&&id&/span&
&span class=&k&&JOIN&/span& &span class=&n&&course_staff&/span& &span class=&k&&ON&/span& &span class=&n&&course_staff&/span&&span class=&mf&&.&/span&&span class=&n&&staff&/span& &span class=&o&&=&/span& &span class=&n&&staff&/span&&span class=&mf&&.&/span&&span class=&n&&id&/span&
&span class=&k&&JOIN&/span& &span class=&n&&courses&/span& &span class=&k&&ON&/span& &span class=&n&&courses&/span&&span class=&mf&&.&/span&&span class=&n&&id&/span& &span class=&o&&=&/span& &span class=&n&&course_staff&/span&&span class=&mf&&.&/span&&span class=&n&&course&/span&
&span class=&k&&JOIN&/span& &span class=&n&&subjects&/span& &span class=&k&&ON&/span& &span class=&n&&subjects&/span&&span class=&mf&&.&/span&&span class=&n&&id&/span& &span class=&o&&=&/span& &span class=&n&&courses&/span&&span class=&mf&&.&/span&&span class=&n&&subject&/span&
&span class=&k&&WHERE&/span&
&span class=&n&&affiliations&/span&&span class=&mf&&.&/span&&span class=&n&&isprimary&/span& &span class=&o&&=&/span& &span class=&k&&TRUE&/span&
&span class=&k&&AND&/span& &span class=&n&&staff_roles&/span&&span class=&mf&&.&/span&&span class=&k&&name&/span& &span class=&o&&=&/span& &span class=&s1&&'Head of School'&/span&
&span class=&k&&AND&/span& &span class=&n&&affiliations&/span&&span class=&mf&&.&/span&&span class=&n&&ending&/span& &span class=&k&&IS&/span& &span class=&k&&NULL&/span&
&span class=&k&&AND&/span& &span class=&n&&orgunit_types&/span&&span class=&mf&&.&/span&&span class=&k&&name&/span& &span class=&o&&=&/span& &span class=&s1&&'School'&/span&
&span class=&k&&AND&/span& &span class=&n&&course_staff&/span&&span class=&mf&&.&/span&&span class=&n&&staff&/span& &span class=&o&&=&/span& &span class=&n&&people&/span&&span class=&mf&&.&/span&&span class=&n&&id&/span&
&span class=&k&&GROUP&/span& &span class=&k&&BY&/span&
&span class=&n&&people&/span&&span class=&mf&&.&/span&&span class=&k&&name&/span&&span class=&p&&,&/span&
&span class=&n&&orgunits&/span&&span class=&mf&&.&/span&&span class=&n&&longname&/span&&span class=&p&&,&/span&
&span class=&n&&people&/span&&span class=&mf&&.&/span&&span class=&n&&email&/span&&span class=&p&&,&/span&
&span class=&n&&affiliations&/span&&span class=&mf&&.&/span&&span class=&n&&starting&/span&
&span class=&k&&HAVING&/span&
&span class=&n&&count&/span&&span class=&p&&(&/span&&span class=&n&&subjects&/span&&span class=&mf&&.&/span&&span class=&n&&code&/span&&span class=&p&&)&/span& &span class=&o&&&&/span& &span class=&mf&&0&/span&
&span class=&k&&ORDER&/span& &span class=&k&&BY&/span&
&span class=&n&&people&/span&&span class=&mf&&.&/span&&span class=&k&&name&/span& &span class=&k&&ASC&/span&&span class=&p&&;&/span&
&/code&&/pre&&/div&&p&调用explain命令来看看postgres内部是如何执行这个查询的,这就是所谓的query plan:&/p&&div class=&highlight&&&pre&&code class=&language-text&& GroupAggregate
(cost=634.26..634.32 rows=2 width=82)
Group Key: people.name, orgunits.longname, people.email, affiliations.starting
Filter: (count(subjects.code) & 0)
(cost=634.26..634.27 rows=2 width=83)
Sort Key: people.name, orgunits.longname, people.email, affiliations.starting
Nested Loop
(cost=28.48..634.25 rows=2 width=83)
Nested Loop
(cost=28.19..633.53 rows=2 width=78)
Nested Loop
(cost=27.91..633.21 rows=1 width=90)
Nested Loop
(cost=27.61..632.84 rows=1 width=90)
Nested Loop
(cost=27.32..301.62 rows=1 width=82)
Nested Loop
(cost=27.03..300.80 rows=1 width=39)
Join Filter: (affiliations.role = staff_roles.id)
Seq Scan on staff_roles
(cost=0.00..18.05 rows=1 width=4)
Filter: ((name)::text = 'Head of School'::text)
(cost=27.03..271.74 rows=881 width=43)
Hash Cond: (affiliations.orgunit = orgunits.id)
Seq Scan on affiliations
(cost=0.00..202.85 rows=8807 width=16)
Filter: (isprimary AND (ending IS NULL))
(cost=26.22..26.22 rows=65 width=35)
(cost=1.14..26.22 rows=65 width=35)
Hash Cond: (orgunits.utype = orgunit_types.id)
Seq Scan on orgunits
(cost=0.00..17.48 rows=648 width=39)
(cost=1.12..1.12 rows=1 width=4)
Seq Scan on orgunit_types
(cost=0.00..1.12 rows=1 width=4)
Filter: ((name)::text = 'School'::text)
Index Scan using people_pkey on people
(cost=0.29..0.82 rows=1 width=43)
Index Cond: (id = affiliations.staff)
Index Only Scan using course_staff_pkey on course_staff
(cost=0.29..331.08 rows=14 width=8)
Index Cond: (staff = people.id)
Index Scan using courses_pkey on courses
(cost=0.29..0.36 rows=1 width=8)
Index Cond: (id = course_staff.course)
Index Only Scan using staff_pkey on staff
(cost=0.29..0.32 rows=1 width=4)
Index Cond: (id = people.id)
Index Scan using subjects_pkey on subjects
(cost=0.29..0.36 rows=1 width=13)
Index Cond: (id = courses.subject)
&/code&&/pre&&/div&&p&简单解释一下,这里面第一行的GroupAggregate和后面行-&后跟着的表示一个基本操作,基本上可以对应到关系代数中的各种运算,比如GroupAggregate就是聚集运算,Hash Join是Join的一种实现方式,等等;缩进代表的是这些操作的隶属关系。&/p&&p&看到了吧,这就是所谓隐藏在关系代数背后的细节——的一部分。跟原始的query比较一下,你会发现join的顺序已经发生了改变。括号内你可以看到每一个操作的cost,它的join是从cost最小的开始的(你可以理解为产生的行数最少),这就是利用关系运算的定律以及数据库本身的统计信息来计算的优化。当然了,这样的计算是粗糙的,有时候结果未必是最优的,具体可以看看这个例子:&a href=&//link.zhihu.com/?target=https%3A//amplitude.engineering/how-a-single-postgresql-config-change-improved-slow-query-performance-by-50x-b0& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&How a single PostgreSQL config change improved slow query performance by 50x&/a&,就是因为数据库的默认设置是机械硬盘,而使用的是固态硬盘,导致cost的计算出现了偏差。&/p&&p&更多采用关系代数对数据查询进行优化的例子可以看这里,我也就不展开了:&a href=&//link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Relational_algebra%23Use_of_algebraic_properties_for_query_optimization& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Relational algebra&/a&&/p&&h2&关系型数据库的不足&/h2&&p&前面说到,我们目前的代数体系已经相当庞大,涵盖了我们生活的方方面面。但是寄希望于在代数体系内解决一切问题是&a href=&//link.zhihu.com/?target=https%3A//blog.csdn.net/pongba/article/details/1336028& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&不可能&/a&的:&/p&&blockquote&哥德尔的不完备性定理证明了数学是一个未完结的学科,永远有需要我们以人的头脑从系统之外去用我们独有的直觉发现的东西。&/blockquote&&p&高度发展的代数系统尚且如此,更何况才发展不到百年的数据库系统呢?关系代数作为关系型数据库的理论基础,它的局限性也是关系型数据库的&a href=&//link.zhihu.com/?target=https%3A//zh.wikipedia.org/wiki/%25E5%%25E7%25B3%25BB%25E4%25BB%25A3%25E6%_%28%25E6%%25E6%258D%25AE%25E5%25BA%2593%29& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&局限性&/a&——正如同&a href=&//link.zhihu.com/?target=https%3A//zh.wikipedia.org/wiki/%25E5%E6%259C%25BA%25E9%2597%25AE%25E9%25A2%2598& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&停机问题&/a&指出了图灵机的局限性一样。由于我数理逻辑学得并不好,这里不敢不懂装懂,理论方面没法解释,只能从一些别的角度来探讨了。&/p&&p&理论虽然简单优雅,可是实践起来逃不开软硬件的限制。&/p&&p&&b&一致性带来的性能问题&/b&&/p&&p&鉴于一致性的种类很多,这里就说强一致性。为了提升数据库的性能,往往采用多线程进行实现。而为了保证强一致性,在读写操作里面就需要加锁。当然,最简单的方法是给整个数据库加一个互斥锁——这样正确性保证了,性能却不行了。于是就有考虑更细粒度的加锁。数据库中B+树如此重要,除了读写上有优势之外,更重要的原因是它加锁很方便——当然了,方便只是相对而言的,真正实现起来非常繁琐——如果你已经上了系统课就应该了解,一旦牵涉到锁,问题就多了:死锁、活锁、饥饿……这些都是需要考虑的问题,当这个问题被抽象出来之后,就有了下面这张表:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-cfd5cdbf896d32f686c631c8_b.jpg& data-size=&small& data-rawwidth=&697& data-rawheight=&407& class=&origin_image zh-lightbox-thumb& width=&697& data-original=&https://pic1.zhimg.com/v2-cfd5cdbf896d32f686c631c8_r.jpg&&&figcaption&SQL Server Lock Table&/figcaption&&/figure&&p&我们需要小心翼翼地去使用锁,才能够避免上述问题的发生——光这一个话题,就有好多论文了。而近几年微软弄出了一套叫做BW-树的结构,使用原子操作和特殊的维护方法避免掉了锁的使用:&a href=&//link.zhihu.com/?target=https%3A//www.microsoft.com/en-us/research/publication/the-bw-tree-a-b-tree-for-new-hardware/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&The Bw-Tree: A B-tree for New Hardware Platforms - Microsoft Research&/a&&/p&&p&同时,一致性的要求还会引起分布式系统之间的同步问题,这个话题也比较广,在这里也就不展开了。&/p&&p&&b&连接的开销&/b&&/p&&p&关系型数据库的核心就是连接,然而join本身是一个比较重的操作。如果你对数据库内部两个表怎么join不是很了解的话,你可以思考思考一下你会怎么去实现?&/p&&p&其实原理很简单,最最基本的就是,如果有索引可以用hash join,没有index就只能两层for循环对两个表进行遍历了——当然,为了提高缓存命中率,有一个常见的优化技巧是分块for循环,但本质上还是两层for循环。&/p&&p&然而,由于关系型数据库本身的存储和索引方式,join操作的开销依然非常巨大。&/p&&p&有一种非常常见的情况就是社交网络的N步邻居查询。假设我们有一个表people (id int, name text),还有一个表friend (from int, to int, attr1 type1, att2 type2, ...),假设我们要查3步邻居怎么办?得这么做:&/p&&div class=&highlight&&&pre&&code class=&language-text&&SELECT DISTINCT friend_3.id
FROM people
JOIN friend friend_1 ON friend_1.from = people.id
JOIN friend friend_2 ON friend_2.from = friend_1.to
JOIN friend friend_3 ON friend_3.from = friend_2.to
WHERE ...;
&/code&&/pre&&/div&&p&当然,对于这种查询,经常会有一些每一步查询计算量都是指数级增长,缓存命中率直线下降。更致命的是,它只能单点查询,如果想同时对多个点查询,只能分别执行多个SQL语句,加剧锁带来的资源消耗和性能下降。另一方面,要写递归查询、不定长度的查询非常困难。&/p&&p&所以,在反洗钱、电话诈骗等深度链接分析的应用领域,图数据库开始崛起——我说的是真·图数据库,那种给关系型数据库套壳的不算。&/p&&p&&b&关系模型往往不是最自然的抽象&/b&&/p&&p&之前说了,为了方便查询的实现和对查询进行优化,加入了各种范式。但是这些范式往往限制了我们用直接的方法去建立模型。比如说,一个常用的数据库测试数据集是TPC-H,先来看看它的表结构:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-d52dc0190bc_b.jpg& data-size=&small& data-rawwidth=&1080& data-rawheight=&1018& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&https://pic1.zhimg.com/v2-d52dc0190bc_r.jpg&&&figcaption&TPC-H表&/figcaption&&/figure&&p&注意看左边的SUPPLIER表和PART表,它们的关系靠PARTSUPP这个表连接起来。但是在实际情形中,应该是PART-SUPPILER两个实体直接连接,同时这个连接上附带了一些属性而已。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-43fe03d836_b.jpg& data-size=&small& data-rawwidth=&813& data-rawheight=&649& class=&origin_image zh-lightbox-thumb& width=&813& data-original=&https://pic3.zhimg.com/v2-43fe03d836_r.jpg&&&figcaption&图数据库TigerGraph中的Schema&/figcaption&&/figure&&p&在这个问题上,图数据库的建模就比关系型数据库直观很多。如上图所示,这是一个用来表示公司之间投资关系的Schema,如果是关系型数据库,CompanyInvestCompany需要单独建一个表来存储,查询的时候需要Company JOIN CompanyInvestCompany JOIN Company,作两个JOIN操作,非常耗时,而图数据库只需要一步。&/p&&h2&最后&/h2&&p&我啰啰嗦嗦地从小学奥数讲到数据库,列举了题主所提到的概念在数据库中的应用,以及当前关系型数据库的各种局限性,就是希望用我的经历给有同样疑惑的朋友一点启发,因为我也曾面临同样的迷茫,学而不知为何所学的效率是最低的。这里面有许多东西都是我到了研究生,甚至工作以后才慢慢有所领悟,可是这些其实本科阶段完全可以有比较深入和透彻的理解。&/p&&h2&&br&参考&/h2&&p&&a href=&https://www.zhihu.com/question/& class=&internal&&解释一下关系数据库的第一第二第三范式?&/a&&br&&a href=&//link.zhihu.com/?target=http%3A//www.cs.cmu.edu/%7Echristos/courses/826.S16/FOILS-pdf/220_text2.pdf& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&cs.cmu.edu/~christos/co&/span&&span class=&invisible&&urses/826.S16/FOILS-pdf/220_text2.pdf&/span&&span class=&ellipsis&&&/span&&/a&&br&&a href=&//link.zhihu.com/?target=https%3A//baike.baidu.com/item/%25E9%25B8%25A1%25E5%E5%E7%25AC%25BC/5907332& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&鸡兔同笼(一种数学奥数题目)_百度百科&/a&&br&&a href=&//link.zhihu.com/?target=https%3A//blog.csdn.net/pongba/article/details/1336028& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&康托尔、哥德尔、图灵--永恒的金色对角线(rev#2) - CSDN博客&/a&&br&&a href=&https://www.zhihu.com/question/& class=&internal&&非关系型数据库和关系型数据库区别,优势比较?&/a&&br&&a href=&//link.zhihu.com/?target=https%3A//zh.wikipedia.org/wiki/%25E5%%25E7%25B3%25BB%25E4%25BB%25A3%25E6%_%28%25E6%%25E6%258D%25AE%25E5%25BA%2593%29& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&关系代数 (数据库)&/a&&br&&a href=&//link.zhihu.com/?target=https%3A//insidebigdata.com//interview-dr-yu-xu-ceo-founder-tigergraph/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Interview: Dr. Yu Xu, CEO and Founder of TigerGraph - insideBIGDATA&/a&&/p&
刚刚接触数据库的时候,我也有和你一样的困惑。现在想起来,主要还是因为教学模式存在一定的问题,没有把来龙去脉讲清楚,没头没脑的灌输知识,最后不知为何而学,没动力,学着也痛苦。很多老师也没有想清楚这一点,照本宣科罢了。毕业几年之后,现在我也算…
&p&推荐一款冷门的系统维护工具 &a href=&//link.zhihu.com/?target=https%3A//www.wisecleaner.com.cn/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Wise System Monitor&/a&&/p&&a class=&video-box& href=&//link.zhihu.com/?target=https%3A//www.zhihu.com/video/625536& target=&_blank& data-video-id=&& data-video-playable=&true& data-name=&& data-poster=&https://pic1.zhimg.com/80/v2-153ac131abb571c_b.jpg& data-lens-id=&625536&&
&img class=&thumbnail& src=&https://pic1.zhimg.com/80/v2-153ac131abb571c_b.jpg&&&span class=&content&&
&span class=&title&&&span class=&z-ico-extern-gray&&&/span&&span class=&z-ico-extern-blue&&&/span&&/span&
&span class=&url&&&span class=&z-ico-video&&&/span&https://www.zhihu.com/video/625536&/span&
&/a&&p&&b&(视频才是重点哦!)&/b&&/p&&p&&br&&/p&&p&有时候我们觉得网速变慢,又或者被黑客入侵、中了病毒,非专业的你当然不可能知道怎么查看背后的原因,其实,&b&我们只需要一款系统维护工具——Wise System Monitor&/b&&/p&&p&&br&&/p&&p&&br&&/p&&p&这是一款非常小巧实用的系统维护工具。安装之后,在界面中的进程监控,即可看到所有正在运行的程序占用的 CPU、内存、接收和发送文件统计、接收和发送文件的速度,&b&甚至是谁正在使用它&/b&;&/p&&p&&br&&/p&&p&如果某个软件占用了奇多的流量、或者正在无限制地向你的电脑发送文件,&b&你就能一眼看出来,然后搞死它;&/b&什么软件对你的电脑友好,什么软件不友好,你也不用再到处问评测了;&/p&&p&&br&&/p&&p&在硬件监控当中,&b&你可以看到电脑几乎所有的硬件参数,&/b&当你电脑出了问题,咨询朋友或者专业人士,他们都会问,你显卡是什么啊?内存有多少啊?打开软件告诉他就好了,不再懵逼;&/p&&p&&br&&/p&&p&另外,你还能在操作系统这里看到你目前的系统详细情况。&/p&&p&&br&&/p&&p&这款软件会有一个轻巧的浮动球,显示上传、下载网速,内存和 CPU的占用、以及硬件温度,细节到某浏览器、程序的网速,以及具体元器件的温度。&/p&&p&&br&&/p&&p&你可以到 Wise 的官方网站下载该软件,也可以直接在 Topbook 微信公众号后台回复 &b&系统监控&/b& 获取中文版的下载链接。&/p&&p&&br&&/p&&p&&b&收藏不要忘记点赞,白嫖可不太好呀!(●'?'●)&/b&&/p&
推荐一款冷门的系统维护工具 (视频才是重点哦!) 有时候我们觉得网速变慢,又或者被黑客入侵、中了病毒,非专业的你当然不可能知道怎么查看背后的原因,其实,我们只需要一款系统维护工具——Wise System Monitor 这是一款非常小巧实…
&figure&&img src=&https://pic2.zhimg.com/v2-6b9debb40b_b.jpg& data-rawwidth=&500& data-rawheight=&316& class=&origin_image zh-lightbox-thumb& width=&500& data-original=&https://pic2.zhimg.com/v2-6b9debb40b_r.jpg&&&/figure&&h2&1、前言&/h2&&p&微信朋友圈包括图片和视频两套业务架构组成,朋友圈图片的特点是请求量大、消耗计算资源较多,视频则主要消耗带宽。&/p&&p&朋友圈的数据是永远存储的,而且随着业务的快速发展,存储容量、带宽和设备的消耗大量增加,尤其重大节日带来的使用量增长,更加剧了消耗,也给运维人员的保障带来了巨大压力。&/p&&p&&b&在重在节假日节点,技术保障主要由三方面组成:&/b&&/p&&p&1)软件保障指通过程序、业务逻辑层面的优化和评估,减轻负载;&/p&&p&2)硬件保障主要指带宽、机器负载的评估和扩容;&/p&&p&3)柔性措施指的是通过业务调整,降低一些不重要特性的资源,来保障重点特性的正常运行。&/p&&p&&b&学习交流:&/b&&/p&&blockquote&- 即时通讯开发交流3群:&a href=&https://link.zhihu.com/?target=https%3A//link.jianshu.com/%3Ft%3Dhttp%253A%252F%252Fshang.qq.com%252Fwpa%252Fqunwpa%253Fidkey%253D051ed62f79eaf622dd5b1c87b26bedb890b068be79dd2006fc80ccf& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&&/a&[推荐]&br&- 移动端IM开发入门文章:《&a href=&https://link.zhihu.com/?target=https%3A//link.jianshu.com/%3Ft%3Dhttp%3A//www.52im.net/thread-464-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&新手入门一篇就够:从零开发移动端IM&/a&》&/blockquote&&p&(本文同步发布于:&a href=&https://link.zhihu.com/?target=https%3A//link.jianshu.com/%3Ft%3Dhttp%253A%252F%252Fwww.52im.net%252Fthread-.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&http://www.52im.net/thread-.html&/a&)&/p&&h2&2、相关文章&/h2&&p&《&a href=&https://link.zhihu.com/?target=https%3A//link.jianshu.com/%3Ft%3Dhttp%253A%252F%252Fwww.52im.net%252Fthread-178-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&微信朋友圈海量技术之道PPT [附件下载]&/a&》&/p&&p&《&a href=&https://link.zhihu.com/?target=https%3A//link.jianshu.com/%3Ft%3Dhttp%253A%252F%252Fwww.52im.net%252Fthread-177-1-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&架构之道:3个程序员成就微信朋友圈日均10亿发布量[有视频]&/a&》&/p&&h2&3、软件架构方面的保障&/h2&&p&&b&朋友圈整体情况如下图所示:&/b&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-e4cdb7b784_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&646& data-rawheight=&590& class=&origin_image zh-lightbox-thumb& width=&646& data-original=&https://pic1.zhimg.com/v2-e4cdb7b784_r.jpg&&&/figure&&p&&br&&/p&&p&&b&朋友圈的架构主要分为OC和IDC两种:&/b&&/p&&blockquote&IDC指的是数据中心,即数据最终落地存储的地方;&br&OC指的是带外网的独立机房,SOC指规模较大的OC。&/blockquote&&p&每个IDC都有一整套接口机/逻辑设备/存储设备用以支撑用户的上传下载、及文件落地存储的需求。&/p&&p&OC点的主要作用是提供外网访问,承载用户的下载流量。每个OC内的设备,一起组成一个缓存池,用户下载时,本地OC中缓存不命中,才到IDC去回源拉取文件。每个OC的功能都是相同的,用户一般到就近的OC点下载,当单个OC点故障时,会通过重试或者切换让用户到其他OC点下载,确保下载成功。&/p&&h2&4、容灾及重试机制&/h2&&p&朋友圈的模块容灾主要是实现单机故障时的自动剔除,主要形式是通过master管理服务器的ip列表,通过心跳探测等方式找到异常设备,并屏蔽故障ip,不返回给前端使用。&/p&&p&&b&以front层的单机剔除为例:&/b&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-48848dbb5dfde650c0f9_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&588& data-rawheight=&111& class=&origin_image zh-lightbox-thumb& width=&588& data-original=&https://pic4.zhimg.com/v2-48848dbb5dfde650c0f9_r.jpg&&&/figure&&p&&br&&/p&&p&如果整个OC或IDC点碰到故障,由于变动较大,一般依赖运维人员手工切换来恢复,或者通过模块之间的重试机制来保障。&/p&&p&&b&朋友圈下载的重试:&/b&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-7caa29d3e7ddf3d8ebedbd2a_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&687& data-rawheight=&205& class=&origin_image zh-lightbox-thumb& width=&687& data-original=&https://pic2.zhimg.com/v2-7caa29d3e7ddf3d8ebedbd2a_r.jpg&&&/figure&&p&&br&&/p&&p&不管是用户到OC的下载过程,还是OC到IDC的回源过程,默认都会进行2次失败后的重试,并且重试一定会选择异地的接入点,避免继续重试到故障的节点。实现的原理是每一层master都会返回给前端至少两组ip列表,并保证两组ip列表为异地节点,前端失败时才可以实现异地重试。&/p&&p&&b&但重试由于会造成请求的增加,所以是把双刃剑,节日高峰期间由于请求本身涨幅已经很高,重试更容易引发问题,需要进行调整:&/b&&/p&&p&1)通过master路由下发,关闭重试。在元旦/春节这种请求有数倍增长的节日实行;&/p&&p&2)值班人员严密监控,如果IDC失败率超过20%,则紧急手工关闭重试。这种在中秋/国庆这种增长并不高的节日实行。&/p&&p&&b&Front模块的重试控制界面:&/b&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-f67c5c8a4c_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&700& data-rawheight=&310& class=&origin_image zh-lightbox-thumb& width=&700& data-original=&https://pic2.zhimg.com/v2-f67c5c8a4c_r.jpg&&&/figure&&p&&br&&/p&&h2&5、硬件方面的保障&/h2&&h2&5.1 容量评估和设备扩容&/h2&&p&重要节日前运维人员会连同资源组,根据业务预算和业务增长的需求及实际负载,进行各个机房、模块的设备扩容。预算以外的请求上涨,则通过柔性或者过载的方式,进行降低或者拒绝。&/p&&p&&b&评估方法:&/b&&/p&&p&1)机房容量主要根据交换机带宽的上限评估;&/p&&p&2)接入层设备容量主要根据CPU、内存的负载比例、网卡的流量/包量占比来评估;&/p&&p&3)存储层设备容量主要根据CPU、内存的负载比例、磁盘IO的读写次数来评估。&/p&&h2&5.2 春节朋友圈上传负载&/h2&&figure&&img src=&https://pic4.zhimg.com/v2-472becb3500cb6bdc0ba3e8a7be2d683_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&685& data-rawheight=&569& class=&origin_image zh-lightbox-thumb& width=&685& data-original=&https://pic4.zhimg.com/v2-472becb3500cb6bdc0ba3e8a7be2d683_r.jpg&&&/figure&&p&&br&&/p&&p&业务侧春节要求的增长比例,是上传支持9倍增长,下载支持1倍增长,超过这个比例的请求可以拒绝掉,但根据预算扩容后,达到上图的效果,还是有部分模块无法支持这个涨幅,尤其是压缩compress模块,该模块每支持一倍增长就需要大量虚拟机扩容,预算内无法支持,这样就需要使用柔性策略来解决。&/p&&h2&6、柔性策略简介&/h2&&p&&b&朋友圈的柔性策略分为两层:&/b&&/p&&p&&b&第一层是粗暴柔性:&/b&即按比例、接业务直接限制上传下载的请求,被限制的请求会返回给用户失败,与微信C2C相同,这种一般用于超过系统预估的负载能力,造成系统故障时用于快速恢复业务时使用;&/p&&p&&b&第二层是按业务特性柔性:&/b&即从业务层面通过降低图片视频清晰度、延迟用户更新等方向降低系统的负载。下面主要详述业务柔性。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-5dbbd76fe5d5f_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&700& data-rawheight=&348& class=&origin_image zh-lightbox-thumb& width=&700& data-original=&https://pic3.zhimg.com/v2-5dbbd76fe5d5f_r.jpg&&&/figure&&p&&br&&/p&&p&朋友圈业务的主要增长与瓶颈:从前文的设备负载评估图看,在预算范围内,接入层和逻辑层都只能支撑5倍增长,而压缩compress模块只能支撑1倍增长。&/p&&h2&7、柔性实践之:压缩compress柔性&/h2&&p&Compress模块的作用是将客户端上传来的原始图片按需求压缩成各种格式和尺寸,以支持特定的业务场景,并且节省存储空间和带宽。由于压缩技术的不断发展,使用更先进的压缩格式,同等清晰度的图片压缩比例越高,需要消耗的压缩计算资源就越多。&/p&&figure&&img src=&

我要回帖

更多关于 服务器日常维护内容 的文章

 

随机推荐