问题汇总

负责某公司技术以来,遇到了一些问题,汇总一下:

  1. 接口设计问题,错误的接口设计将导致难以避免的问题
  2. DNS劫持问题,用户网络问题定位困难
  3. 苹果IAP漏单问题
  4. 缓存时间、状态不一致、压力太大、崩溃重启、启动慢问题
  5. NoSQL选型问题
  6. 数据库负载问题,主从同步问题
  7. 日志监控问题
  8. 服务自动扩容,全球部署问题
  9. 垃圾信息、僵尸账号问题
  10. IM丢消息,收不到消息问题。
  11. IM、群聊问题定位、测试困难
  12. 聊天信息存储问题

笔墨之殇

说点什么好呢?这两天我开始,翻阅以前我读过的书,我发现,有很多的书,只是草草看过,还有一些书,根本没有看过。原来自己有做读书笔记的习惯,可是当我把阅读的时间放到地铁上之后,这个习惯,也随之消失了。以至于我根本不知道这本书,有没有读过。纸质书,可以有记录笔记的空间,而电子书,阅读起来比较方便,我想这就是纸质书和电子书的区别吧!

以前我总想写点文字。可是我发现自己,写作的速度越来越慢了,也找不到合适的输入法。拼音输入法,当你想打一些,书面语,或者是文言文的时候,就很难输入。而,五笔输入法或者其他的字型输入法,都有一个问题,就是,学起来太麻烦了,我根本记不住那些字码表,而且,当我,去回忆那些字码的时候,我的思路已经被打断了。

我还是喜欢拿着笔在纸上写字的感觉。在这种状态下,我的思路是最流畅的。

一直以来,我都想写一两本小说,可是构思了很久,却迟迟没有动笔。自己内心真正想表达的东西,和整个故事的结构,往往存在冲突。我不愿意写一些,没有人想看的东西,但我也不想,完全是为了迎合别人的口味,而写作。

其实,这并不是什么文章,我这是在测试一种新的输入法,一种,新的写作方式,那就是,直接把我想写的,念出来。你所看到的一切,都是我通过语音输入的。好吧,今天就说到这里,我的脚也泡好了。

如何学习编程

编程入门

大部分人都是通过某一个原因,喜欢上了编程。同样,你也需要一个理由。也许只是走在路上,忽然有人对你说:“年轻人,我看你天赋异禀,骨骼惊奇,我这里有一套编程秘笈,你想不想学啊”

入门编程语言,有很多选择,你可以选择python、JS,也可以选择C。比如我自己,是通过Basic语言入门的,也是因为它喜欢上了编程。

在这一阶段,最容易出现的问题是:Compiler Error,Syntax Error。你还不习惯和计算机进行沟通,你们之间的语言不够顺畅。它听不懂你说什么,当它说Error,你也听不懂它在说什么。你总是很抓狂的问,What’s the Error,一定是计算机出了什么问题,而不是我的代码有任何问题。直到你意识到,计算机没有任何问题,有问题的一定是我的代码,你能够检查你的代码,修复语法错误,恭喜你,你已经入门了。

这一阶段,你对编程有了感性的认识。你为自己写出来的东西感到骄傲,完全不会注意到其实那些代码其实只是piece of shit。你也会遇到很多的问题,即使你已经查阅到了所需要的知识点,还是无法实现你要的功能。就好像已经把所需要的材料全部交给了你,你却无法用这些材料造出你想造的东西。

这一段时间,你的灵感泉涌,有很多的想法想要去做,但却又感觉力不从心。你需要开始补充一些基础知识了,难度也要开始增加。

计算机科学基础

这是一个非常重要的阶段,这一阶段的学习效果,直接决定了你的技术实力。有些知识,并不会立刻用得上,但是,这些知识,已经潜移默化的影响了你的思维方式。你的任督二脉将在这一阶段打开。

算法

算法和数据结构 这是一切程序的基础,你需要恰当的使用这些数据结构,你无法绕开它们。有一些算法,你需要知道它们的原理,这有助于你理解你的代码最终在计算机上是如何运行的。你可能并不需要掌握算法设计的机巧,也不需要去参加一个算法比赛。但你需要理解这些经典算法,记住它们的名字,在你遇到问题时,第一时间想到它们。最终,你可能不需要自己去实现它们,但你需要恰当的使用现有的算法代码。

设计模式

函数式编程、面向对象编程,设计模式。这些方面的知识,你也需要掌握,你需要了解如何将自己的代码组织在一起。这就像你拥有了一些积木,你需要了解玩积木的常用技巧。阅读一些书籍或者阅读他人的代码,都是非常好的途径。学习这些知识,就像是学习作画。这些技巧你一看就会明白,但却不能熟练的使用。这里是考验你艺术天分的地方。

在拥有了以上这些技能后,你已经可以算是一个不错的程序员了。但这些知识可以让你写出很棒的代码,却无法使你的程序有任何的功能。你必须要让你的程序和外界进行交互,它才有存在的价值。

运行环境

你的程序如何和外界进行交互?你的程序是运行在一个封闭的环境之中的。想象一下,一只猴子被关进了一个房间中,房间中有一个操作面板,当它按下某个按钮,外界就会发生某件事情,比如说在你的电脑上打开一个新网页。你的程序就是这只猴子,你必须熟悉你的操作面板,有些时候面对一些奇怪的面板故障,你甚至需要了解它的工作原理,以避免发生那些故障。

网络基础, TCP/IP 协议,HTTP协议,如果你要开发网络应用,这些都是非常重要的基础知识。

操作系统原理,无论你开发桌面应用、移动应用、嵌入式应用、网络应用、服务器端应用,你都应该对你的程序所运行的环境有足够了解。

如果你开发的是Web应用,也许你不需要了解操作系统,但你需要了解你的浏览器,它是你的运行环境。

计算机架构,这个你可以不必知道。但如果你要开发一个操作系统,那么你必须对计算机架构有所了解,还是那句话,你需要了解你的程序所运行的环境。而操作系统所运行的环境就是计算机硬件的体系架构。

交流

你需要一个目标,你定下的这个目标可能就是下一个facebook。带着目标学习,这是我所推崇的方式。对于还处于学习阶段的你来说,这是一段幸福的时光。你不必为了生计而学习,你可以纯粹的为了爱好而学习。

你需要加入开发者交流的社区,加入论坛、QQ群、讨论组、邮件列表。与别人分享你的收获与挫折,社区的氛围也是你继续学习的动力之一。当你遇到难题,可以在社区里提问。但是你应该学习一些提问的智慧,不要做伸手党,这对你的学习不会有任何帮助。你应该至少已经阅读了相关的书籍、资料,并借助搜索引擎(不要使用baidu,中国可以用bing)来寻求答案。记住一点:社区不能给你想要的东西,但社区可以解答你的疑惑。社区是用来交流的,你也可以通过回答别人的问题来提高自己的知识。

开源社区,也是你获取知识技能的主要来源之一。当你需要某个功能,有人可能已经实现了他,并将他开源在了github(目前最大的开源社区)之类的地方。这些开源项目可以帮助你解决某些细节问题,使你可以更专注在你的主要目标上。对于优秀的开源项目,你可以阅读他们的代码,学习他们的机巧。

再论运行环境

如果你仔细体会的话,你会发现,编写代码只占到你学习编程中的很少的一部分时间,而大部分时间,你是在查阅资料。你需要花大量的时间在学习程序的运行环境上,而不是学习编程语言上。运行环境会提供给你很多的编程接口,一般被称之为API。

我这里所说的运行环境,并不是仅仅指操作系统运行环境,它也可以是浏览器,Java运行环境,Sevlet容器,node.js,unity3D运行环境,flash运行环境,directX,OpenGL,cocos2d游戏开发框架。

你可能注意到了一点,我将开发框架,视作了一种运行环境。为什么这么说呢?因为框架是对运行环境的再次封装,在框架之上,你将看到更加易用,更加人性化的接口。有一些框架,还额外提供了很多辅助的库,甚至插件机制,让你可以直接使用整个社区贡献的插件。你只需要面对框架编程,借来几个插件,再搭配几个辅助库,就可以完成一个作品。

你明白了吗?编程就是这么简单!这也是为什么有那么多平庸的程序员的主要原因————他们只懂得在框架之上编程,使用别人写好的现成的代码。可是一旦他所赖以生存的框架或插件或库,出现了任何问题,他们的平庸就会显现

如果你是初次接触编程,还不知道什么是开发框架(framework)什么是库(library)的话,没关系,你只需要记住一点:Library决定了你能做什么,framework决定了你不能做什么。如果有一个新的框架,让你眼前一亮,蠢蠢欲动,请保持冷静,先想一想,如果你用了这个框架,你将失去哪些能力,是否是可以接受的?我看过太多的项目因为框架的限制,而不得不使用一些旁门左道来突破框架的限制,从而失去了代码的美感。抑或是自己动手,将框架改的面目全非,完全失去了框架的意义。

对于初学者,我强烈建议远离框架。框架是一种捷径,但对于一个以学习阶段的人来说,捷径是并不是什么好事。如果你已经有了足够的经验,对你的运行环境足够了解了之后,你应该在你的运行环境之上,寻找一个优秀的框架,学习它的设计思想。更进一步的,你可以搭建一个你自己的框架。我并不反对使用框架,但我反对不求甚解的使用框架。

修炼是一个长期的过程,即使你已经成为了一名优秀的程序员,你依然需要不断的修炼。记住一点:修炼的捷径就是不走捷径

Hack

你可能想要做一些看起来不可能的事情,这通常是从某个夸张的想法而引起的。Hook、反射,这些略有些高级的技巧。

软件工程

你已经找到了你的第一份工作,你加入了一个团队,经过一段时间,你又被提升为了项目组长。你需要开始考虑一些团队管理问题、系统架构问题

专业方向

游戏开发书籍

设计

(2015) Prototyping(21st Century Skills Innovation Library: Makers as Innovators)
(2015) Spelunky (Boss Fight Books #11)
(1988) The Design of Everyday Things
(2008) The Art of Game Design: A Book of Lenses

数学

(2001) Mathematics for 3D Game Programming and Computer Graphics
(2002) 3D Math Primer for Graphics and Game Development

图形学

Computer Graphics: Principles and Practice
(1999) Real-Time Rendering
Physically Based Rendering: From Theory to Implementation

语言

Modern C++ Design: Generic Programming and Design Patterns Applied
More Effective C++
(1999) C++ Standard Library: A Tutorial and Reference

引擎

(2009) Game Engine Architecture
(2011) Game Programming Patterns
(2003) Game Coding Complete
Game Physics Engine Development: How to Build a Robust Commercial-Grade Physics Engine for Your Game

算法

(1st 2004) Real-Time Collision Detection (The Morgan Kaufmann Series in Interactive 3d Technology)
Game Programming Algorithms and Techniques: A Platform-Agnostic Approach

AI

Programming Game AI by Example
Artificial Intelligence for Games

MMO

(2015) Multiplayer Game Programming: Architecting Networked Games (Game Design)

Unity (不推荐)

Unity in Action

Too many open files 的解决办法

在开发TCP网络应用的过程中,我们经常会遇到“Too many open files”这个问题。这说明你的程序以达到Linux所允许的打开文件数上限。你需要按照以下方式来提升:

每用户上限:

打开 /etc/security/limits.conf
在末尾添加:

1
2
3
4
* hard nofile 500000
* soft nofile 500000
root hard nofile 500000
root soft nofile 500000

修改后,你需要logout并重新login。

pam-limits

据说对于Daemon进程需要额外的步骤,但目前我并不需要。如果以上改动不能对你有所帮助,可能需要以下步骤。

打开 /etc/pam.d/common-session

添加以下内容:

1
session required pam_limits.so

系统级限制

这项设置应该大于没用户限制。

打开 /etc/sysctl.conf

添加以下内容:

1
fs.file-max = 2097152

运行:

1
sysctl -p

这会增加系统级的最大打开文件数。

验证效果

使用以下命令验证系统级最大打开文件数

1
cat /proc/sys/fs/file-max

Hard Limit

1
ulimit -Hn

Soft Limit

1
ulimit -Sn

检测用户限制

www-data替换为你希望检测的用户。

1
su - www-data -c 'ulimit -aHS' -s '/bin/bash'

检测运行中的进程限制

XXX替换为PID

1
cat /proc/XXX/limits

今日在一台新启动的服务器上,系统级、用户级配置都正常,唯独进程的limits仅为默认1024。进程使用的是supervisor守护启动,使用supervisor restart进程后,limits依然为1024,后重启了supervisor服务,limits恢复所设定数值。

开源静态网站生成工具

有博客订阅者反馈我的博客ATOM输出有问题,总有两篇已unpublish的博客出来诈尸。这个是个老问题,当时也是因为总是有这两篇博客捣乱所以unpublish了,但完全无效。

自己的博客一直没有认真维护,只是偶尔随手记录,更没有想到有人订阅了,闻之顿感责任重大。计划认真整理一下自己的博客。

那两篇诈尸的博客,或是github的bug,或是jekyll的bug,未能验证。细思之,将博客系统完全交予github管理,的确不够合理,于是考虑使用本地生成静态文件再行push的方式,代替先push再由github jekyll生成静态文件的方式。顺便也更新一下自己博客的样式。

关于jekyll,也有不少问题,比如不能生存tag page等,也考虑更换一下生成器。奈何目前的静态网站生成器着实太多,无从选择。幸有有心人整理了一个列表,staticgen.com,包含了github的关注数、项目使用的语言,模版语言等信息,选择方便了许多。

计算机科学经典书籍

在我学习编程的过程中,看过很多的书籍,大部分的书籍只能提供很有限的知识,有的甚至不能提供真正的“知识,充其量只是某个软件产品的使用手册而已,而且这类手册极易过时。现在,因为工作的需要,我依然会偶尔阅读这类“手册”。但我渐渐体会到了有些计算机知识是永恒的,如果从一开始我所阅读的,都是这些永恒的知识,而不是那些短暂的技能,我的知识体系会比现在更加的完整。

所以,我整理了这个列表。我希望他能涵盖目前已知的计算机科学体系,并且尽可能的在每个领域都提供一两本经典书籍。我会优先选取发布时间较早的书籍,因为那代表着它经得起时间的考验,同时我会参考Amazon和豆瓣的评分,以及维基百科等网站的引用和评价。我希望所提供的这个列表是“相对权威”的列表。

我会尽可能的包含中文译名和英文原版书名。

我会尽可能按照权威的学科分类对书籍进行划分,如果在分类上有错误,希望各位指出。

我也希望能够对学科间的依赖关系明确描述,默认是无依赖,当我发现了某个学科需要依赖于一些前置知识的时候,我会注明。如有遗漏,希望指出。

在列表中,也会包含部分非“计算机科学”方面的书籍,比如游戏开发,互联网相关的书籍。这些书籍入选的条件时,他是适合程序员阅读的,并且同样符合经典、权威的要求的。

科普

  • 1985 计算机科学概论 Computer Science: An Overview
  • 1999 编码 Code

计算历史

  • The Computer from Pascal to von Neumann
  • A History of Computing in the Twentieth Century

Mathematics 数学

  • 300 BC 几何原本 Elements
  • 1687 自然哲学的数学原理 Philosophiae Naturalis Principia Mathematica
  • 1965 微积分和数学分析引论 Introduction to Calculus and Analysis (Richard Courant / Fritz John)
  • 1976 线性代数及其应用(侯自新 译)Linear Algebra and Its Applications (Gilbert Strang)
  • 1988 具体数学 Concrete Mathematics
  • 1995 线性代数应该这样学 Linear Algebra Done Right
  • (当下流行) 托马斯微积分 Thomas calculus
  • (当下流行) 初等概率论

Computability 计算理论

  • Alan Turing (1937) “On computable numbers, with an application to the Entscheidungsproblem”
  • (1979) 自动机理论、语言和计算导论 Introduction to Automata Theory, Languages, and Computation

本书建议看原版

  • 1996 计算理论导论 Introduction to the Theory of Computation

Information theory 信息论

  • Shannon, C.E. (1948) “A mathematical theory of communication”
  • Hamming, Richard (1950) “Error detecting and error correcting codes”
  • Huffman, D. (1952). “A Method for the Construction of Minimum-Redundancy Codes”
  • Ziv, J.; Lempel, A. (1977). “A universal algorithm for sequential data compression”
  • 1991 Elements of Information Theory

Computer Architecture 计算机架构

  • 1990 Computer Architecture: A Quantitative Approach

Operating System 操作系统

  • 1974 操作系统设计与实现 Operating Systems Design and Implementation
  • 1992 UNIX环境高级编程 Advanced Programming in the UNIX Environment
  • 1992 现代操作系统 Modern Operating Systems
  • 2002 深入理解计算机系统 Computer Systems:A Programmer’s Perspective

Compilers 编译原理

  • 1986 Compilers: Principles, Techniques and Tools

在封面变成一条龙后,被称为 dragon book.

img

Programming Languages

  • 1978 C程序设计语言 The C programming Language

Programming ?? (not science)

  • 1984 计算机程序的构造和解释 Structure and Interpretation of Computer Programs
  • 1986 编程珠玑 Programming pearls
  • 1993 代码大全 Code Complete

Algorithms 算法

  • 1968 The Art of Computer Programming
  • 1974 The Design and Analysis of Computer Algorithms
  • 1983 Data Structures and Algorithms
  • 1983 Algorithms
  • 1990 Introduction to Algorithms
  • 1996 Data Structures and Algorithm Analysis in C

Computational complexity theory 计算复杂度理论

  • 1979 Computers and Intractability: A Guide to the Theory of NP-Completeness
  • 1994 Computational Complexity

Networking 网络

  • TCP/IP详解 卷1:协议
  • UNIX网络编程

Database 数据库

  • 1980 Principles of Database & Knowledge-Base Systems, Vol. 1: Classical Database Systems
  • 1987 Database System Concepts
  • 2001 数据库系统全书 Database Systems: The Complete Book

Software engineering 软件工程

  • 1975 人月神话 The Mythical Man-Month: Essays on Software Engineering
  • 1994 设计模式 Design Patterns: Elements of Reusable Object-Oriented Software
  • 1999 程序员修炼之道 The Pragmatic Programmer: From Journeyman to Master

面向对象程序设计的经典。但当你使用动态语言时,会发现部分模式是不必要的

  • 2004 软件随想录 Joe on software
  • 重构:既有代码的改善 Refactoring: Improving the Design of Existing Code

Artificial Intelligence

  • 1994 人工智能:一种现代方法 Artificial Intelligence: A modern approach

膜计算 Membrane Computing ???

  • 2002 膜计算导论 Membrane Computing - An Introduction

参考:
ACM: 经典出版物
维基百科:计算机科学重要出版物
维基百科:理论计算机科学重要出版物
Goodreads: 必备计算机科学书籍列表
Goodreads: 游戏开发
维基百科:数学著作列表

Kingshard阅读笔记

KingShard 是 mysql 代理,可实现分库分表等功能。但因业务复杂,无法使用,故阅读其源码,以便修改。

代码版本:
2016-09-12
3c4a1db63226cb1384047a3f915d10e0594228d1

入口: cmd/

服务启动: proxy/server/server.go

Server.Run()
服务逻辑

Server.onConn(net.Conn)
客户端连接逻辑

  • Server.newClientConn(net.Conn)
    客户端连接初始化

客户端连接:proxy/server/conn.go

ClientConn.IsAllowConnect()
判断客户端IP是否合法

ClientConn.Handshake()
握手

ClientConn.Run()
客户端逻辑

ClientConn.readPacket()
PacketIO.ReadPacket()
拆包逻辑

ClientConn.dispatch(data)
包分发逻辑
data[0] mysql命令

  • QUIT c.handleRollback() c.Close()
  • QUERY c.handleQuery(string(data))
  • PING
  • INIT_DB c.handleUseDB 分配后端节点 backend.Node
  • FIELD_LIST
  • STMT_PREPARE
  • STMT_EXECUTE
  • STMT_CLOSE
  • STMT_SEND_LONG_DATA
  • STMT_RESET
  • SET_OPTION
    其它命令不支持,log

命令执行成功后,写结果给客户端,某些命令只需 ClientConn.writeOK

执行查询 ClientConn.handleQuery
ClientConn.preHanleShard 不确定什么时候会用
解析sql
handleSelect
handleExec
handleBegin
handleCommit
handleRollback

后端节点: backend/node.go backend.Node
GetSlaveConn
GetMasterConn

后端连接:
基类 backend/backend_conn.go backend.Conn
子类 backend/db.go backend.BackendConn

写入命令,读取返回
writeCommandStr
readOK

SQL 语法解析
sqlparser
需要执行 make,通过yacc编译

其它
Counter 计数器

雇主与雇员的关系

通常,我们认为雇主与雇员之间的关系是一种管理者和被管理者的关系,但在作者看来,雇主与雇员之间的关系并非如此,在很多时候雇员往往拥有更多的主动权。

在法制社会中,当我们成立一家公司时,股东之间通过契约联系在了一起,向同一个目标共同努力,同时实现股东个体的成功。可以说,契约精神是公司赖以存在的基础。

在公司与员工的关系上,契约精神同样是重要的基础。在公司与员工形成雇佣关系,这种契约关系就建立了。

在一个人成为管理者之前,应该对这一事实有充分的认识。你与下属是平等的,你只有一种权利那就是聘用和解聘的权利。如果公司没有赋予管理者这种权利,本质上,管理者只是个为员工提供服务的人员。员工会向你索取各种资源配合他们的工作,而你提供资源的过程和服务人员递上餐具和食物的过程并没有太大区别。

人事部门应该按市场规则与员工进行互动,本质上就和买菜时侃价行为类似。是一种交易行为。如果你要对其进行职位和薪资的调整,本质上是一种内部重新聘用的过程,即使是升职加薪,也需要征得员工的同意,然后才可执行。如果要进行合理的避税,这些事项必须在签订契约(也就是聘用)之前达成共识。对于辞退员工,各种处理方法亦必须要按照契约精神进行,无论是劝退或是辞退,本质上就是一种公司违约行为,理应给予赔偿。对于一些曾经有过突出贡献的员工,在辞退时不仅要给予法律内规定的赔偿,甚至要给予更多的“补偿”。这种补偿本质上也是基于一条根本契约:员工向公司提供劳动,公司为这种劳动支付报酬。违反这种契约,或许不会受到法律的惩罚,但会使某一方丧失在市场上的信用,无论是公司方还是员工方。

No Blame Culture,它的基础在于,人和人之间是平等。人们通过不同的分工在一起协作,人们不应因理念、方法的差别而受到羞辱或讽刺。