• Feeds

  • 2PC之踵?是时候升级二阶段提交协议了

    感谢读者,能看到这篇文章,也许是通过 RSS 订阅或者是博客首页来的。博客过去很长时间没有更新,大部分随想都发表在微博,由于发的内容大多是碎碎念,建议大家也不用专门去拜访。在 2010 年时候,曾写过一篇多IDC的数据分布设计的文章提到过 2PC 等协议,最近在 Hackernews 上又有很多有关优化 2PC 讨论,讨论的源头主要由下面这篇文章引起的,因此作了翻译,供大家参阅。

    两阶段提交协议(2PC)已经在企业软件系统中使用了三十多年。它是一种非常有影响力的协议,用于确保访问多个分区或分片中的数据的事务的原子性和持久性。它无处不在 – 无论是在旧的“古老的”分布式系统、数据库系统和文件系统,如Oracle,IBM DB2,PostgreSQL 和 Microsoft TxF(支持事务的 NTFS)还是在较年轻的“千禧”系统如 MariaDB、TokuDB、VoltDB、Cloud Spanner、Apache Flink、Apache Kafka 和 Azure SQL 数据库。如果您的系统支持跨分片/分区/数据库的 ACID 事务,那么它很可能会在后台运行 2PC(或其某些变体)。有时它甚至出现在“前台” – 旧版本的 MongoDB 要求用户在应用程序代码中为多文档事务实现 2PC。

    在这篇文章中,我们将首先介绍一下 2PC:它是如何工作的以及它解决了什么问题。然后,我们将展示 2PC 的一些主要问题以及现代系统如何试图解决它。不幸的是,这些尝试的解决方案也带来了一些其他问题。在文章最后,我将说明下一代分布式系统应该避免使用 2PC,以及如何实现这一点。

    2PC 协议概述

    2PC 有很多变种,但基本协议的工作原理如下:

    背景假设:一个事务相关的工作已经划分给存储该事务数据的分片节点。我们将在每个分片中执行的工作,称为节点“参与者”的工作。当事务准备好“提交”时,每个参与者都能够独立于彼此完成事务相应的职责。2PC 协议由单个独立的、可协调的节点发起(可能是参与者之一)。

    2PC 协议的基本流程如下图所示。(协议从图的顶部开始,然后向下进行。)
    2PC

    阶段1:协调者询问每个参与者,是否已成功完成其对该事务的职责,并达到可以提交的状态。每个参与者都回答“同意”或“反对”。

    阶段2:协调者统计所有回应,如果每个参与者都回答“同意”,那么就提交事务,否则就中止事务。协调者向每个具有提交最终决策权力的参与者发送消息,并接收参与者的确认消息。

    此机制确保事务的原子性属性:整个事务将反映在系统的最终状态中,或者不反映在系统的最终状态中。即使只有一个参与者没有提交,那么整个事务将会被中止。换句话说:每个参与者对事务都有“否决权”。

    它还确保了事务的持久性。每个参与者确保在阶段1响应“同意”之前,已将所有事务持久地写入存储。这使协调者对事务做出最终决定时,无需担心参与者在投票“同意”之后写入失败。在这篇文章中,当使用术语“持久写入”时,我们有目的地模糊化了两个区别 – 本地临时性存储,或是分布式的写入到多个分片以“持久化”。

    除了持久地写入事务相关的数据之外,协议本身还需要额外的写入,在处理消息之前必须使其持久化。例如,一名参与者在第一阶段投票“同意”之前拥有否决权,但在此之后,它不能改变其投票结果。但如果它在投票“同意”后立即崩溃怎么办? 当它恢复时,它可能不知道它投了“同意”,仍然认为它拥有否决权,并继续流程并中止事务。为了防止这种情况,它必须在“同意”投票发给协调者之前,持久化相关投票结果。(除了这个例子,在标准的 2PC 流程中,还有另外两种消息需要发送前持久化操作。)

    2PC 的问题

    2PC 存在两个主要问题。第一个是众所周知的,并在所有讲述 2PC 的教科书中都进行了讨论。第二个不太知名,但仍然是一个大的问题。

    众所周知的问题被称为“阻塞(block)问题”。当每个参与者都投了“同意”,但协调者在将最终决定的消息未能发送给至少一参与者之前就挂了,就会出现这种情况。问题的原因是,通过投票“同意”,每个参与者已经取消了否决事务的权力。但是,协调者仍有绝对权力来决定事务的最终状态。如果协调者在向至少一名参与者发送最终决定的消息之前挂了,那么参与者就无法做出最终决定 – 他们不能中止,因为协调者可能会在挂掉之前决定提交,并且他们无法提交,因为协调者可能决定在失败之前中止。因此,他们必须等待—等到协调者恢复—以便得到最终决定。与此同时,他们无法处理与停滞冲突的事务,因为该事务的写入的最终结果尚未确定。

    阻塞问题有两种解决方案。方案一是修改核心协议以消除阻塞问题。不幸的是,这些修改降低了性能 – 通常通过添加额外的一轮通信来实现 – 因此很少在实践中使用。

    方案二是保持协议不变,但降低协调者失败从而引发阻塞的可能性 – 例如,通过在副本共识协议上运行 2PC 并确保协议的重要状态被复制。不幸的是,这些解决方案再一次降低了性能,因为协议要求这些副本共识轮次按顺序进行,因此它们可能会给协议增加显著的延迟。

    鲜为人知的问题是我称之为“拥堵(cloggage)问题”。在处理事务之后进行 2PC,必然增加事务的等待时间,它等于运行协议所花费的时间。延迟的增加对于许多系统来说已经是一个问题,但更大的问题是,工作节点必须到第二阶段中期才知道事务的最终结果。在他们得到最终结果之前,他们必须为可能中止事务的可能性做好准备,因此在事务得到确认之前,他们通常会暂停其他有冲突的事务进行。这些阻塞的事务同样会进一步阻止其他事务运行,依此类推,直到 2PC 完成,所有被阻止的事务才可以恢复。这些拥堵问题进一步增加了事务平均延迟,并且降低了整体的事务吞吐量。

    总结我们上面讨论的问题:2PC 在四个方面污染了系统架构:延迟 (协议的时间加上冲突事务的停顿时间),吞吐量(因为它碰到冲突的事务会停顿),可扩展性 (系统越大,事务更需要多分区的支持,并且必须付出 2PC 的吞吐量和延迟成本以及可用性(前面提到的阻塞问题)。

    没有人喜欢 2PC,但几十年来,人们都认为它是一种必要的妥协。

    是时候改变了

    三十多年来,业界一直在分布式系统中使用两阶段提交。我们已经意识到引入 2PC 会带来性能、可伸缩性和可用性问题,但在没有更好的替代方案之前,仍需要选择使用它。

    真相就是,如果有更好的方案,2PC 就没必要存在了。为了实现这一目标,无论是在学术界(如SIGMOD 2016论文)和工业界都在进行尝试。通常的做法是避免分布式事务,例如通过在提交事务之前将数据重新分片,使得事务不再是分布式事务。不幸的是,这种重新分片的做法降低了系统的性能。

    我倡导对分布式系统架构进行更深层次的优化。我坚持认为系统可以使用更简单和高效的提交协议,在保证 ACID 的同时,能够处理分布式事务。

    一切问题的根源来自一个存在数十年的假设:事务可能随时以任何理由中止。即使我在相同的初始系统状态下运行相同的事务,在下午 2:00 它可能可以成功提交,但在 3:00 时却会提交失败。

    为什么需要该假设?大多数架构师认为有以下几个原因。首先,节点可能在任何时候失败,包括在事务处理过程中。系统故障恢复过程中,由于无法获取故障前的内存状态,因此也无法恢复事务失败之前的现场。因此系统需要中止故障出现时所有相关事务。由于任何时候都可能发生故障,这意味着事务可能随时中止。

    其次,大多数并发控制协议都需要能够随时中止事务。乐观协议在处理事务后执行“验证”,如果验证失败,则中止事务。悲观协议通常使用锁来防止并发异常,这种锁的使用可能会导致死锁,然后又需要通过中止(至少)事务的方法来解决死锁问题。由于可能随时出现死锁,因此事务需要保留随时中止的能力。

    如果来重新审视两阶段提交协议,您将看到随时中止事务的可能性,是 2PC 协议中复杂和延迟的主要原因。参与者不能轻易地告诉其他方是否同意提交,因为他可能在此之后(在事务提交前)出现故障,然后在故障恢复期间中止此事务。因此,他们必须等到事务结束(当所有重要状态都已经持久化)并且严格按照两个阶段进行处理:在第一阶段,每个参与者公开放弃其控制以中止事务,然后才能进入第二阶段,作出最终决定并进行广播。

    在我看来,我们需要从参与者中移除否决权,并且以系统无法在执行期间随时中止事务的假设来进行架构设计。只接受以业务逻辑需要来否决事务的情况。如果在给定数据库当前状态下,理论上可以提交事务情况下,无论发生何种类型的故障,该事务都必须可以提交。此外也不接受由于其他并发运行导致的竞争条件而不能最终提交或中止事务。

    消除随意中止事务的灵活性听起来很难。我们将很快讨论如何实现这一目标。但首先让我们观察在不能随意中止事务的情况下,提交协议会如何变化。

    当事务不能随意中止时,提交协议是什么样的

    我们来看两个例子:

    在第一个例子中,假设存储变量 X 的节点需要执行一个任务:将 X 的值更改为 42。假设在 X 上没有定义完整性约束或触发器(这可能会阻止系统将 X 设为 42)。在这种情况下,该参与方永远没有中止事务的权力。无论发生什么,该参与方必须将 X 更改为42,如果修改过程中出现系统故障,则必须在故障恢复后将 X 设成 42。由于参与方没有随意中止事务的能力,因此在提交协议期间,不需要检测参与方是否可以提交。

    在第二个例子中,假设存储变量 Y 和 Z 值的节点接收到两个事务任务:从前一个 Y 值中减去 1 并将 Z 设置为 Y 的新值。此外,假设 Y 上存在完整性约束,表明 Y 永远不会低于 0(例如它代表零售应用程序中的库存)。因此,此参与方必须运行以下代码:

     IF (Y > 0)
                  Subtract 1 from Y
    ELSE
                  ABORT the transaction
    Z = Y
    

    因为应用程序的逻辑需要这样做,所以必须赋予参与者中止事务的权力。但是这种权力是受限的。只有当 Y 的初始值为 0 时,才能中止该事务,否则必须提交。因此,参与方不必等到完成事务之后才知道它是否需要提交。相反:一旦它完成了事务中第一行代码的执行,它就已经知道了最终需要提交还是中止。这意味着相比于 2PC 而言,提交协议将能够更早地启动。

    现在让我们将这两个例子组合成一个例子,其中一个事务由两个参与者执行 – 其中一个参与者正在完成第一个例子中描述的工作,另一个参与者正在完成第二个例子中描述的工作。由于我们保证原子性,第一个参与者不能简单地将 X 设置为 42,相反,它自己的工作依赖于 Y 的值。实际上,第一个参与者的事务代码变为:

    temp = Do_Remote_Read(Y)
    if (temp > 0)
        X = 42
    

    请注意,如果第一个参与者的代码如上的话,那么另一个参与者的代码可以简化为:

    IF (Y > 0)
             Subtract 1 from Y
             Z = Y
    

    通过以这种方式编写事务代码,两个参与方都删除了显式中止逻辑。相反,两个参与方都有 if 语句来检查是否会导致原始事务中止的约束。如果原始事务中止,两个参与方最终都无所作为。否则,两个参与方都会根据事务逻辑更改其本地状态。

    此时需要注意的一点是,在上面的代码中完全消除了对提交协议的需求。除了应用程序代码在给定数据状态下定义的条件逻辑以外的任何原因,系统都不允许中止事务。并且所有参与者都在这个相同的条件上调整他们的动作,这样他们就可以独立地决定,在由于当前系统状态而无法完成事务的情况下“什么也不做”。因此,已经消除了事务中止的所有可能性,并且在事务处理结束时不需要任何类型的分布式协议来做出关于事务组合的最终决定。2PC 的所有问题都已消除。因为没有协调者,所以也没有阻塞(block)问题。因为所有必要的检查都与事务处理时候完成,而非在事务完成之后检查,所以没有拥堵(cloggage)问题。

    此外,只要不允许系统因应用程序逻辑之外的任何原因而中止事务,总是可以像上面那样重写任何事务以替换代码中的中止逻辑,即 if 语句有条件地检查中止条件。此外,可以在重写应用程序代码的情况下实现此目的。(有关如何执行此操作的详细信息超出了本文的范围,但可以高屋建瓴地总结为:当一个节点执行了导致中止的条件逻辑时,它可以设置特殊的标记,其他节点可以在远程读取这些标记。)

    实质上:在事务处理系统中有两种类型中止:(1)由数据状态引起的中止和(2)由系统本身引起的中止(例如故障或死锁)。如上所述,类别(1)总是可以根据数据的条件逻辑来编写。因此,如果您可以消除类别(2)中止,则可以消除提交协议。

    所以现在,我们所要做的就是解释如何消除类别(2)中止。

    消除系统本身中止

    我花了将近十年的时间来设计没有系统引发中止的系统。此类系统的示例是 Calvin,CalvinFS,Orthrus,PVW 以及惰性处理事务系统。这一特性的推动力来自于— Calvin —因为它是一个确定性数据库系统。确定性数据库保证在给定一组定义的输入请求的情况下,数据库中只有一个可能的最终数据状态。因此,如果将相同的输入发送到系统的两份不同的副本,两份副本将独立地处理该输入,并将最终达到一致的结果。

    系统本身中止,例如系统故障或并发控制竞态条件,从根本上说是不确定性事件。一个副本很可能碰见系统调用失败或进入竞态条件,而另一个副本则不会。如果允许这些非确定性事件导致事务中止,则一个副本会中止事务而另一个副本将提交事务 – 这是对确定性的违背。因此,我们必须以系统故障和竞态条件不能导致事务中止的方式设计 Calvin。对于并发控制,Calvin 使用了避免死锁技术的悲观锁定,该技术确保系统永远不会陷入由于死锁导致的事务中止的状况。面对系统故障,Calvin 无法从中断的位置重启事务(因为在故障期间失去了内存状态)。尽管如此,通过从相同的原始输入重新启动事务,它依然能够完成该事务的处理而不必中止它。

    这些解决方案(包括防止死锁以及故障重启恢复事务),都不局限于在确定性数据库系统中使用。在非确定性系统中,如果失败期间,丢失的事务状态被其他非故障节点侦测到,那么事务重启变得略微棘手。但是也有一些简单的方法来解决这个问题,但这些方法已经超出了本文讨论的范围。实际上,我上面提到的其他系统都是非确定性系统。一旦我们意识到消除系统本身故障所带来的威力,我们就将设计植入到 Calvin 之后构建的每个系统中 – 甚至是非确定性系统。

    结论

    系统架构师继续在分区系统中使用 2PC 的好处微乎其微。我认为,忽略系统本身中止以及状态写入故障是更好的前进方法。确定性数据库系统(如 Calvin 或 FaunaDB)总是会规避系统本身中止,因此通常可避免 2PC。但是这种优势仅发挥在确定性数据库是一个巨大的浪费。从非确定性系统中消除系统本身引起的中止并不困难。最近的项目表明,甚至可以在不使用悲观并发控制技术的系统中消除系统引起的中止。例如,我们上面链接的 PVW 和惰性事务处理系统都使用多版本并发控制(MVCC)的变体。FaunaDB 使用乐观并发控制的变体。

    在我看来,几乎没有理由坚持过时的系统性中止假设,当系统在单台机器上运行时,这种假设是合理的。然而,很多现代系统已经扩展到到多台可以故障隔离的机器上。维持该假设就需要成本高昂类似 2PC 的协调和提交协议。2PC 的性能问题一直是非 ACID 系统兴起的主要推动力,这些系统放弃了强一致性保证,以达到更好的可扩展性、可用性和性能。2PC 太慢了!它增加了所有事务的延迟,不仅仅是协议本身的时间占用,还阻止了访问相同数据的其他事务的并发执行。此外,2PC 还限制了可伸缩性(通过降低并发性)和可用性(我们上面讨论的阻塞问题)。前进的道路已经很明确:我们需要在设计系统时重新审视过时的假设,并对两阶段提交说“再见”!

    本文作者 DANIEL ABADI,翻译自 It’s Time to Move on from Two Phase Commit方圆对本文翻译亦有贡献。

    是时候支持HTTPS了:免费SSL证书letsencrypt配置教程

    今天抽空将 blog 增加了 HTTPS 支持,并停止了原来的 HTTP 服务。

    由于证书仅网站域名需要,因此使用了免费的 Let’s Encrypt 证书服务。

    根据维基百科的说明,Let’s Encrypt 是一个于2015年三季度推出的数字证书认证机构,将通过旨在消除当前手动创建和安装证书的复杂过程的自动化流程,为安全网站提供免费的SSL/TLS证书。Let’s Encrypt 是由互联网安全研究小组(ISRG,一个公益组织)提供的服务。主要赞助商包括电子前哨基金会,Mozilla 基金会,Akamai 以及思科。

    2015年12月3日,该服务进入公测阶段,正式面向公众。

    2016年4月12日,该项目正式离开Beta阶段。

    到2016年9月9日,Let’s Encrypt 已经发放 1000 万张证书。因此对于大部分中小型网站来说,是一个值得考虑的选择。

    letsencrypt

    HTTPS 启用及配置的主要步骤如下,假设你已经有一个正常运行的 HTTP 网站。

    1. 打开 https://certbot.eff.org/ 选择对应操作系统与 Web 服务器,选完后出现响应的平台说明。由于我的系统运行在 nginx 及 Ubuntu,选完之后出现的说明地址是 https://certbot.eff.org/#ubuntuxenial-nginx

    2. 执行命令,并根据需要修改相应域名参数。

    $ sudo apt-get install letsencrypt
    $ letsencrypt certonly --webroot -w /var/www/timyang.net -d timyang.net -d www.timyang.net
    

    3. 修改 nginx
    将 80 端口相关配置改成 443 端口,并增加相关配置

    # listen       80;
    listen 443 ssl;
    server_name timyang.net www.timyang.net;
    
    ssl_certificate /etc/letsencrypt/live/timyang.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/timyang.net/privkey.pem;
    

    再增加 80 端口自动跳转

    server {
        listen 80;
        server_name timyang.net www.timyang.net;
        return 301 https://$host$request_uri;
    }
    

    4. 重启 nginx,并用 chrome 访问,如果 URL 地址之前出现锁标记,则说明设置成功。
    如果页面中还包含有嵌入的 HTTP 元素,chrome 会仍然显示 i 标记,通过点击 i 之后的元素说明逐个修复即可。

    timyang-https

    另外注意 Let’s Encrypt 每次只有 90 天有效期,但可以通过脚本进行更新

    测试运行

    $ sudo letsencrypt renew --dry-run --agree-tos
    

    如果运行成功,建议将正式更新脚本加到 cron 脚本中,一劳永逸。

    $ sudo letsencrypt renew
    

    虽然 Let’s Encrypt 是一个免费的服务,但对 letsencrypt 使用感到满意的朋友,还可以去他们网站进行赞助。

    IT工程师的又一次春节感悟

    身在中国,生长的环境已经教导好了我们如何过一个正常的春节。

    举国同庆的仪式

    工作之后,回不回家则成了每年需要思考的问题。如果想过得轻松,离开父母去国外晒太阳发呆睡觉是一个不错的主意。但在这样一个举国团聚的日子,离开亲人远走毕竟会有一些愧疚感。

    要回老家,需要面临交通和礼物的问题,同时还需要考虑自身是否体面。在城里工作,生活未必光鲜;但如果要回家,大部分还是希望将自己过得好的一面展示,比如用的手机、开的车、穿的衣服等。工程师群体一个冬天没添置新衣服并不罕见,但如果过年回家还是穿着去年爬山买的冲锋衣,会给细心的家里人增加不必要的担忧。

    带什么礼品也是个发愁的问题,上一年带的礼品父母可能还收藏在老家未开封。送自己父母有时候挑了一些不实用的东西就算了,但如果去看岳父岳母(或未来的)就得多掂量一下。

    按照传统的习俗,过年从腊月二十左右就开始了,在外地工作人群陆续返乡,经过了小年的酝酿、伴随着爆竹及烟花声,在除夕夜进入高潮。到正月份开始走亲访友,包括要拜访一些平时并没有热情及兴趣访问的亲戚,对于一些节奏慢的,直至过了元宵节春节才算结束。

    春联大多是在年货市场买的,尽管上一辈少部分人还有自己编对联的经历,但到了这一代,除了少部分人有学校练过毛笔字的经历,大部分人都不会再有手写春联的兴趣及能力了。买来春联的横幅大多是一帆风顺或出入平安之类比较俗的文字,但也没人去琢磨更雅的文字,春联只是一个过年的象征,虽然贴在每天出入的大门口,但没什么人关注上面具体的内容。

    在外工作的人过年回家,如果生活在大家族里面,红包是一笔不小的开支。除了给现金之外,现在还流行网上派红包,几百元甚至几千发下去,冒个泡就没了。当然也有更多的群体是抢红包一族,以至于回到家里吃年夜饭,也逐渐出现了城里面吃饭聚会的场面,大家都在盯着手机抢红包。

    「小道消息」最近的的「猴年春晚的蝴蝶效应」中提到

    1) 今年刚毕业的小李在春节这天摇了 328 次微信,打开了 523 次支付宝,最后红包总计收入 13.50 元,前后四个小时什么都没干。

    2) 经此猴年春晚一役,中国有数千万青年一夜之间手臂变粗,并有数百万人练就「金手指」绝技,驰名日本的加藤鹰先生从此失业。

    3) 某公司美女财务年终业绩考评不佳,奖金少发了一个月。春节这天,她潜伏在公司数百个群里,一天不吃不喝抢红包赚到 9300 元,出了一口恶气。节后,她成功转岗,任职手机 App 测试工程师。

    大部分在外地工作的人的问题在于,一年其他时间并不会有机会抽出时间看望父母,因此回家探亲的义务都积攒到春节了。如果大家在一年之中对于亲情有更多看望及表达,则可以不需要凑在这几天。

    一件事情应该尽量避免走到这样一个阶段,大家(比如父母以及另一半)都觉得需要这种仪式,每个人都觉得为了其他人在进行某项仪式,但是可能每个人自己都不喜欢及享受这种仪式。

    无所事事的时间

    尽管大部分人在春节这段时间无所事事,但也有不循规蹈矩的,李笑来 2015 年 12 月写的「什么是践行」一文中提到自己在以往春节完成的工作

    《托福核心词汇 21 天突破》最后的突击成稿,就是在 2003 年的春节完成的。《把时间当做朋友》最初一搞,还叫《管理我的时间》的时候,是 2007 年春节……

    2008 年年初,我和朋友合伙开了个留学咨询公司,在数码大厦租了个办公室,交完房租,就是装修,花不了几个钱。装修差不多了,就春节了。于是大家都去过年。等他们回来的时候,我已经在这期间接了几个客户,讲了一小期班,收上来的钱已经使得公司产生了盈利。

    2010 年春节,一口气在两周内整理完《人人都能用英语》,以及《把时间当作朋友》的修订……
    《人人都能用英语》现在在这里:http://zhibimo.com/books/xiaolai/everyone-can-use-english
    《把时间当作朋友》(第三版)在这里:http://zhibimo.com/books/xiaolai/ba-shi-jian-dang-zuo-peng-you

    2013 年年初,我和两个小伙伴组建了 Knewone,网站上线后没多久,就是春节。他们俩一个去了香港,一个去了柬埔寨,度假。我在家里充当客服…… >等两个小伙伴回来,网站的流量已经冲进 Alexa 全球排名 5 万以内了。

    大部分人在春节假期浪费的时间至少有 2 周以上,这里说的浪费是指时间消耗在一些无谓的琐事上,而不是真正的度假或休息,比如游泳晒太阳算不上浪费。工作通常在放假前 1~2 周就停了;放假后恢复到正常工作状态通常还需要额外几天时间。因此这段时间大部分精力放在准备衣服、年货、交通、例行公事的拜访。如果你是一家之主,你可能还需要投入更多精力张罗招待客人。

    大部分人对这段时间的浪费见怪不怪,某种程度已经习惯了这段时间无所事事。上面一文中还提到

    可实际上,我并不讨厌给自己放假的啊。只不过,我觉得“法定”这事儿对我来说没意义,那所谓的“法定”是制约企业的,又不是制约我个人的。我什么时候该休息,应该是我说了算啊。手里本来有要做的事儿,结果可倒好,法定要求休息,我就休息了,那手里的事儿怎么办?在不得不与他人协同的时候,法定假日更是气人,活生生把很多事儿给搅黄,且每个人都不在乎 —— 他们说他们有他们自己的生活。

    由于整个国家都在大迁徙,长途交通除了体验糟糕之外,时间上往往比平时多出更多时间。火车票一票难求,高速公路变成了停车场。还有些为了节约过路费,放假前夕在高速路口等候零点免费放行的人群。

    因此如果按照正常的方式来过春节,假期并不能得到足够的休息。我们忙于完成春节的程序及仪式。

    想充分利用时间的工程师,也计划看点书、写点东西,然而时间都被饭局、牌桌以及应酬不同的人群打断。想交流思想或者行业话题也找不到人。因此结果往往是,准备的书本没怎么看,准备写的东西没有写。

    很多家里面人多比如有小孩及父母在一起的深有体会,平时想在家里面做点事情尚不容易,就不要说逢年过节了。

    2016 年特别不凑巧,大家正准备收紧心思上班的时候,又碰到情人节,IT 工程师还没上班又在思考如何有特色的度过情人节吧?

    观念的冲突

    春节期间如果大部分时间在跟亲人在一起,对于大部分年轻人,首先碰到择偶观点的冲突。

    关于择偶条件,今年春节让大家印象深刻的,莫过于从江西匆忙逃走的上海姑娘和那一桌饭菜的照片了。在陈岚另外一篇相似经历的文章「上海姑娘,不是逃饭,是逃命」中提到。

    “我反复在心里犯拧的,是那一桌子,明晃晃亮灿灿的——不锈钢餐盘。”

    从小到大,她没有使过这样的器皿。

    她从小的餐饮习惯也并不讲究到色香味形器诸色具精。只是喝碧螺春使白瓷,为的取其色悦,喝明前龙井使一只透明玻璃厚矮杯,为观其形逸,喝普洱使一只粗陶杯,喝红茶要么是英国瓷器,要么是紫砂,这在她家,并不刻意,是一种至少已经延续了三代、而且已经无感了的生活习惯。

    无论如何,那一桌子不锈钢餐具,在她来看,非常有损食相。扎眼地难受。金属撞击声更让她反胃。那些筷头己发黑的筷子,她尽快忽略,礼貌地吃完整顿饭。毫不失礼。是因为确实相爱。

    但从这顿饭开始,她开始参悟,参悟彼此那些总会引起磕碰的差异的根源。

    择偶是不同人群观念冲突的集中表现。这时候,背景及家庭条件的差异、文化的差异、阅历的差异在这里体现得淋漓尽致。虽然大部分年轻人并不能理解上面文字体现出的家庭环境带来的文化差异。

    除了择偶的问题,工作等价值观的问题会经常碰撞,IT工程师除了要解释自己工作的性质之外,还需要面临隔壁家二狗上学成绩不如自己却比现在比自己有钱的事实,再加上职场上的成长需要厚积薄发,一年过去并不意味有显著的变化,因此回家的工程师往往有意回避谈论具体工作问题。

    同学聚会是另外一个主题,一个方面,当年的发小都希望有更多机会再回首聚一下,一起感概青春的年华与岁月的流逝;但另外一个层面,常年不在一起,彼此观念差异往往比意想的更大。如果避免让对方惊诧你竟然成为脑残或愤青时,尽量避免将话题引向一些社会深层次问题。组织方也最好事先确定活动费用支付方式问题。

    春节时环境和习惯的力量促使我们每个人按照既定的程序前行,大的环境无法改变,但是可以改变自己的生活方式。是时候思考下当下习惯的合理性。

    大约从 1986 年开始,我很讨厌过春节,很朴素的原因,就是觉得真浪费时间啊…… 那个时候,罗永浩就表示很不理解,奇怪我为什么一到过年的时候,就找个宾馆躲进去 —— 这真是个怪人!

    123...Last