拉巴力的纸皮箱


  • 首页

  • 标签

  • 归档

  • 关于

  • 搜索

金融业务容灾切换后监控和修正方案

发表于 2020-09-08

前言

  • 接关于MHA_Consul_MySQL高可用方案的简单总结和思考
    中所讲,该方案无法严格保证主从数据一致或者不丢数据,那么对数据准确性非常严格的业务,则需要在业务层面进行相应的对账和修正。

  • 对账的前提当然是要有流水,可以是业务流水(跟余额表事务绑定)或者是binlog的变更流水。

  • 既然是对准确性要求严格的业务,一般都应该会有业务流水。

方案描述

  • 方案以数据库切换事件为线索,描述切库前的事先准备、切库中的止损、切库后的监控和修正。

一、切库前

  1. 余额写redis缓存(如果有多机房,需要异步多写对应机房的redis,或nsq通知)

二、切库中

  1. 发生切库事件
  2. (切库之后的一段时间内)若有用户余额变动操作,比对redis和DB余额是否一致,不一致则阻断一段时间。
  • 缺点:不一致有可能是误伤(redis刚好写失败导致切库前就不一致)
  • 折中:针对一些大额变更才阻断,增加一些更细致的策略

三、切库后

  1. 指定主库和从库,对比流水日志
  2. 修复数据(若有不一致),并关闭冻结开关
  3. 无法修复的订单如何处理(用户余额不足)?
    • 考虑当坏账处理;通过余额调整(邮件审批方式同步团队成员);再按流水订单重新扣除

对比流水和修复大致思路

  1. 读旧主库和新主库的余额变更流水日志
  2. 对比得到旧主库存在而新主库不存在的余额变更流水日志
  3. 获取受影响的用户的余额,重放流水日志模拟分析,得到受影响人数,受影响金额,不可修复订单(比如余额不足)等情况
  4. 按照流水日志中的业务类型重新执行相应的业务sql(充值,消费,提现等)
  5. 修复完成之后,重建旧主库,并挂为主库

金融业务容灾体系简述

发表于 2020-09-08

概述

  • 本文针对金融类(如用户虚拟货币)这类对数据准确性很敏感的业务的容灾架构;
  • 案例中的服务架构为同城主备架构;
  • 内容包括:容灾架构、故障切换、故障恢复、演练方案等;
  • 涉及技术点:MySQL、MHA、Consul等;
  • 本文基于
    1. 关于MHA-Consul-MySQL高可用方案的简单总结和思考
    2. 如何解决脑裂问题
  • 由于某种原因,某些细节不会描述。
  • 关于系统可用性,收藏了一张网图
  • MTTF 是 Mean Time To Failure,平均故障前的时间,即系统平均能够正常运行多长时间才发生一次故障。系统的可靠性越高,MTTF 越长。(注意:从字面上来说,看上去有 Failure 的字样,但其实是正常运行的时间。)
  • MTTR 是 Mean Time To Recovery,平均修复时间,即从故障出现到故障修复的这段时间,这段时间越短越好。
  • 故障是正常的,而且是常见的。
    故障是不可预测突发的,而且相当难缠。
    我们要干的事儿就是想尽一切手段来降低 MTTR——故障的修复时间。
    – 陈皓

容灾架构

  1. 红色线条为正常情况下的服务主链路;
  2. 同城主备架构: 主-IDC-A;从-IDC-B;
  3. 域名灾备:前端通过主域名访问后端接口,当响应超时或者返回50x的时候,前端将切换到备用域名访问后端接口;
    • 异常情况可能是后端服务异常或者用户所在地区网络不稳定等原因;
    • 针对不幂等的接口,应设置成只切换域名不进行重试;
    • 后端服务可以根据自身服务的异常情况,返回50x,让前端切换到备用域名
  4. 主域名为CDN域名,连接北京两个机房,备用域名是非CDN域名,直接连接北京第三个机房;
    • 使用CDN域名的原因:不把回源点暴露出去,从而把核心机房暴露出去。
  5. 使用MHA+Consul作为DB的切换方案;
  6. 每个IDC的gateway配置服务的主权重都是在IDC-A;发生故障切换时,gateway将把服务主权重切换到IDC-B,而通过外网进入IDC-A的流量,服务通过返回50x由前端切换到备用域名。

详细描述

故障切换

触发故障切换的场景

  1. 机房孤岛 (MHA+Consul出发切换)
  2. 网络抖动 (由决策服务通过健康检查手段决策)
  3. 服务自身异常或机器问题等 (MHA+Consul出发切换)

1) MHA+Consul切换

  • 触发条件:1或3 (主库不可访问)
  • MHA+Consul切换后,决策服务切换gateway的服务权重

2) 决策服务切换

  • 触发条件:2 (网络抖动)
  • 决策服务健康检查异常后,通过MHA+Consul主动切换主库,并切换gateway的服务权重

机房容灾场景(单机房故障)

1) 机房内外网不通

  1. IDC-A故障
    1. 服务权重通过gateway切换到IDC-B
    2. 外网无法进入IDC-A,只能进入IDC-B
    3. CDN域名检测异常后剔除IDC-A的服务节点
    4. 故障瞬间由于IDC-A不通,cdn结点会重试到IDC-B或者返回前端50x,前端访问备用域名。
  2. IDC-B故障
    1. 服务权重无需调整
    2. 外网无法进入IDC-B,只能进入IDC-A
    3. CDN域名检测异常后剔除IDC-B的服务节点
    4. 故障瞬间由于IDC-B不通,cdn结点会重试到IDC-A或者返回前端50x,前端访问备用域名。

2) 机房孤岛(内网不通,外网通)

  1. IDC-A故障
    1. 服务权重通过gateway切换到IDC-B
    2. 通过外网进入IDC-A的流量,服务自杀返回50x,前端访问备用域名
      • 服务自杀参考:如何解决脑裂问题
  2. IDC-B故障
    1. 服务权重无需调整
    2. 通过外网进入IDC-B的流量,服务自杀返回50x,前端访问备用域名

3) 机房网络抖动

机房服务异常(内外网都通,但该机房服务有问题,网络不稳定,丢包率高等,需机房切换)。
流量进入服务之后处理同2)只是切换策略不同。

决策服务

  1. 通过Consul判断是否孤岛
  2. 通过接口调用失败率,apm,监控网络丢包率等指标判断
  3. 相关服务同步切

单元化

  1. 切换需要把相互依赖的服务整体进行切换,尽量避免跨机房调用。

实现

gateway如何实现

  • 可以考虑结合服务发现,以localproxy代替nginx代替服务权重配置

其他注意事项

  1. 定时任务是否要切换
  2. MQ消费或生产是否要切换
  3. 服务强依赖要单元化,比如强依赖方主备,自己的服务做双活也没用
  4. MQ类发送异步进行
  5. 留意nginx重试机制,如以下配置:proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504;,501是不重试的,超时和其他50x会重试。
    • nginx的重试机制

其他技巧

  1. 服务所依赖的外部服务分为强依赖和弱依赖。弱依赖可以继续降级,而强依赖则不可以。
  2. 强依赖可以进一步划分成读依赖和写依赖。通常情况下写依赖是几乎不可能优化的,只能依赖其高可用,比如扣费服务。而读依赖则有优化空间,读依赖可以分为实时性依赖和非实时性依赖,后者可以通过缓存来解决强依赖的问题,比如用户的信息。这部分数据通常的强依赖的,但是又可以缓存下来。
  3. 强实时性读依赖的,故障情况下,可以考虑降级成非实时性依赖。比如采取先读远端数据,失败时降级成读缓存的策略。

演练方式

  1. 前期:tcpcpoy线上流量,复制线上服务部署单独一台演练环境,包括应用和db
  2. kill服务,killDB
  3. iptables屏蔽端口
    • iptable和kill应用不一样。前者会有readtimeout,后者直接reset peer
    • kill应用的方式基本是平稳的,使用iptable屏蔽端口的方式,可能会有connectTimeout或readTimeout。
  4. 线上停机房
    • 停专线一定是孤岛,不存在一边内网通,另一边内网不通的情况,是一个内网(看上图的网络拓扑图)。

Q&A

  1. 备用机房(IDC-B)正常情况下无流量?
    • 配置万分之一的流量,确保切换前已经可用。
    • 确保切换之前备机房是可用的,是否可用通过观察日志情况。
    • 备用机房异常应该及时告警。
  2. 为什么跨机房同步不使用MySQL主从同步而使用otter?
    • 一般主从同步只在同机房或者同城进行。
    • otter是阿里开源的一个分布式数据库同步系统,尤其是在跨机房数据库同步方面,有很强大的功能。
    • ????
  3. 相关服务一同切换是否合理
    1. 机房异常一同切换可行;
    2. 如果只是单个服务异常,别的服务也要跟着切库不一定合理。决策服务应该支持业务自行配置切换策略。

如何解决脑裂问题

发表于 2020-09-05

什么是“Split Brain”(脑裂)问题?

Split Brain 是指在同一时刻有两个认为自己处于 Active 状态的 NameNode。对于HA集群而言,确保同一时刻只有一个NameNode处于active状态是至关重要的。否则,两个NameNode的数据状态就会产生分歧,可能丢失数据,或者产生错误的结果。

CAP理论

  • Consistency (一致性): 副本一致性特指强一致性;

  • Availiablity(可用性): 指系统在出现异常时已经可以提供服务;

  • Tolerance to the partition of network (分区容忍): 指系统可以对网络分区这种异常情 况进行容错处理;

  • CAP理论,对于P(分区容忍性)而言,是实际存在 从而无法避免的。因为,分布系统中的处理不是在本机,而是网络中的许多机器相互通信,故网络分区、网络通信故障问题无法避免。因此,只能尽量地在C 和 A 之间寻求平衡。

  • 对于数据存储而言,为了提高可用性(Availability),采用了副本备份。某数据块所在的机器宕机了,就去该数据块副本所在的机器上读取。但是,当需要修改数据时,就需要更新所有的副本数据,这样才能保证数据的一致性(Consistency)。因此,就需要在 C(Consistency) 和 A(Availability) 之间权衡。

  • Quorum机制,就是这样的一种权衡机制,一种将“读写转化”的模型。

Quorum机制

  1. Write-all-read-one(简称 WARO).(极端的方案)
    • 当Client请求向某副本写数据时(更新数据),只有当所有的副本都更新成功之后,这次写操作才算成功,否则视为失败。
    • WARO牺牲了更新服务的可用性,最大程度地增强了读服务的可用性。而Quorum就是更新服务和读服务之间进行一个折衷。
  2. Quorum 机制
    • 将 WARO 的条件进行松弛,从而使得可以在读写服务可用性之间做折中,得出 Quorum 机制。
    • Quorum机制是“抽屉原理”的一个应用。定义如下:假设有N个副本,更新操作wi 在W个副本中更新成功之后,才认为此次更新操作wi 成功。称成功提交的更新操作对应的数据为:“成功提交的数据”。对于读操作而言,至少需要读R个副本才能读到此次更新的数据。其中,W+R>N ,即W和R有重叠。一般,W+R=N+1
    • 仅仅依赖 quorum 机制是无法保证强一致性的。因为仅有 quorum 机制时无法确 定最新已成功提交的版本号,除非将最新已提交的版本号作为元数据由特定的元数据服务器或元数 据集群管理,否则很难确定最新成功提交的版本号。
      • 1)如何读取最新的数据?—在已经知道最近成功提交的数据版本号的前提下,最多读R个副本就可以读到最新的数据了。
      • 2)如何确定 最高版本号 的数据是一个成功提交的数据?—继续读其他的副本,直到读到的 最高版本号副本 出现了W次。
    • Quorum 机制的三个系统参数 N、W、R 控制了系统的可用性,也是系统对用户的服务承诺:数 据最多有 N 个副本,但数据更新成功 W 个副本即返回用户成功。对于一致性要求较高的 Quorum 系 统,系统还应该承诺任何时候不读取未成功提交的数据,即读取到的数据都是曾经在 W 个副本上成 功的数据。

Lease 机制

  • Lease 是由颁发者授予的在某一有效期内的承诺。颁发者一旦发出 lease,则无论接受方是否收到,也无论后续接收方处于何种状态,只要 lease 不过期,颁发者一 定严守承诺;另一方面,接收方在 lease 的有效期内可以使用颁发者的承诺,但一旦 lease 过期,接 收方一定不能继续使用颁发者的承诺。
  • Lease 机制依赖于有效期,这就要求颁发者和接收者的时钟是同步的。对于这种时钟不同步,实践中的通常做法是 将颁发者的有效期设置得比接收者的略大,只需大过时钟误差就可以避免对 lease 的有效性的影响。

解决脑裂的关键

raft是如何解决的?

  1. 核心是“大多数成功”机制。Raft就是基于Quorum机制下实现的。
  2. 看下以下这篇文章:为 Raft 引入 leader lease 机制解决集群脑裂时的 stale read 问题
    • 这种方法牺牲了一定的可用性(在脑裂时部分客户端的可用性)换取了一致性的保证。
    • 多数派的网络分区挂了,岂不是直接不可写了
  3. 如何解决多数派的网络分区挂了,服务就不可用的问题?
    • 我的答案是部署不止两个网络分区,至少三个网络分区;这样任意一个分区挂了,服务都可用,除非三个分区的大多数分区挂了(挂了2个);
  4. 副本控制协议分为两大类:“中心化(centralized)副本控制协议”和“去中心化(decentralized) 副本控制协议”。解决脑裂的其中一个关键点是哪种 “去中心化的协议”,paxos和raft都是。

使用非分布式存储的应用如何解决?

  1. 上述处理脑裂问题的前提是:服务本身就是一个分布式存储服务,使用raft等一致性协议;那么普通的业务服务,使用MySQL的的情况下,怎么解决脑裂问题?
  2. MySQL主从服务复制,这种存储服务本身就不是去中心的分布式数据库;
  3. 解决问题的核心点是:引入第三方组件作为整个业务集群的“选主服务”(比如Consul、Etcd,都是基于Raft协议);结合MySQL的半同步复制机制:支持配置n个从库ack才响应客户端(类似Quorum机制)和MHA,可以很大程度的避免丢数据导致不一致。
  4. Consul本身就是基于raft协议,可以利用其去中心化的特性,作为选主服务,业务通过Consul识别到哪个集群是主集群之后,可定制进行相应的业务处理。

选主服务

  1. Consul、Etcd (Raft)
    • 在本次案例中是通过判断是否能获得Consul集群中的leader来判断孤岛的(调获取某个node的信息接口,如果没有leader会返回“No cluster leader”);而不是通过Consul分布式锁的方式选主。
  2. ZooKeeper (ZAB、Paxos )
  3. Chubby 分布式锁;Google的锁,才是分布式锁?

使用Consul解决脑裂问题

如何判断“孤岛”?

  1. 在三个IDC部署一个Consul集群,该集群会存在一个leader,且每个IDC的service在网络正常的情况下,都能检测到哪个是leader;依赖Consul的raft协议选举判断网络孤岛;(为了后续描述简单,假设每个IDC只部署一个Consul结点)
  2. 每个IDC的service只访问当前IDC对应的Consul结点;当访问返回“No cluster leader”时,说明该网络分区已经是”孤岛”;
    curl 'http://consul:8500/v1/health/service/nodeName?passing&wait=1s&index=1&tag=master'
    No cluster leader
    
  3. 通过“No cluster leader”来判断孤岛的前提是,假设Consul是高可用的。因为当有两个Consul结点无法访问或挂掉的时候,也有能误判成没有leader(实际上并未出现网络孤岛,只是Consul集群异常);
  4. 引入双重检查机制,解决Consul集群因为可用性问题导致的误判的可能性;在Consul判断为网络孤岛的情况下,通过ping异地IDC的service的健康检查接口,二次确认;双重检查机制只能解决误判问题,若Consul集群不能高可用,那么判断孤岛的机制将失效。

如何处理“孤岛”?

  1. 判断为孤岛的网络分区的服务,如果接收到外网请求(因为是孤岛情况下其他IDC内网不通),可以拒绝服务,也可以返回特殊的业务错误码或HTTP错误码,由上层服务或客户端重试到其他的机房。

“孤岛”消失后如何恢复?

  1. 手动恢复。”孤岛”的网络分区服务不恢复提供服务,由开发人员确认DB等无异常后再手动恢复;
  2. 自动恢复。需做好充分的检测手段才能启用自动恢复:DB是否发生切换、主从DB数据是否一致(如比对脚本)、判断网络是否已经恢复到策略(防止来回切)等。

Q&A

为什么每个IDC的service只访问当前IDC对应的Consul结点?(前提是Consul高可用性)

  1. 假设IDC-A出现网络孤岛的情况下,IDC-A的service本身就无法访问IDC-B的Consul结点;
  2. 假设IDC-B未出现网络孤岛,IDC-A的service只需要访问IDC-A的Consul结点即可判断;

选主服务一定要选择基于去中心一致性协议的组件吗?

  1. 不一定。使用选主服务只是利用组件高可用性和选举机制解决脑裂问题。Raft等去中心一致性的协议解决的的一致性问题及其leader的选举机制。换句话,只要该组件能高可用且在结点大多数存活(网络互通)的情况下,能选举出一个Leader即可,数据的一致性并不重要(因为没用到组件提供的数据存储功能)。
  2. 一般情况下,业务使用MHA-Consul-MySQL作为DB切换的高可用方案;那么解决脑裂问题,也使用Consul组件,也可以减少服务对其他组件的依赖。

扩展

  1. Group Replication
    • Group Replication由至少3个或更多个节点共同组成一个数据库集群,事务的提交必须经过半数以上节点同意方可提交,在集群中每个节点上都维护一个数据库状态机,保证节点间事务的一致性。Group Replication基于分布式一致性算法Paxos实现,允许部分节点故障,只要保证半数以上节点存活,就不影响对外提供数据库服务,是一个真正可用的高可用数据库集群技术。 Group Replication支持两种模式,单主模式和多主模式。在同一个group内,不允许两种模式同时存在,并且若要切换到不同模式,必须修改配置后重新启动集群。 在单主模式下,只有一个节点可以对外提供读写事务的服务,而其它所有节点只能提供只读事务的服务,这也是官方推荐的Group Replication复制模式。
  2. NewSQL
    • 关于NewSQL的定义是:这是一类现代关系型的DBMS,旨在为NoSQL的OLTP读写负载提供相同的可扩展性能,同时仍然提供事务的ACID保证。
    • TiDB。TiDB 是一个分布式 NewSQL 数据库。它支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议,具有数据强一致的高可用特性,是一个不仅适合 OLTP 场景还适OLAP 场景的混合数据库。

Reference

  • 刘杰:分布式原理介绍
  • 分布式系统理论之Quorum机制
  • 关于MHA_Consul_MySQL高可用方案的简单总结和思考
  • MySQL · 引擎特性 · Group Replication内核解析
  • 我们听到的TiDB到底是什么?

关于MHA_Consul_MySQL高可用方案的简单总结和思考

发表于 2020-08-31

概述

MHA + Consul + MySQL的高可用方案,网上已经有很多资料,这里只是做一下简要的总结和思考。文章部分文字摘自Reference中的链接。
直接先上一张图

  1. 图中的灾备架构适用于同城主备架构的业务,比如金钱业务;
  2. DB层是一主多从,主库至在其中一个机房,并在DB集群上搭建跨IDC的MHA;同样Consul也是跨IDC的集群;
  3. 业务的写主流量配置在主库机房的一侧,当主库故障发生DB切换产生新主库时,流量也跟从新主库一同切换;
  4. 主库切换通过MHA完成,并通过Consul集群和应用的SDK通知到业务服务。
  5. MySQL采用默认的异步复制方式

解决什么问题

  1. 解决MySQL的单点问题。当主库发生故障时能提升从库为新的主库,且应用层能自动识别;从而缩短故障的处理时间;
  2. 通过Consul能支持从库的故障切换以及从库扩容或下线;

每个组件各自的作用

  1. MHA:监控主节点,可以在故障时自动或手动切换、非故障时手动主从切换。切换时会进行数据补齐,并将新的master信息更新到consul中。
  2. Consul:MySQL服务注册并提供健康检查、记录最新的master;还可以提供其他配置性的服务,比如dns,可解析数据库域名。
  3. SDK: sdk通过consul-api监控MySQL ip列表的变化,能连接新的库和去掉已下线的库。

下面的部分将对使用到的技术逐一简要描述和总结。

MHA

介绍

MySQL MHA架构介绍:

MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Facebook公司)开发,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。

该软件由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上。MHA Node运行在每台MySQL服务器上,MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master。整个故障转移过程对应用程序完全透明。

在MHA自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失,但这并不总是可行的。例如,如果主服务器硬件故障或无法通过ssh访问,MHA没法保存二进制日志,只进行故障转移而丢失了最新的数据。使用MySQL 5.5的半同步复制,可以大大降低数据丢失的风险。MHA可以与半同步复制结合起来。如果只有一个slave已经收到了最新的二进制日志,MHA可以将最新的二进制日志应用于其他所有的slave服务器上,因此可以保证所有节点的数据一致性。

目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库,因为至少需要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,目前淘宝TMHA已经支持一主一从。(出自:《深入浅出MySQL(第二版)》)
MHA工作原理总结为以下几条:
(1)从宕机崩溃的master保存二进制日志事件(binlog events);
(2)识别含有最新更新的slave;
(3)应用差异的中继日志(relay log) 到其他slave;
(4)应用从master保存的二进制日志事件(binlog events);
(5)提升一个slave为新master;
(6)使用其他的slave连接新的master进行复制。
自带脚本:
自动切换脚本:/usr/local/bin/master_ip_failover
手动切换脚本:/usr/local/bin/master_ip_online_change

图中的MHA阐述

  1. 服务为主备架构,部署在IDC-A和IDC-B,其中主流量在IDC-A;MHA MANAGER则部署在IDC-C(第三个机房),这样才能保证任意一边的IDC出问题,都不影响MHA的切换;
  2. 为了防止来回切导致严重数据问题。可以设置,当MHA发生自动切换时,MHA MANAGER无论成功与否都会退出;
  3. MHA在故障时可以进行数据补齐。

MySQL 半同步复制

主从复制的基本原理

  1. [master] SQL操作存入binLog中;
  2. [slave] 连接master,进行数据同步;
  3. [master] dump thread 把binlog数据发送到slave中;
  4. [slave] 创建I/O线程读取 master传输过来的binlog内容并写入到relay Log;
  5. [slave] 创建SQL线程,从relay Log读取并执行。

主从复制的方式

  1. 异步复制(Asynchronous replication)

    • MySQL默认的复制即是异步的,主库先提交事务,然后立即响应客户端。
    • 如果主库crash,且主库上已经提交的事务还没有同步到相应的从库上,那么当从库提升为主时,会导致新主上的数据不完整。
    • 性能最好
  2. 全同步复制(Fully synchronous replication)

    • 当主库执行完一个事务,且所有的从库都同步完之后才响应客户端。
    • 性能差
  3. 半同步复制(Semisynchronous replication)

    • AFTER_COMMIT;即参数 rpl_semi_sync_master_wait_point = after_commit
    • 介于异步复制和全同步复制之间,主库提交完事务之后不立即响应客户端,而是等待至少一个从库接收到并写到relay log中才响应客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。
    • 等待的时间以rpl_semi_sync_master_timeout参数为准,默认为10秒。在这等待的10秒里,对其他会话该事务是可见的;所以一旦master发生宕机,对外就会产生不一致的影响
    • Slave ACK超时,将退化为异步复制模式 (所以半同步复制并不是严格意义上的半同步复制)
  4. 增强半同步(Loss-less Semi-Synchronous)

    • AFTER_SYNC;即参数 rpl_semi_sync_master_wait_point = after_sync
    • after sync是MySQL5.7官方新加以解决MySQL5.6半同步缺陷的选项,也是官方推荐的方式。
    • 原理:客户端发送过来一个请求,经过mysql的SQL分析,存储引擎处理,写入binlog,然后 写入从库的relaylog,存储引擎层提交,最后返回给客户端。
    • 优点:主库把SQL操作先发给从库的relay log,然后再提交,再响应给客户端,这个过程即使 在storage commit之后主crash了,日志也已经写入到relay log中,从库和主库数据一致。
    • 在commit之前等待Slave ACK,可以堆积事务,利于group commit,有利于提升性能。
    • 在master接受到Slave ACK之前,数据的变化对其他会话时不可见的,因为此时并未提交,从 而也不会产生数据不一致的影响。
    • 同样,Ack超时,也将退化为异步复制模式
  5. 组复制 MySQL Group Replication(MGR)

    • MGR内部实现了分布式数据一致性协议,paxos通过其来保证数据一致性。

after_commit VS after_sync


  • after_commit:master把每一个事务写到二进制日志并保存到磁盘上,并且提交(commit)事务,再把事务发送给从库,开始等待slave的应答。响应后master返回结果给客户端,客户端才可继续。
  • after_sync :master把每一个事务写到二进制日志并保存磁盘上,并且把事务发送给从库,开始等待slave的应答。确认slave响应后,再提交(commit)事务到存储引擎,并返回结果给客户端,客户端才可继续。
  • 半同步和增强半同步都是等待slave的ACK后才给客户端返回成功(也就是整个流程完成)

总结

  • 一致性要求高的,比如金融类的(相比其他业务TPS较低),可以考虑开启增强半同步复制

其他

  1. MySQL 5.7新增了rpl_semi_sync_master_wait_for_slave_count系统变量,可以用来控制主库接收多少个从库写事务成功反馈,给高可用架构切换提供了灵活性。 当该变量值为2时,主库需等待两个从库的ACK。

Consul

介绍

  • Consul is a tool for service discovery and configuration. Consul is distributed, highly available, and extremely scalable
  • Consul是一个服务管理软件。支持多数据中心下,分布式高可用的,服务发现和配置共享。采用 Raft 算法,用来保证服务的高可用。
  • Consul使用Gossip Protocol来管理成员资格并向集群广播消息。所有这些都是通过使用Serf库提供的。
  • 关于raft算法原理,可以后续再讲。

和MHA的结合使用

  1. checkmysql 脚本部署到每台 consul server 中, 实现了多点检测 MySQL 是否正常;
  2. checkmysql 脚本在超过半数的情况下调用 masterha_manager_consul 脚本进行主从切换;

主从切换

  • MHA 是切换工具,控制数据库主从切换和数据补齐;
  • MHA 进行故障检测,故障时进行切换并通知Consul下发新的主库配置到应用服务。

从库上下线

  • Consul可以对从库进行健康检查,通过配置下发控制从库上下线。

扩展

CMDB

  • 配置管理数据库( Configuration Management Database,CMDB)
  • 自动化运维立足之本。在容灾切换管理工具中,可以直接一键从CMDB中同步所有业务系统,并能够非常灵活的定义每个业务系统的切换过程环节以及每个环节所有执行的具体操作。
  • CMDB与容灾备份的关联
  • 好的CMDB建设,应该具备这些要素
  • 【运维探讨】如何实现更加简单、高效、安全的灾备切换管理?

脑裂

  • 脑裂问题是分布式多活建设必须面临的问题之一。
  • 以上面的架构进行描述,当IDC-A和IDC-B、IDC-C网络不通时,其实IDC-A就是一个网络孤岛。
    这时候时IDC-B中的从库就会提升为主库,并开始接收写操作。因为IDC-A已经是个数据孤岛,服务的主从库并未发生改变(接收不到consul下发的配置),此时也接受外部的写操作请求,那么就会造成两边数据都有写操作,错误的双主架构导致错误的数据问题。

如何避免脑裂问题

  1. 如何让IDC的服务可以判断自身是否孤岛,从而拒绝服务,避免数据问题呢?
  2. 其中一个方案使用Consul作为选主服务来解决。后续另开文章叙述。
  3. 使用etcd:etcd 实现故障时主备秒级切换高可用架构
  4. 分布式锁服务Chubby(参见文献[Bur06])集群锁服务提供一个与文件系统类似的API用来操作锁。Chubby 可以处理异地、跨机房级别的锁请求。Chubby 使用Paxos协议来提供分布式一致性(具体描述参看第23章)。Chubby 是实现主实例选举(Master-Election)过程的关键组件。例如,一个服务有5个冗余实例在同时运行,但是只有一个实例可以处理对外请求,一般的做法是通过Chubby进行自动选举,选择一个实例成为主实例。Chubby适合存放那种对一致性要求非常高的数据。—《SRE:Google运维解密》

结合raft的思考

  • 为了避免脑裂,需要有选主机制,一般超半数的投票才能成为leader;Consul就是基于raft是实现的;
  • 在线上部署consul必须至少是三个机房,因为如果只有两个机房,其中一个机房挂了(刚好是大多数机器的机房),服务将不可用;
  • 分布式存储系统,需要解决数据的一致性问题和脑裂问题。
    1. raft有实现,但是首先得基于raft协议的文件存储;
    2. 使用MySQL作为存储,Consul作为选主服务的业务:Consul可以解决脑裂问题
      • MySQL的增强半同步复制机制 支持配置n个从库ack才响应客户端(其实和raft大多数结点写成功才算成功有点类似[Quorum机制]),可以很大程度的避免丢数据导致不一致。
  • 一般金钱业务使用同城两个机房,主备架构,那么不能完全和raft三机房匹配(三机房意味着一定每个机房至少有一个结点接收到数据才算成功)。当然每个机房可以有多个DB,比如同城的两个机房A合B,A有一主一丛,B有两从。增强半同步可以根据实际情况配置rpl_semi_sync_master_wait_for_slave_count参数,指定必须多少个从库成功。
    • MySQL使用异步复制的,一般情况下,切完机房保持数据一致性或检查监控数据一致性的方案,需要业务方自行监控和修正。
    • 就算使用了增强半同步,理论上数据也只是落盘到relay log,极端情况下,从库也可以立马故障,甚至无法恢复。这种极端情况基本不考虑了,只能业务自己权衡,允不允许丢数据,有没有其他修复数据机制(日志文件或对账等),要不要继续提供服务了。

Q&A

为什么Dump和I/O线程不能多线程?

  1. dump线程和IO线程都是负责网络传输,如果将这里扩展为多线程那么会将一份Binlog日志分割为多份,并行传输,那么在slave端将会要额外的增加代码考虑如何将多份日志还原为原来的Binlog,大大增加难度。
  2. 性能瓶颈不在IO,扩展后也没有多大效率提升。
  3. 为什么Redis 6.0使用IO多线程增强性能,MySQL这里使用IO多线程却不行?
    • Redis是多个Client节点一个Server节点(暂且这么看),IO线程需要处理多个不同Client来源的请求;MySQL主从复制,本质上是1个Client端一个Server端,增大IO线程也无济于事。

增强半同步是否会导致从有数据而主却没有?

  • 是。在Loss-less Semi-Synchronous模式下,master在调用binlog sync之后,engine层commit之前等待Slave ACK(需要收到至少一个Slave节点回复的ACK后)。这样只有在确认Slave收到事务events后,master事务才会提交,然后把结果返回给客户端。此时此事务才对其他事务可见。在这种模式下解决了after_commit模式带来的幻读和数据丢失问题,因为主库没有提交事务。但也会有个问题,假设主库在存储引擎提交之前挂了,那么很明显这个事务是不成功的,但由于对应的Binlog已经做了Sync操作,从库已经收到了这些Binlog,并且执行成功,相当于在从库上多了数据,也算是有问题的,但多了数据,问题一般不算严重。这个问题可以这样理解,作为MySQL,在没办法解决分布式数据一致性问题的情况下,它能保证的是不丢数据,多了数据总比丢数据要好。

MHA本身就支持自动切,为什么还要使用Consul?

  • MHA本身提供了自动切换主库的功能,但是MHA本身没有提供通知应用等机制。因此采用比较成熟的方案MHA+consul,并以SDK的方式接入。

自动切换安全吗?

  1. 直接启用masterha_manager 自动切换脚本并不安全,主要因为在网络抖动的情况下并不能保证数据库真的不能访问。不能仅通过一个点的检测就判断数据库不可访问。
  2. 通过 Consul( Consul 提供 dns 接口)集群的特性, 增加多点检测机制, 在 n 个集群的环境中, 有超过半数的检测点检测到数据库有问题, 就认为数据库不可访问, 这时调用 masterha_manager 脚本进行切换。
  3. 网络问题千变万化,在发生切换事件之后,需有相应的方案对主从流水数据进行对账或修正(确定基于binlog与应用日志的重要数据校验与补偿机制)。
  4. 发生切换事件之后,在确定数据已经无异常之前,需要防止再自动切回去,造成严重的数据异常。所以一般情况下,只能自动切一次,直到人工介入确认无异常,重新设置为自动切模式。当然,有完善的监控比对数据异常机制的情况下,可以考虑做成自动化,无需依赖人工介入。

MHA切换之后,主库禁写后,现有的连接是否还能继续写入?


mha切库禁写时,直接锁住整个实例,新操作无法写入,直接就设置read_only。

自动切的时机如何把握?

  1. 自动切的最佳时机很难人为,必须经过多种故障场景的测试,确定合适尽可能安全的切换策略和参数。
  2. 在实践中,初期可以先告警人工介入决定是否切换;确定好合适的切换策略和参数后,自动切在非核心业务中稳定正确运行一段时间后才在核心业务运用。

MHA能保证数据一定不丢吗?

  • 在MHA自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失。但如上所述,网络等问题时无解的,理论上还是存在丢的可能性。一致性要求高的,比如金钱类的(相比其他业务TPS较低),可以考虑开启半同步复制,大大降低数据丢失的风险。

新的主库和原主库数据一致性问题如何解决?

  1. MHA只能尽量保证数据补齐;
  2. 主从延迟较大时,切主库有风险;
  3. 开启半同步复制可以大大降低丢数据的风险,但也带来一定的性能损耗;
  4. 要做好切库后,主从日志流水对比修复方案

不一致如何止损?

  1. 根据业务情况进行实现,比如在发生切换事件的一端时间内(比如一个小时),阻断大额交易操作,等待开发确认后再恢复;
  2. 具体实现可以使用redis存储数据快照,执行前和数据库的数据进行对比判断是否阻断,或其他可行方案;
  3. 是否应该阻断,公司的利益和用户的利益,这是个哲学问题。。。

扩展

  • 云数据库使用数据库代理进行连接:读写分离扩展云数据库 MySQL 性能
  • 切换网络

Reference

  1. 基于 consul 架构的 MHA 自动切换
  2. 基于MHA+consul的MySQL高可用设计
  3. MySQL高可用之MHA的搭建
  4. MHA官方介绍
  5. 京东MySQL数据库主从切换自动化
  6. MySQL数据库的授权原则
  7. MySQL MHA 搭建&测试
  8. MySQL半同步复制
  9. MySQL - 异步复制,半同步复制,增强半同步复制,组复制,全告诉你
  10. mysql 半同步复制
  11. 增强半同步复制
  12. 【MySQL】5.7增强半同步AFTER SYNC&AFTER COMMIT

使用Redis实现榜单

发表于 2020-08-31

一、前言

  1. 使用redis实现
  2. 基于直播间业务场景
  3. 不阐述详细实现细节

二、相关Redis数据结构和命令

Redis 集合(Set)

  1. Sismember 命令判断成员元素是否是集合的成员。

Redis 有序集合(sorted set)

  1. Zrevrank 命令返回有序集中成员的排名。其中有序集成员按分数值递减(从大到小)排序。
  2. Zincrby 命令对有序集合中指定成员的分数加上增量 increment
  3. Zrevrangebyscore 返回有序集中指定分数区间内的所有的成员。有序集成员按分数值递减(从大到小)的次序排列
  4. Zremrangebyrank 命令用于移除有序集中,指定排名(rank)区间内的所有成员。

其他

  1. 查找特定前缀key:scan命令

三、如何实现

榜单保存

  1. 使用 Redis 有序集合(sorted set)保存榜单数据
  2. 如果是按时间排序的榜单,把时间戳存到score字段;如果是按礼物数量排序,把数量存到score;其他排序场景同理

榜单添加数据操作幂等

  1. 使用数据库日志表(唯一索引) (最严格可靠)
  2. 使用一个set保存所有的消息ID,并使用sismember防止重复处理(并发场景可能不幂等)

数据清理

  1. 使用一个set保存现有所有在线的房间榜单;定时任务检查房间是否在播,不在线的进行清理(同时可以监听房间下播时间)
  2. 保存一定数量的redis榜单:Zremrangebyrank 命令用于移除有序集中,指定排名(rank)区间内的所有成员
  3. 使用scan命令 查找特定前缀key的榜单,同1或2操作进行清理

四、扩展

  1. 房间榜单的标识是房间id有时可能不够,因为通过榜单有时是和本场开播挂钩的,同一个房间多次开播,可能导致不同场次的数据导致榜单错误。
    增加房间开播id标识可以解决。
  2. 老生常谈的哲学问题:二八定理。花费大量时间来得到较低的收益,实现时要从业务看是否值得。但不代表在做设计方案时不去考虑,这是严谨性的问题。
    按极端的方式考虑,实际实现按业务需要进行选择折中。

关于CDN缓存总结摘要

发表于 2020-08-20

CDN缓存的几点总结

  1. CDN资源的标识: url
  2. 跟HTTP缓存无关的请求头不影响CDN缓存(亲测)
  3. 不仅是静态资源,接口的数据可以做CDN缓存(亲测)
  4. CDN服务一般都有默认的缓存配置(比如一分钟),服务端可以通过设置HTTP缓存相关的Header控制是否适用CDN缓存
  5. HTTP缓存和CDN缓存分别作为客户端缓存和服务端缓存

HTTP缓存

关键字段有Expires,Cache-Control ,Last-Modified ,Etag 四个字段,Expires和Cache-Control用来确定确定缓存的存储时间,Last-Modified 和Etag则用来确定缓存是否要被更新

强制缓存

控制强制缓存的字段分别是Cache-Control和Expires,其中Cache-Control优先级比Expires高

  1. Expires: HTTP1.0的,已废弃
  2. Cache-Control: HTTP1.1中用来控制缓存时间的参数 (Cache-Control:max-age=30;xxx;)
    public: 表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存。
    private: 表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。
    max-age=seconds: 设置缓存存储的最大周期,相对于请求的时间缓存seconds秒,在此时间内,访问资源直接读取本地缓存,不向服务器发出请求。(与expires同时出现时,max-age优先级更高)
    s-maxage=seconds: 规则等同max-age,覆盖max-age 或者 Expires 头,但是仅适用于共享缓存(比如各个代理),并且私有缓存中它被忽略。(与expires或max-age同时出现时,s-maxage优先级更高)
    no-store: 不缓存服务器响应的任何内容,每次访问资源都需要服务器完整响应
    no-cache: 缓存资源,但立即过期,每次请求都需要跟服务器对比验证资源是否被修改。(等同于max-age=0)
    

协商缓存

协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。控制协商缓存的字段分别有:Last-Modified / If-Modified-Since和Etag / If-None-Match,其中Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高。

  1. Last-modified: 源头服务器认定的资源做出修改的日期及时间。精确度比Etag低。包含有If-Modified-Since或 If-Unmodified-Since首部的条件请求会使用这个字段。
  2. Etag: HTTP响应头是资源的特定版本的标识符。

如何控制不使用缓存

  • F5刷新:
    (Cache-Control: max-age=0)
    浏览器会设置max-age=0,跳过强缓存判断,会进行协商缓存判断【浏览器直接对本地的缓存文件过期,但是会带上If-Modifed-Since,If-None-Match(如果上一次response带Last-Modified, Etag)这就意味着服务器会对文件检查新鲜度,返回结果可能是304,也有可能是200.】
  • 强制刷新 (command+shift+R):浏览器不使用缓存,因此发送的请求头部均带有 Cache-control: no-cache(为了兼容,还带了 Pragma: no-cache),服务器直接返回 200 和最新内容。
    ctrl+F5强制刷新:
    (Cache-Control: no-cache)
    跳过强缓存和协商缓存,直接从服务器拉取资源。【浏览器不仅会对本地文件过期,而且不会带上If-Modifed-Since,If-None-Match,相当于之前从来没有请求过,返回结果是200.】
  • 如何不缓存
    Cache-Control其他字段:
    no-cache: 虽然字面意义是“不要缓存”。但它实际上的机制是,仍然对资源使用缓存,但每一次在使用缓存之前必须向服务器对缓存资源进行验证。
    no-store: 不使用任何缓存
    禁止缓存:
    Cache-Control: no-cache, no-store, must-revalidate
    Expires:设为当前时间之前
  • 强缓存存在两种形式:from memory cache 与 from disk cache (浏览器F12查看)

CDN缓存

  • cdn缓存是一种服务端缓存
  • 与http缓存规则不同的是,这个规则并不是规范性的,而是由cdn服务商来制定
  • 回源的意思就是返回源站,何为源站,就是我们自己的服务器;CDN回源,没有资源就去源站读取,有资源就直接发送给用户。
  • cdn缓存配置,整体来说,建议和http缓存配置保持统一

不一致的影响

cdn的缓存配置会受到http缓存配置的影响,而且各个cdn服务商并不完全一致,以腾讯云为例,在缓存配置的文档中特别有以下说明。
这会对我们有什么影响呢?

  1. 如果我们http缓存设置cache-control: max-age=600,即缓存10分钟,但cdn缓存配置中设置文件缓存时间为1小时,那么就会出现如下情况,文件被访问后第12分钟修改并上传到服务器,用户重新访问资源,响应码会是304,对比缓存未修改,资源依然是旧的,一个小时后再次访问才能更新为最新资源
  2. 如果不设置cache-control呢,在http缓存中我们说过,如果不设置cache-control,那么会有默认的缓存时间,但在这里,cdn服务商明确会在没有cache-control字段时主动帮我们添加cache-control: max-age=600。
    注:针对问题1,也并非没有办法,当我们必须要在缓存期内修改文件,并且不向想影响用户体验,那么我们可以使用cdn服务商提供的强制更新缓存功能,主要注意的是,这里的强制更新是更新服务端缓存,http缓存依然按照http头部规则进行自己的缓存处理,并不会受到影响。

缓存配置

  • cdn缓存的配置并不复杂, 复杂的情况在于cdn缓存配置会受到http缓存配置的影响,并且不同的cdn运营商对于这种影响的处理也都不一致,实际使用时,建议去对应的cdn服务商文档中找到对应的注意事项。
  • CDN缓存控制:如果源站设置了 no-cache 、private、 max-age = 0 都遵循源站,CDN 是不会进行缓存的。
  • 又拍云为开发者执行缓存刷新提供了主动更新和被动更新两种方式。
    1. 主动更新主要是指同名资源在源服务器更新之后,开发者手动刷新文件。又拍云提供了可视化的操作台供用户执行缓存刷新操作,同时支持 URL 刷新和规则刷新。此外开发者也可通过 API 接口完成刷新操作。
    2. 被动刷新则是等文件在 CDN 节点的缓存过期之后,节点回源拉取源服务器上最新的文件。这个过程由 CDN 自动完成,无需手动操作。

扩展

  • 动态CDN加速

  • CDN的全称是Content Delivery Network,即内容分发网络

  • 动态CDN加速:非静态数据,通过CDN的加速来起到快速回源的效果的。使用到的就是CDN的快速传输的能力。其实也就是DSA(Dynamic Site Acceleration)

    • 传统的DSA有:
      • TCP 优化:设计算法来处理网络拥堵和包丢失,加快这些情况下的数据从cdn的恢复以及一些常见的TCP瓶颈
      • Route optimization:就是优化从源到用户端的请求的线路,以及可靠性,就是不断的测量计算得到更快更可靠的路线
      • Connection management:就是边缘和源之间,包括CDN之前的线路,采用长连接,而不是每一个请求一个连接
      • On-the-fly compression:就是数据在刚刚离开源的时候就进行压缩,可以缩短在整个网络之中的流通时间
      • SSL offload:加速或者说减少一些安全监测,减少原服务器执行这种计算密集型的压力
      • Pre-fetching:有的服务可以解析HTML文件,并将原始服务器预取缓存对象嵌入到文件中
    • 更可靠的连接(只要负责连接边缘服务器,如果直接走回源线路的话,线路会很长,不可靠)
  • 使用CDN隐藏服务器真实IP

    • 隐藏服务器真实IP是解决问题最好和最快的方法,但只针对小流量,大流量同样会扛不住。
      服务器前端加CDN中转,比如阿里云、百度云加速、360网站卫士、加速乐、安全宝等,如果资金充裕的话,可以购买高防的盾机,用于隐藏服务器真实IP,域名解析使用CDN的IP,所有解析的子域名都使用CDN的IP地址。此外,服务器上部署的其他域名也不能使用真实IP解析,全部都使用CDN来解析。
    • 另外防止服务器对外传送信息泄漏IP,最常见的是,服务器不使用发送邮件功能,如果非要发送邮件,可以通过第三方代理(例如sendcloud)发送,这样对外显示的IP是代理的IP。

Reference

  • 聊聊 CDN 缓存与浏览器缓存
  • http缓存与cdn缓存配置指南
  • CDN 基础架构及缓存控制
  • 从HTTP响应头看各家CDN缓存技术
  • HTTP 缓存机制

打赏类业务货币体系简述

发表于 2020-08-04
  • 在打赏类业务中,消费跟分成是紧紧挂钩的。比如在直播间送礼,用户通过花费虚拟货币给对方送礼,而对方则得到相应的分成。
  • 定义:用户花费的是“金币”,接受者得到的是“银币”。

设计概要

一、用户货币类型组成

  1. 用户通过充值或活动赠币等方式得到“金币(coin)”
    • 充值行为得到的是“充值金币(money)”
    • 活动赠币等非充值行为得到的是“非充值金币(virtualCoin)”
    • coin=money + virtualCoin
  2. 消费行为的接受者(收益方)得到的是“银币(bean)”

二、业务情况

所有的业务场景其实都是对上述几种货币类型的加减,主要分为以下几类:

  1. 充值业务
  2. 消费业务(伴随着分成)
  3. 赠币业务(活动获取)
  4. 兑换业务(“银币”可以兑换成“金币”进行消费)
  5. 结算业务(“银币”可以进行提现)
  6. 管理员调整(运营行为,对用户货币进行调整)

三、冻结账户设计

针对消费场景,有两种形式的消费:

  1. 即时消费(比如送礼);
    • 用户消费的同时,收益方立即得到相应的分成
  2. 延迟消费(比如申请上麦)
    • 先对用户的“金币“进行冻结,根据最终的结果,对用户冻结的金币进行结算或退回;用户的消费时间为实际结算的时间(不是冻结时的时间)。

  • 冻结&结算 和 消费&退款 在技术实现设计上的差异:
    1. 前者两次RPC,后者一次RPC
    2. 前者以结算时间作为消费完成时间;后者是以扣币时间作为消费完成时间,且退款会导致营收数据受影响

《程序员的职业素养》摘要

发表于 2020-07-21

6年前看的书,重新整理一下

前言

摘要

一 (专业主义)

  1. 专业主义的精髓就在于将公司的利益视同个人的利益。(这个呢,看情况吧)
  2. 不能忽略完整的测试环节,否则就交付软件是不负责任的。
  3. 为自己的不完美负责。代码难免出现bug,但这并不意味着你不用对它们负责。
  4. 让QA找不出任何问题。把自己没把握的代码发送给QA是不专业的,违背了“不行损害之事”的原则。
  5. 有些代码很难测试,是因为设计时就没考虑如何测试。唯一的解决办法就是要设计易于测试的代码,最好事先写测试,再写要测的代码。(前半句挺对,后半句实际上比较难操作?)
  6. 职业发展是你自己的事。雇主没有义务确保你在职场能够立于不败之地。
    • 雇主出了钱,你必须付出时间和精力。一周工作60个小时,前40小时给雇主,后20小时是给自己的。你应该看书,练习,学习,做一些提升职业能力的事情。
    • 每天大概是3个小时是给自己提升的,你可以在路上学习,在公交学习等,利用一些时间碎片。
    • 一周有168小时,给你雇主40小时,为自己的职业发展留20小时,剩下的108小时再留56小时给睡眠,那么还剩52小时可做其他的事。
    • 其实这样让你免于枯竭匮乏,假设你热爱软件开发,渴望成为专业开发者,在那20个小时里,就应该做能够激发,强化你的热情的事,那20小时是充满乐趣!
  7. IT行业发展迅猛,要时常了解自己的领域,坚持广泛学习才不至于落伍,但并不意味着忘掉过去。别忘了桑塔亚纳的诅咒:“不能铭记过去的人,注定重蹈先人的覆辙”。
  8. 每个软件开发人员必须精通的事项:
    设计模式。GOF书中的全部24种模式。
    设计原则。必须了解SOLID原则,而且深刻了解组件设计原则。
    方法。必须理解XP,Scrum,精益,看板,瀑布,结构化分析及结构化设计等。
    实践。必须掌握测试驱动开发,面向对象设计,结构化编程,持续集成和结对编程。
    工件。必须了解如何使用UML图,DFD图,结构图,Petri网络图,状态迁移图表,流程图和决策表。
    

    • 练习。业精于勤,真正专业人士往往勤学苦干,以求得自身技能的纯属精炼。
    • 合作。学习的第二个最佳方法就是与他人合作。从彼此身上学到很多东西,而且能在更短的时间内更高质量地完成更多工作。并不是要花全部时间一直和别人共事,独处的时间也更重要。
    • 辅导。教学相长,想迅速牢固地掌握某些事实和观念,最好的方法就是与由你负责的人交流这些内容。传道授业中,导师也会从中受益。
  9. 了解业务领域。了解自己所开发项目的业务领域,了解该领域的基本架构和基本知识,一边同客户和用户访谈。花时间与业内专家交流,了解他们的原则和价值观念。
  10. 雇主的问题就是你的问题。弄明白这些问题,并寻求最佳解决方案。开发系统时,站在雇主的角度思考,确保开发的功能真正满足雇主的需要。

二 (说“不”)

  1. 许诺“尝试”,就意味着你承认自己之前未尽全力,承认自己还有余力可施。
    只要你许诺会去“尝试”,你其实是在承诺你会确保成功。
    从本质上讲,承诺“尝试”就是一种不诚实的表现。你这么做的原因,可能是为了护住面子和避免冲突。
  2. 坚守专业主义精神,不能为了赶工而写出糟糕的代码,如果不能做到,当初就应该说“不”。
    (这个吧,尽量吧,前提老板是个讲道理的人。。。。)

三 (说“是”)

  1. 口头上说。心里认真。付诸行动。
    做出承诺,包含三个步骤。
    1口头上说自己将会去做。
    2心里认真对待做出的承诺。
    3真正付诸行动。

  2. 没有做到自己对他人之前的承诺,会让自己难堪。言必信,行必果。
    你只能承诺自己能完全控制的事。
    如果你不尽早告诉别人可能的问题,就错失了让他们帮助你达成目标,兑现承诺的机会。
    (前提是老板要讲道理啊。。。)

  3. 若为了赶工完成任务,周六日加班,那么要求周三才上班也是应该的。 (现实情况。。。)

四 (编码)

  1. 编码是一项颇具挑战也十分累人的智力活动。相比其他,编码要求更加聚精会神。
    自己的代码要让其他人看得懂。(将心比心啊!)
  2. 如果感到疲劳或者心烦意乱,千万不要编码。
    奉献精神和职业素养,更多意义上指要遵循纪律原则而非成为长时间工作的工作狂。
    要确保自己已经将睡眠,健康和生活方式调整到最佳状况,这样才能做到每天的8个小时工作时间内全力以赴。 (虽然生活欺骗了你,但自己也别自暴自弃。。。。)
  3. 中断无法避免,总有人会打断你,消耗你的时间。发生这种情况时要记住一点,也许下次也会轮到你去打断别人请求帮助。因此,礼貌地表现出乐于助人的态度才是专业的态度。(还是将心比心!)
  4. 当大脑已经无法正常思考却硬逼自己在深夜还加班解决问题,你只会把自己折腾得更累,回家洗澡之类的反而会豁然开朗。
    当碰到困难而受阻时,当你感到疲倦时,就离开一会儿,让富有创造力的潜意识接管问题。
    精力分配得当,你将能在更短的时间内以更少的精力完成更多的事情。让自己保持好节奏,让团队保持好节奏。
    了解你的创造力和智力运行的模式,充分发挥它们的优势而非与之背道而驰。
    埋头忙于解决问题时,有时候可能会由于和问题贴得太近,无法看清楚所有的可选项。由于大脑中富有创造力的部分被紧张的专注力所抑制,你会错过漂亮的解决方案。
    (适当放松一下,欲速则不达!!)
  5. 互相帮助是每个程序员的职责所在。作为专业人士,要以随时帮助别人为荣。
    当然你需要独处时间,你可以直接并礼貌的告诉别人你在某个时间段不希望被人打扰。
    (自重感啊)
  6. 接受他人的帮助。如果有人向你伸出援手,要诚挚接受,心怀感激地接受帮助并诚意合作。
    不要因为自己进度压力很大,就推开伸来的援手。不妨给他半个小时的时间。如果到时那个人不能真正帮到你,再礼貌地致歉用感谢结束谈话也不迟。要记住,如同要以乐于助人为荣一样,也要以乐于接受别人的帮助为荣。
    要学会如何求助。如果帮助唾手可得却让自己一个人堵在那儿,是很不专业的表现。
    (透明透明!不盲目埋头苦干!)
  7. 辅导缺乏经验的程序员是那些经验丰富的程序员的职责。向资深导师寻求辅导也是年轻程序员的专业职责。(大家都那么菜,别不好意思!)

六 (练习)

  1. 保持不落伍的一种方法是为开源项目贡献代码。
  2. 职业程序员是用自己的时间来练习。老板的职责不包括避免你的技术落伍,也不包括为你打造一份好看的履历。
    既然你是用自己的时间练习,就不必限制在老板规定的语言和平台。可以选择你喜欢的语言,练习你喜欢的技术。
    (要多多学习啊!)

九 (时间管理)

  1. 受到邀请的会议没有必要全部参加。参加的会议太多,其实只能证明你不够专业。理智使用时间,谨慎选择,礼貌拒绝。
    邀请你参加会议的人并不负责管理你的时间,为时间负责的只有你。
    领导最重要的责任之一,就是帮你从某些会议脱身。好的领导一定会主动维护你拒绝出席的决定,因为他和你一样关心你的时间。
    (时间宝贵,无效浪费还不如用来睡觉。。。)
  2. 如果会议让人厌烦,就离席。如果你发现参加某个会议是在浪费时间,就应当想个礼貌的方法退出来。
    重要的是,你应当明白,继续呆在会议室里是浪费时间;继续参加对你没有太多意义的会议,是不专业的行为。
  3. 如果受到会议邀请,务必弄清楚指定的议题是什么,每个议题花多长时间没要取得什么成果。如果得不到确切的答案,你可以礼貌拒绝。
  4. 专业开发人员会安排好他们的睡眠,保证清晨有饱满的注意力去上班。
  5. 运动需要肌肉的注意力,而编程需要的是心智的注意力。肌肉注意力有助于改善心智注意力。
  6. 时间拆分与番茄工作法。
  7. 专业开发人员会评估每个任务的优先级,排除个人喜好和需要,按照真实的紧急程度来执行任务
  8. 选择了走不通的技术道路,你对这个决定越是坚持,浪费时间就越多。
    专业开发人员不会执拗于某个不容放弃的主意,他们会保持开放的头脑来听取其他意见,让自己有多种选择,一旦看清楚,就会避开。

十(预估)

  1. 专业开发人员能够清楚区分预估和承诺。只有在确切知道可以完成的前提下,他们才会给出承诺。而且会尽可能清楚说明预估的概率分布,这样主管就可以做出合适的计划。
  2. 大多数情况下,专业人士都不会给出确切的承诺,而是提供概率预估,来描述期望完成时间及可能的变数。

十一(压力)

  1. 即使有压力,专业人士也会冷静果断。尽管压力不断增大,他仍然会坚守所受的训练和纪律,他知道这些是他赖以战胜有最后期限和承诺所带来的压力感的最好方法。
  2. 快速前进确保最后期限的方法,便是保持整洁。专业人士不会为了快点前进而乱来。脏乱只会导致缓慢。
  3. 观察自己在危机时刻的反应,就可以了解自己的信念。如果在危机中依然遵循着你守持的纪律,就说明你确信这些纪律。
    如果在平常时候你会注意保持代码整洁,但在危机时刻你却产出混乱的代码,就说明你并不真正相信混乱会导致速度下降。
    如果你遵守的纪律原则是工作的最佳方式,那么即使是深度危机中,也要坚决秉持这些纪律原则。

十二(协作)

  1. 专业程序员最糟糕的表现就是两耳不闻窗外事,只顾一头将自己埋在技术堆里,甚至连公司业务火烧眉毛行将崩溃了也不闻不问。
    你的工作职责就是要让业务免于陷入困顿,让公司可以长久发展下去。
    专业程序员会花时间去理解业务。他们会和用户讨论他们正在使用的软件,会和销售人员与市场人员讨论所遭遇的问题,会和经理们沟通,明确团队的短期目标和长期目标。

  2. 不正常的团队最糟糕的症状是,每个程序员在自己代码周边筑起一道高墙,拒绝让其他程序员接触到这些代码。
    这样会造成许多重复代码,模块间的接口完全是杂乱混淆而非正交的。
    将代码所有权的各种隔断全部打破,由整个团队共同拥有全部代码的做法,相较于此要好得多。
    专业开发人员不会阻止别人修改代码的。他们通过合作来达到学习的目的。

十四(辅导、学徒期与技艺)

  1. 计算机科班毕业生的质量一直令我颇感失望。究其原因,并不是这些毕业生不够聪明或缺乏天份,而是由于大学并没有教授真正的编程之道。
  2. 我们今天的做法和我所提倡的理想化的学徒制程序,这两者之间的主要差异在于技术方面的传授,培训,督导和检查。
    观念上最大差别在于,专业主义价值观和技术敏锐度需要进行不断的传授,培育,滋养和文火慢炖,直至其深植入文化当中。
    我们当前的做法之所以传承无力, 主要是因为其中缺少了资深人士辅导新人向其传授技艺的环节。


附录

编辑推荐

编程大师Bob大叔40年编程生涯心得体会
讲解成为真正专业程序员所需态度原则
业界权威好评,广受赞誉
助您职业生涯迈上更高台阶

媒体推荐

Bob大叔的这本新作又一次抬高了专业程序员的门槛,指出了他们需要在历练尚浅的软件开发职业生涯中需要不断精进的内容。
——Markus Gartner,it-agile公司资深软件开发者

有一些技术书颇具启发与教益,有一些则读来轻松喜悦且富有趣味,但很少有技术书籍能够同时兼具所有这四个特色。我感觉Martin所有的书都可归入此列。
——George Bullock,微软公司资深程序经理

如果计算机科学学位要求有“毕业后必读书单”,本书当在其列。本书描述了迈向专业程序员的修炼旅程……而且阅读起来确实异常有趣。
——Jeff Overvey,伊利诺伊大学厄本那-香槟分校

如果你期望自己能成为软件专业人士,那么本书不容错过。
——R.L.Bogetti,Baxter Healthcare公司系统主设计师

作者简介

Robert C.Martin
世界级软件开发大师,设计模式和敏捷开发先驱,敏捷联盟首任主席,C++ Report前主编,背后辈程序员尊称为“Bob大叔”。20世纪70年代初成为职业程序员,后创办Object Mentor公司并任总裁。Martin还是一名多产的作家,至今已发表数百篇文章、论文和博客,除本书外,还著有《代码整洁之道》、《敏捷软件开发:原则、模式和实践》、《UML:Java程序员指南》等。他最近创办了cleancoders.com网站,专为软件开发人员提供教育视频。

目录

目 录

第1章 专业主义 1
1.1 清楚你要什么 2
1.2 担当责任 2
1.3 首先,不行损害之事 4
1.3.1 不要破坏软件功能 4
1.3.2 不要破坏结构 7
1.4 职业道德 8
1.4.1 了解你的领域 10
1.4.2 坚持学习 11
1.4.3 练习 11
1.4.4 合作 12
1.4.5 辅导 12
1.4.6 了解业务领域 13
1.4.7 与雇主/客户保持一致 13
1.4.8 谦逊 13
1.5 参考文献 14

第2章 说“不” 15
2.1 对抗角色 17
2.2 高风险时刻 20
2.3 要有团队精神 22
2.3.1 试试看 24
2.3.2 消极对抗 25
2.4 说“是”的成本 27
2.5 如何写出好代码 34

第3章 说“是” 37
3.1 承诺用语 39
3.1.1 识别“缺乏承诺”的征兆 40
3.1.2 真正的承诺听起来是怎样的 41
3.1.3 总结 43
3.2 学习如何说“是” 43
3.2.1 “试试”的另一面 43
3.2.2 坚守原则 44
3.3 结论 47

第4章 编码 48
4.1 做好准备 49
4.1.1 凌晨3点写出的代码 50
4.1.2 焦虑时写下的代码 51
4.2 流态区 53
4.2.1 音乐 54
4.2.2 中断 55
4.3 阻塞 55
4.4 调试 57
4.5 保持节奏 60
4.5.1 知道何时应该离开一会 60
4.5.2 开车回家路上 61
4.5.3 洗澡 61
4.6 进度延迟 61
4.6.1 期望 62
4.6.2 盲目冲刺 62
4.6.3 加班加点 63
4.6.4 交付失误 63
4.6.5 定义“完成” 64
4.7 帮助 64
4.7.1 帮助他人 64
4.7.2 接受他人的帮助 65
4.7.3 辅导 66
4.8 参考文献 66

第5章 测试驱动开发 67
5.1 此事已有定论 69
5.2 TDD的三项法则 69
5.3 TDD的优势 70
5.3.1 确定性 70
5.3.2 缺陷注入率 71
5.3.3 勇气 71
5.3.4 文档 72
5.3.5 设计 72
5.3.6 专业人士的选择 73
5.4 TDD的局限 73
5.5 参考文献 74

第6章 练习 75
6.1 引子 75
6.1.1 10的22次方 76
6.1.2 转变 77
6.2 编程柔道场 79
6.2.1 卡塔 80
6.2.2 瓦萨 81
6.2.3 自由练习 81
6.3 自身经验的拓展 82
6.3.1 开源 82
6.3.2 关于练习的职业道德 82
6.4 结论 83
6.5 参考文献 83

第7章 验收测试 84
7.1 需求的沟通 84
7.1.1 过早精细化 86
7.1.2 迟来的模糊性 87
7.2 验收测试 89
7.2.1 “完成”的定义 89
7.2.2 沟通 91
7.2.3 自动化 92
7.2.4 额外工作 93
7.2.5 验收测试什么时候写,由谁来写 93
7.2.6 开发人员的角色 94
7.2.7 测试的协商与被动推进 95
7.2.8 验收测试和单元测试 96
7.2.9 图形界面及其他复杂因素 97
7.2.10 持续集成 98
7.3 结论 98

第8章 测试策略 99
8.1 QA应该找不到任何错误 100
8.1.1 QA也是团队的一部分 100
8.1.2 需求规约定义者 100
8.1.3 特性描述者 100
8.2 自动化测试金字塔 101
8.2.1 单元测试 101
8.2.2 组件测试 102
8.2.3 集成测试 103
8.2.4 系统测试 104
8.2.5 人工探索式测试 104
8.3 结论 105
8.4 参考文献 105

第9章 时间管理 106
9.1 会议 107
9.1.1 拒绝 107
9.1.2 离席 108
9.1.3 确定议程与目标 109
9.1.4 立会 109
9.1.5 迭代计划会议 109
9.1.6 迭代回顾和DEMO展示 110
9.1.7 争论/反对 110
9.2 注意力点数 111
9.2.1 睡眠 112
9.2.2 咖啡因 112
9.2.3 恢复 112
9.2.4 肌肉注意力 112
9.2.5 输入与输出 113
9.3 时间拆分和番茄工作法 113
9.4 要避免的行为 114
9.5 死胡同 115
9.6 泥潭 115
9.7 结论 116

第10章 预估 117
10.1 什么是预估 119
10.1.1 承诺 119
10.1.2 预估 120
10.1.3 暗示性承诺 121
10.2 PERT 122
10.3 预估任务 125
10.4 大数定律 127
10.5 结论 127
10.6 参考文献 128

第11章 压力 129
11.1 避免压力 131
11.1.1 承诺 131
11.1.2 保持整洁 132
11.1.3 危机中的纪律 132
11.2 应对压力 133
11.2.1 不要惊慌失措 133
11.2.2 沟通 133
11.2.3 依靠你的纪律原则 133
11.2.4 寻求帮助 134
11.3 结论 134

第12章 协作 135
12.1 程序员与人 137
12.1.1 程序员与雇主 137
12.1.2 程序员与程序员 140
12.2 小脑 142
12.3 结论 143

第13章 团队与项目 144
13.1 只是简单混合吗 144
13.1.1 有凝聚力的团队 145
13.1.2 如何管理有凝聚力的团队 146
13.1.3 项目承包人的困境 147
13.2 结论 148
13.3 参考文献 148

第14章 辅导、学徒期与技艺 149
14.1 失败的学位教育 149
14.2 辅导 150
14.2.1 DIGI-COMP I, 我的第一台计算机 150
14.2.2 高中时代的ECP-18 152
14.2.3 非常规辅导 154
14.2.4 艰难的锤炼 155
14.3 学徒期 156
14.3.1 软件学徒期 158
14.3.2 现实情况 159
14.4 技艺 160
14.5 结论 161

附录 工具 162

《人性的弱点》摘要

发表于 2020-07-19

十年前看过这本书,现在早就忘掉差不多了,重新整理一下。


  1. 与人相处的大秘窍:献出你真实,诚恳的赞赏。
  2. 如果这样做,你将到处受欢迎:真诚的对别人发生兴趣。
  3. 在辩论中,获得最大利益的唯一方法,就是避免辩论。
  4. 要真诚的以他人的观点去看事情。
  5. 在批评对方之前,不妨先谈谈你自己的错误。
  6. 请对方帮忙。

第一篇 待人的基本技巧

第一章如欲采蜜,勿蹴蜂房

  • 批评是没有用的,因它使人增加一层防御,而且竭力的替自己辩护。批评也是危险的,它会伤害了一个人的自尊,和自重的感觉,并激起他的反抗。
  • 人类自然的天性,是做错事只会责备别人,而绝不会责备自己,我们每个人都是如此的。
  • 不要批评,责怪或抱怨。

第二章 与人相处的大秘窍

  • 自重感,这是一种痛苦的,而且急待解决的人类「饥饿」,如果能诚挚的满足这种内心饥饿的人,就可以将人们掌握在他手掌之中。
  • 寻求自重感的欲望,是人类和动物间,一项重要的差别。它使人努力成为伟人或强盗。
  • 献出你真实,诚恳的赞赏。

第三章 左右逢源的方法

  • 如果有一个成功秘诀的话,那就是如何得到对方『立场」 的能力;由他的观点设想,正同由你自己的观点一样。
  • 一个人能设身于他人境地,能了解他人意念活动,他不必考虑到将来的前途如何。
  • 永远站在别人立场去打算、设想,并由对方的观点,去观察事物的趋向。
  • 先激起对方某种迫切的需要,若能做到这点就可左右逢源,否则到处碰壁。
  • 威立姆.温德,有一次说过:「表现自己,那是人性最主要的需要。」可是,为什么在我们事业上,不用这种同样的心理学呢?
    引起别人的渴望。
●提要
不要批评,责怪或抱怨。
献出你真实,诚恳的赞赏。
引起别人的渴望。

第二篇 使人喜欢你的六种方法

第一章 如果这样做,你将到处受欢迎

  • 真诚的对别人发生兴趣。

第二章 如何给人好印象

  • 微笑!
  • 如果你希望别人用一副高兴、欢愉的神情来接待你,那么你自己先要用这样的神情去对别人。
  • 遇到人就展开一个轻松的微笑。
  • 行动该是追随着一个人自己的感受………可是事实上,行动和感受,是并道而驰的。所以你需要快乐时,可以强迫自己快乐起来。
  • 没有给人微笑的人,更需要别人给他微笑。

第三章 你要避免发生麻烦,就请这样做

  • 你要记住你所接触中,每一个人的姓名。
  • 最简单、最明显、而又是最重要的如何获得好感的方法,就是记住对方的姓名,使别人感到自己很重要

第四章 如何养成优美而得人好感的谈吐

  • 做一个善于静听的人,鼓励别人多谈谈他们自己。
  • 很少人能拒受那专心注意所包含的谄媚。
  • 专心静听着对你讲话的人,那是最重要的,再也没有比这个更重要的了
  • 最爱挑剔的人,最激烈的批评者,往往会在一个怀有忍耐、同情的静听者面前软化下来
  • 他们所喜欢的,不是善于谈话的人,是那些静静听着的人。能养成善于静听能力的人,似乎要比任何好性格的人少见。
  • 要使别人对你感到兴趣,先要对别人感到兴趣。

第五章 如何使人感到兴趣

  • 就别人的兴趣谈论。

第六章 如何使人很快的喜欢你

  • 使别人感觉到他的重要–必需真诚的这样做。
  • 如果我们是那样的卑贱自私,不从别人身上得到什么,就不愿意分给别人一点快乐,假如我们的气量比一个酸苹果还小,那我们所要遭遇到的,也绝对是失败。
  • 自重的欲望,是人们天性中最急切的要求。
  • 最重要的定律:「你希望别人怎样待你,你就该怎样去对待别人。」
  • 真诚,一股出自内心的赞赏的力量。
  • 爱默生所说的:「凡我所遇到的人,都有比我优越的地方,而在那些方面,我能向他学习。」
    ●提要
    使人喜欢你的六种方法
    第一项规则:真诚的对别人发生兴趣。
    第二项规则:微笑。
    第三项规则:记住你所接触中,每一个人的姓名。
    第四项规则:做一个善于静听的人,鼓励别人多谈谈他们自己。
    第五项规则:就别人的兴趣谈论。
    第六项规则:使别人感觉到他的重要--必需真诚的这样做。
    

第三篇 得人同意于你的十二种方法

第一章 你不可能在争辩中获胜

  • 在辩论中,获得最大利益的唯一方法,就是避免辩论。
  • 「永远避免正面的冲突!」
  • 天下只有一种方法,能得到辩论的最大胜利,那就是尽量避免辩论………避免辩论,就像避开毒蛇和地震一样。
  • 「我们绝不可能用辩论使一个无知的人心服口服。」
  • 「跟这种冷厉,傲慢,固执的稽查员讲理,那等于是废话…….跟他争辩愈久,他愈是固执,所以我决定避免跟他争论,换个话题,赞赏他几句。
  • 释迦牟尼曾这样说过:「恨永远无法止恨,只有爱可以止恨。」
    所以误会不能用争论来解决,而需要用外交手腕,和赋予对方同情来解决。

第二章 如何避免制造敌人

  • 你可以用神态、声调,或是手势,告诉一个人他错了,就像我们用话一样的有效……而如果你告诉他错了,你以为他会感激你?不,永远不会!因为你对他的智力、判断、自信、自尊,都直接的给予打击,他不但不会改变他的意志,而且还想向你反击。如果你运用柏拉图、康德的逻辑来跟他理论,他还是不会改变自己的意志,因为你已伤了他的自尊。
  • 我所知道的只有一件事,那就是我什么也不知道。
  • 很少人有逻辑性,我们大多数的人,都怀有成见,我们之间,都受到嫉妒、猜疑、恐惧,和傲慢所毁伤。
  • 任何事情只要运用若干的手腕;并不需要告诉对方,他是如何的错误。
  • 尊重别人的意见,永速别指摘对方是错的。

第三章 如果你错了就承认

  • 迅速、坦白的承认错误
  • 假如我们已知道一定要受到责罚,那我们何不先责备自己,找出自己的缺点,那是不是比从别人嘴说出的批评,要好受得多?
    你如在别人责备你之前,很快的找个机会承认自己的错误,对方想要说的话,你已替他说了,他就没有话可说,那你有百分之九十九会获得他的谅解。
  • 任何一个愚蠢的人,都会尽力辩护自己的过错………而多数愚蠢的人是这样的一个能承认自己错误的人,却可使他出类拔萃,并且给人一种尊贵、高尚的感觉。
  • 若是我们对了,我们巧妙婉转的让别人赞同我们的观点。可是,当我们错误的时候,我们要快速的、坦直的承认我们的错误。运用这种方法,不但能获得惊人的效果,而且在若干情形下,比替自己辩护更为有趣。
  • 「用争夺的方法,你永远无法得到满足。可是当你谦让的时候,你可以得到比你所期望的更多。」

第四章 使你走上理智的大路

  • 以友善的方法开始。
  • 温柔、友善的力量,永远胜过愤怒和暴力。
  • 『让我们坐下一起商量,如果我们之间意见不同,我们不妨想想看原因到底何在,主要的症结是什么?。我们不久就可看出,彼此的意见相距并不很远,不同的地方很少,而相同的地方却很多。也就是说只要忍耐,加上彼此的诚意,我们就可以更接近了。」

第五章 苏格拉底的秘密

  • 跟人们谈话时,别开始就谈你们意见相左的事,不妨谈些彼此间赞同的事情。
  • 有说话技巧的人,开始的时候就能得到很多「是」的反应,唯有如此,他才能将听者的心埋,导向正面方向。
  • 他的处世技巧,现在被称为「苏格拉底辩论法」,就是以「是,是,」作为他唯一的反应观点。他问的问题,都是他的反对者,所愿意接受而同意的。他连续不断的获得对方的同意、承认,到最后,使反对者在不知不觉中,接受了在数分钟前,他还坚决否认的结论。

第六章 处理一个抱怨者的安全手法

  • 这是实在的,即使是我们的朋友,也宁愿多谈他们自己的成就;喜欢听我们吹嘘的人,可说少之又少。
  • 法国哲学家洛希夫克,曾这样说过:「如果你想得到仇人,你就胜过你的朋友,可是,如果想获得更多的朋友,就让你的朋友胜过你。」
  • 因为当朋友胜过我们时,那就可以满足了他的自重感。可是,当我们显出胜过朋友时,那会使他有种自卑的感觉,并会引起猜疑和妒忌。
  • 德国人有句俗语,那是:「当我们所猜疑、妒忌的人,发生一桩不幸的事时,会使我们有一种恶意的快感。」
  • 所以,别让我们表现出太多的成就来,我们要虚怀若谷、处处谦冲,那样会永远使人喜欢你,谁都愿意跟你接近。
  • 生命是短促的,别把我们不值一提的成就,作为谈话的资料,令人听了厌烦。我们要鼓励别人多说话。仔细想一想,你实在没有什么可以夸耀的。

第七章 如何使人跟你合作

  • 没有人喜欢强迫自己去买一样东西,或是被人派遣去做一件事。我们都喜欢随自已的心愿买东西,或是照着自己的意思去做事情。同时,希望有人跟我们谈谈我们的愿望、需要、想法。
  • 要让他觉得这是他自己的意思。

第八章 一个创造奇迹的公式

  • 要真诚的以他人的观点去看事情。
  • 你接触到每一件事时,会处处替别人着想。而且以对方的观点,去观察这件事情。

第九章 每个人所需要的

  • 同情对方的意念和欲望。
  • 你是不是愿意得到一句神妙的语句?一个可以停止争辩,消除怨恨,制造好感,使人们注意的听你谈话的语句。
    是的,就有这样一句话,让我告诉你。你对人开始这样说:「对你所感觉到的情形,我一点也不会责怪你,如果我是你的话,我也有同样的感觉。」
    就这样一句简单的话,世界上最狡猾,最固执的人,也会软化下来。可是你必需极是真诚的说出那些话来,假如你是对方的话,你当然有他同样的感觉。
  • 你明天遇到的人,其中可能有四分之三都饥渴似的需要同情….!如果你同情他们,他们就会喜欢你。
  • 当你接到这样一封信的时候,第一件事,就是如何用严正的措辞,去对付一个不礼貌而鲁莽的人,接着,或许你就动笔写信了。
    可是,如果你是一个聪明的人,你会把这封信放进抽屉里锁起来,经过两天后,再把这封信拿出来……像这类的信,迟上几天寄出,也不会受到什么影响。但当你两天后再拿出这封信来看时,你就不会投入邮箱,那就是我所采取的途径。
  • 盖慈博士在他那一部著名的「教育心理学」书上,这样写着:一人类普遍的追求同情,孩子们会急切的显示他受伤的地方。有的甚至于故意自己割伤、弄伤,以博得大人们的同情。」
    成人们也有类似的情形,他们会到处向人显示他的损伤,说出他们的意外事故,所患的疾病,特别是开刀手术后的经过。「自怜! 实际上是一般人的习性。」

第十章 人人都喜欢的吸引力

  • 事实确实是如此,凡你所见到的人–甚至你照镜子时所看到的那个人- 都会把自己看得很高尚,他对自己的估计,都希望是良好而不自私的。
    银行家摩根,在他一篇分析的文稿中说:人会做一件事,都有两种理由存在……一种是好听的,一种是真实的。
  • 要改变一个人的意志,需要激发他高尚的动机

第十一章 实行、推进,别停顿下来

  • 现在是表演的时代,只是叙述其中的原理,还不能有具体的效果。这种原理需要生动、活泼,需要使它更有趣、更戏剧化,所以必需用有效的「表演术」。
  • 使你的意念戏剧化。

第十二章 当你无计可施时,不妨试试这个

  • 让司华伯用他自己的话来解释:「如果我们想要完成一件事,必须鼓励竞争,那并不是说争着去赚钱,而是要有一种胜过别人的欲望。」
    争胜的欲望加上挑战的心理,对一个有血气的人来说,是一种最有效的激励。
  • 激将法
    • 党魁伯位德用了激将法,他转身向罗斯福大声的说:「难道圣巨恩山的英雄,竟是这样一个弱者?」
    • 司密斯见他犹疑不决的样子,微笑说:「年轻人,我不会怪你感到害怕……是的,那边确实不是一个太平的地方,那是需要一个有、大人物。才干的人,才能有这份魄力去做的。」
  • 只有竞争,才能发挥他们的工作效能。
  • 争强的欲望,自重感的欲望。
● 提要
得人同意于你的十二种方法
第一项规则:在辩论中,获得最大利益的唯一方法,就是避免辩论。
第二项规则:尊重别人的意见,永远别指摘对方是错的。
第三项规则:如果你错了,迅速、郑重的承认下来。
第四项规则:以友善的方法开始。
第五项规则:使对方很快的回答「是!是!」。
第六项规则:尽量让对方,有多说话的机会。
第七顼规则:使对方以为这是他的意念。
第八项规则:要真诚的以他人的观点去看事情。
第九项规则:同情对方的意念和欲望。
第十项规则:激发更高尚的动机。
第十一项规则:使你的意念戏剧化。
第十二项规则:提出一个挑战。

第四篇 使人同意你的九种方法

第一章如果你必须批评,这是开始的方法

  • 当我们听到别人对我们的称赞后,如果再听到其它不愉快的话,就比较容易接受了。
  • 不使对方难堪、反感,而改变一个人的意志
  • 用称赞和真诚的欣赏作开始。

第二章 如何批评才不致招怨

  • 我们要劝阻一件事,永远躲开正面的批评这是必需要记住的。如果有这个必要的话,我们不妨旁敲侧击的去暗示对方。对人正面的批评,那会毁损了他的自重,剥夺了他的自尊。如果你旁敲侧击,对方知道你用心良善,他不但接受,而且还会感激你。
  • 间接的指出人们的过错。

第三章 先说出你自己的错误

  • 如果批评的人,开始先谦冲的承认自己也不是十全十美的、无可指责的,然后再指出人们的错误,这样就比较容易让人接受了。
  • 在批评对方之前,不妨先谈谈你自己的错误。

第四章 没有人喜欢接受命令

  • 你不妨可以考虑一下。」或者是「你认为那个有效吗?」
  • 运用那种方法,他保持了对方的自尊,而且使那人有了自重感。那种方法,也很容易取得对方的真诚合作,而对方不会有任何的反抗,或是拒绝。
  • 发问时,别用直接的命令。

第五章 让对方保持他的面子

第六章 如何鼓励人们成功

  • 即使只有稍微的进步,我们也要称赞,这样可以鼓励别人继续进步。
  • 我们具有各种潜在的能力,可是却惯于不会利用。这潜在的能力,其中一项,就是称赞别人、激励别人,让他们知道自己这股潜在的能力,所蕴藏的神奇效力。

第七章 给狗取个好名字

  • 一般人,都会愿意接受指导,如果你得到他的敬重,并且对他的某种能力表示敬重的话。」
    我们也可以这样说,如果你想改善一个人某方面的缺点,你要表示出,他已经具有这方面的优点了。
  • 莎士比亚说:「如果你没有某种美德,就假定你有。」是好是「假定」对方有你所要激发的美德,给他一个美好的名誉去表现,他会尽其所能,也不愿意使你感到失望的。
  • 几乎包括了富人、穷人、乞丐、盗贼,每一个人都愿意竭尽其所能,保持别人赠予他的「诚实」的美誉。
  • 给人一个美名让他去保全。

第八章 使错误看起来容易改正

  • 告诉一个孩子、一个丈夫,或是一个员工,他在某一件事上愚蠢至极,没有一点的天伦,他所做的完全不对。那你就破坏了他想要进取、上进的心情。可是,如果运用一种相反的技巧,多给人们一些鼓励,把事情看成很容易。使对方知道,你对他有信心,他有尚未发展出的才干,那他就会付出最大的努力,争取到这个胜利。
  • 用鼓励,使你要改正的错误,看来很容易做到;使你要对方所做的事,好象很容易做到。

第九章 使人们乐意做你所要的事

  • 人与人之间关系中,一项重要的规则,那是:「永远使人们乐意去做你所建议的事。」
  • 可是就有这样一件事,发生在拿破仑身上。当他训练荣誉军时,发出一千五百枚十宇徽章给他的士兵,封他的十八位将军为「法国大将」,称他的军队为「伟大的军队」的时候,人们也说他「孩子气」,讥笑他拿玩具给那些出生入死的老军人。拿破仑回答说:「是的,有时人就是受玩具所统治。」
    这种以名衔、或权威赠予的方法,对拿破仑有效,对你同样有效。
● 提要
改变人而不触犯或引起反感的九种方法
第一项规则:用称赞和真诚的欣赏作开始。
第二项规则:间接的指出人们的错误。
第三项规则:在批评对方之前,不妨先谈谈你自己的过错。
第四项规则:发问时,别用直接的命令。
第五项规则:顾全对方的面子。
第六项规则:称赞最细微的进步,而且称赞每一个进步。
第七项规则:给人们一个美名让他去保全。
第八项规则:用鼓励,使你要改正的错误,看来很易做到;使你要对方所做的事,好象很易做到。
第九项规则:使人们乐意去做你所建议的事。

第五篇 创造奇迹的信件

  • 这封信里的语气、含意,使人很愿意为发信人做一点事情,并且使对方有一种自重、高贵的感觉。因为请对方帮忙,使对方有了自尊、自重的感觉。
  • 巧妙的运用这种「帮我一个忙」的心理学。
  • 我们需要尽量鼓起对方的自尊心,但不是运用谄媚,或是虚伪,如果引误了这个出发点,是绝不会有效果的。
    必需记住:我们每一个人,都是希望如何被人欣赏、如何被人重视……甚至会不顾一切的去达到这个目的。可是,没有人会接受不诚恳的、虚伪的奉承。
    我愿意再说一遍:这书中所告诉你的原则,必需出自由衷才会有效果出现。

如何预估开发时间

发表于 2020-07-19
  1. 大的需求应预留时间方案设计和评审
  2. 方案时间( 包括跟相关依赖方确认方案时间)
    • 确定依赖方工作量和时间点
    • 工作项拆分
  3. 需求细节确认预留
  4. 开发时间
  5. 联调时间
  6. 配合测试时间(改bug)
  7. 单元测试
  8. 产品验收(测试环境)
  9. 需求改动预留
  10. 代码审核时间
  11. 处理其他突发事情预留
  12. 上线跟进
  13. 记录延期原因(需求变更,需求优先级调整,方案改动等;并同步相关人)
  14. 数据需求(可能影响方案实现细节)

参考场景

  1. 需求方需要一个相对准确的时间点;
  2. 给自己一个合理靠谱,相对科学的心理预估,避免坑人坑自己;
  3. 紧急情况特事特办。。。
<1…121314…16>

160 日志
176 标签
RSS
© 2025 Kingson Wu
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.4