讲稿整理-陆奇老师的《正视挑战,把握创业创新机会》(非官方)

更新:本文最早发布在知乎(https://zhuanlan.zhihu.com/p/149776960

看了陆奇老师的奇迹创业坛直播分享(B站有),发现里面非常多值得深挖的点,做了下文字记录(如果有侵犯版权,请告知删除)。

即使不是在创业一线,对于做人做事来说,都是非常值得多次阅读思考的材料。

PS:陆奇老师在做的事情。关于奇绩创坛​www.miracleplus.com

PPS: B站完整视频。https://www.bilibili.com/video/BV1jK4y147kH​www.bilibili.com

正视挑战,把握创业创新机会

挑战与机会

今天很高兴能欢迎大家参加我们积极创谈的直播直播室。我今天给大家分享的主题是正视挑战,把握创业创新的机会。我为什么会选择这样一个主题跟大家分享?本质上是因为世界正处在一个巨大的变化当中,我们有百年未遇,对全球的新冠疫情,在全球范围内造成了大规模的对人民的生命健康和经济生活的影响。

同时新冠疫情造成的未来的新的世界格局,将对全球有结构性的非常大的影响。因此世界经济政治的格局也在加速的变化。

各行各业都面临着非常大的挑战和非常大的不确定性。但纵观历史,这样的小黑天鹅事件,小概率但是影响非常之大,往往会因此让世界进入一个新的环境,打造一个全新的世界,更美好的世界,这也是一个机会。为这个机会来开路的,一定是创新,尤其是技术驱动创新,特别是今天年轻一代的创业者,你们觉得未来社会要如何生活如何工作等等,将决定性的因素,因为创业创新是驱动创新的主要源泉和摇篮,但创业者本身要经过一个非常艰辛的历程,充满着很多不确定性。

面对今天这样的一个新格局,又有了众多的问题,焦虑和迷茫。未来到底何去何从?创业者应该如何来正视挑战,把握住机会。今天我来分享的是我们在奇迹创坛是怎样看待分享我们的想法和观念,积极状态。

我们致力于早期的创业生态,我们通过创新的方法和创业者一起动手解决他们的核心问题,努力当好创业者的合伙创始人。我们一起跟创业者合作,主要是帮助创业者提高两个核心能力,想的更明白,做得更有效。而这正是要正视挑战,抓住机会的核心需要做的工作,需要正视挑战,我们必须从奇迹创坛角度来讲,我们必须对整个创新生态的全局有一个系统化的完整的梳理,把大盘全面的看清楚,同时对新格局所带来的风险要有充分的分析,这些风险的范围,非确定性的时间的区间,帮助每个创业者做好充分的准备。

继续阅读

如何面对失败

那些杀不死我的,必将使我更加强大。

作者马修.萨伊德在他的这本《黑框子思维》里面,就讲到了人类社会中,小到个人,大致跨国机构、国家等,是如何在失败的泥沼中挣扎,又是如何端正对错误的认识,乃至走向更好的未来。

对待失败的态度

很多时候,失败往往意味着责罚、屈辱、缺乏能力等等,这使得人们总是对失败避而远之。书中列举了医疗业、航空业的大量案例,分析大型机构的内部人员也会因为体制固有的安全盲点,或者因为责任规避的各种原因,而对失败采取回避,丢弃,甚至否认的态度。这样的结果,是导致了大量的安全事故,而且一直发生。

即便是在错误反馈机制相对完善的情况下,一些初级的错误导致的事故仍然无法避免,体制无法完全解决问题,还需要搭配人的意愿。而意愿的改变,还是需要修正人们对错误的认识。

人们必须意识到,错误并不是什么洪水猛兽,而是一个更好的学习机会,让前进变得可能的一个助推。

总的来说,要想从错误中学习,有两个关键部分:第一,要有一个正确的机制,在这个机制中,改进错误被视为推动进步的方法;第二,要有能让这种机制蓬勃发展的正确观念。

继续阅读

申请E-residency过程中的趣事

为什么申请?

最早知道这个概念应该是从 Natalia MokNa这篇文章开始的,因为很早就有在关注数字游民啊、加密货币之类的东西,所以知道说爱沙尼亚也出了款类似的电子公民玩意,也想着跑过去试试申请一张玩玩。

有什么用呢?

本质上,很多人除了玩的成分,主要也是看中他们家的电子公司概念,可以直接用这个身份申请受欧洲认可的公司,并且走他们的支付系统。

盗一张官网的图过来。

简单来说,这张E-residency可以做如下事情:

  • Establish a company online
  • Manage the location-independent company fully online
  • Apply for EU business banking and payment card, conduct secure e-banking
  • Access international payment service providers
  • Digitally sign and transmit documents
  • Declare Estonia taxes online
继续阅读

the-thought-of-yii2-rbac

YII2 的 rbac 思路

最近在做一个基于 yii2 的项目,需要用到权限控制的功能,于是考察了 yii2 原生的权限解决方案。

一般来说,权限系统有简单做,也有复杂做。我在做的时候,主要有 3 个点考虑:资源、用户、关系。资源有粒度的概念,比如某种资源、特定资源、部分资源等。用户也有粒度的概念,单个用户、角色、用户组等。而关系,就是描述用户与资源之间,用户是否能够执行某个动作,典型如增删改查。

总体来看,yii2 的原生解决方案实现得比较简单,不过思路比较轻巧。

特性

因为我考察的是基于数据库的解决方案,所以下面主要围绕这个实现来说。这个权限控制的特点:

  • 基于角色模型,role base access control
  • 支持角色(Role)、权限(Permission)、规则(Rule)三种控制层次
  • 角色可以继承
  • 一个用户可以拥有多个角色
  • 不支持直接赋予权限给用户,即用户只能有角色,不能直接拥有某个权限
  • 规则只能添加到权限上

API 使用

// 获取yii的权限管理对象
$auth = Yii::$app->authManager;
// 添加 "createPost" 权限
$createPost = $auth->createPermission('createPost');
$createPost->description = 'Create a post';
$auth->add($createPost);
// 添加 "updatePost" 权限
$updatePost = $auth->createPermission('updatePost');
$updatePost->description = 'Update post';
$auth->add($updatePost);
// 添加"author"角色,并赋予"createPost"权限
$author = $auth->createRole('author');
$auth->add($author);
$auth->addChild($author, $createPost);
// 添加"admin"角色,并赋予"updatePost"权限
// 同时让"author"角色继承"admin"
$admin = $auth->createRole('admin');
$auth->add($admin);
$auth->addChild($admin, $updatePost);
$auth->addChild($admin, $author);
// 把特定的角色赋给用户
$auth->assign($author, 2);
$auth->assign($admin, 1);

在这里,我们完成了权限的初始化。目前系统的权限是下面这样的(yii2 官网直接拿过来):

那程序在校验的时候,流程具体是怎么样的呢?

先看下 api:

if (\Yii::$app->user->can('updatePost', ['post' => $post])) {
    // update post
}

在这里,假设用户想操作一个 post,我们直接调用 user 类的 can 方法,然后去查表。我们这里先讲流程。大致的思路是。查找用户所有的角色,然后把这个角色下面的权限找出来,做一个并集,然后再问这个权限有没在用户的权限集里面。

数据结构

基于上述的考虑,数据库实现的权限控制方案,采用了下面 4 张表:

  • rule 表
    Rule 表对应” 规则”,主要用来存储规则信息。
  • auth_item 表
    这个表比较特殊,yii2 的实现是把 Role 和 Permission 两个信息也存在一起。
  • auth_item_child 表
    这个表用来存储父子关系,包括 Role 之间的继承关系,Role 和 Permission 之间的包含关系。
  • auth_assignment
    最后这张表,存储的是角色和用户之间的多对多关系了,一个用户可以拥有多个角色。

具体的 sql 语句:

create table `auth_rule`
(
   `name`                 varchar(64) not null,
   `data`                 blob,
   `created_at`           integer,
   `updated_at`           integer,
    primary key (`name`)
) engine InnoDB;
create table `auth_item`
(
   `name`                 varchar(64) not null,
   `type`                 smallint not null,
   `description`          text,
   `rule_name`            varchar(64),
   `data`                 blob,
   `created_at`           integer,
   `updated_at`           integer,
   primary key (`name`),
   foreign key (`rule_name`) references `auth_rule` (`name`) on delete set null on update cascade,
   key `type` (`type`)
) engine InnoDB;
create table `auth_item_child`
(
   `parent`               varchar(64) not null,
   `child`                varchar(64) not null,
   primary key (`parent`, `child`),
   foreign key (`parent`) references `auth_item` (`name`) on delete cascade on update cascade,
   foreign key (`child`) references `auth_item` (`name`) on delete cascade on update cascade
) engine InnoDB;
create table `auth_assignment`
(
   `item_name`            varchar(64) not null,
   `user_id`              varchar(64) not null,
   `created_at`           integer,
   primary key (`item_name`, `user_id`),
   foreign key (`item_name`) references `auth_item` (`name`) on delete cascade on update cascade
) engine InnoDB;

代码层面(算法实现)

相关的代码,在框架的路径下面,yii2/framework/rbac,具体的文件有如下几个,我们逐一来看看:

├── Assignment.php  // 对应auth_assignment表,描述用户与角色的关系
├── BaseManager.php  // 忽略
├── CheckAccessInterface.php // 权限校验接口
├── DbManager.php  // 基于数据库实现的权限校验类
├── Item.php  // Role和Permission的基类
├── ManagerInterface.php // 忽略
├── Permission.php // 权限类
├── PhpManager.php // 忽略
├── Role.php // 角色类
├── Rule.php // 规则类

整个代码的思路,比较简单,框架先提出了 3 个对象,分别是 Role,Permission,Rule,这映射到我们之前提到过的 RBAC 概念,分别对应角色、权限、规则。

主要的权限校验,其实是在 DbManager.php 实现,而关键的方法,就是下面这个。


  /**
   * Performs access check for the specified user.
   * This method is internally called by [[checkAccess()]].
   * @param string|int $user the user ID. This should can be either an integer or a string representing
   * the unique identifier of a user. See [[\yii\web\User::id]].
   * @param string $itemName the name of the operation that need access check
   * @param array $params name-value pairs that would be passed to rules associated
   * with the tasks and roles assigned to the user. A param with name 'user' is added to this array,
   * which holds the value of `$userId`.
   * @param Assignment[] $assignments the assignments to the specified user
   * @return bool whether the operations can be performed by the user.
   */
  protected function checkAccessRecursive($user, $itemName, $params, $assignments)
  {
// 参数分析:user是用户类,itemName是具体要查询的权限名(或者角色名),ssignments是用户的角色集
      // 获取这个itemName对应的数据,可能是role,也可能是permission
      if (($item = $this->getItem($itemName)) === null) {
          return false;
      }
      Yii::trace($item instanceof Role ? "Checking role: $itemName" : "Checking permission: $itemName", __METHOD__);
// 暂时先忽略对rule的考虑
      if (!$this->executeRule($user, $item, $params)) {
          return false;
      }
// 角色名是否在用户的assignment里面,或者在系统的默认角色列表里面
      if (isset($assignments[$itemName]) || in_array($itemName, $this->defaultRoles)) {
          return true;
      }
// 构造查询函数对象
      $query = new Query;
      $parents = $query->select(['parent'])
          ->from($this->itemChildTable)
          ->where(['child' => $itemName])
          ->column($this->db);
// 递归查询
      foreach ($parents as $parent) {
          if ($this->checkAccessRecursive($user, $parent, $params, $assignments)) {
              return true;
          }
      }
      return false;
  }

整个函数关键点,其实理解这个递归查找本身。我们在代码层面,比如更新某个 post,可能会写如下代码:

if (\Yii::$app->user->can('updatePost', ['post' => $post])) {
    // update post
}

这个时候,系统会跑到这个函数里面,调用这个递归查找,但代码并不是一开始就查找 updatePost 这个 Permission 本身是否匹配用户的 assignments 列表的,而是查找这个 Permission 的父级,把它归属的那些 Role 找出来,然后去匹配 assignments 列表。可能一级找不到,那就多级查找。

那基于 Rule 的情况,又如何理解呢?

你可以理解为,在 Permission 上面,写入自己的逻辑校验,实现粒度更小的控制。

我们看下官方给的代码:

$auth = Yii::$app->authManager;
// add the rule
$rule = new \app\rbac\AuthorRule;
$auth->add($rule);
// add the "updateOwnPost" permission and associate the rule with it.
$updateOwnPost = $auth->createPermission('updateOwnPost');
$updateOwnPost->description = 'Update own post';
$updateOwnPost->ruleName = $rule->name;
$auth->add($updateOwnPost);
// "updateOwnPost" will be used from "updatePost"
$auth->addChild($updateOwnPost, $updatePost);
// allow "author" to update their own posts
$auth->addChild($author, $updateOwnPost);

图片示意:

具体的实现,可以看看上面的 checkAccessRecursive 函数。

最后

写得比较仓促,读者还可以参考以下链接:

notes of building complex software

背景

这是我一直收藏在 evernote 里面的,架构设计方面的合集。后面会不定期更新一些比较好的设计文章,然后我也在想有没办法像湾区日报那样,做得比较自动化,那就太棒了。

不分主题

继续阅读

note of mqtt protocol

blog

- [SSL/TLS配置(证书生成需要注意CN不能乱填)][1]
- [mqtt协议详解][2]

JPush 参考发现的一些点:

- 推送信息的保存时间长短(10天?)
- 单设备多用户
    - server端记录设备的id,多用户通过别名其它机制来做逻辑的映射
    - 但极光的做法是单个设备和别名一对一,不同用户登录,别名会被覆盖
    - 提供有限时长过的记录保存
- [极光推送的很多策略值得参考,API设计的也不错][3]

rabbitmqtt 插件形式:

         ------------------------
         |  mqtt_sup        |  (supervisor)
          ------------------------
            /                    \
           /                      \
          /                        \
         /                          \
-------------------------------------\
|  rabbitmq_mqtt_collector|\
 ------------------------------------- \
       (worker)                      \----------------------------------
                                          | rabbit_mqtt_client_sup|
                                          -----------------------------------
                                                  (supervisor)
                                                       |
                                                       |
                                                       |
                                                  -------------------------------------------
                                                  | rabbit_mqtt_connection_sup|
                                                   ------------------------------------------
                                                       (supervisor)
                                             /    /  \                                        \
                                            /    /    \                                        \
                                           /    /      \                                        \
                                                       -----------------------------          -------------------------------
                                                       | rabbit_mqtt_reader|         | keepalive_supervisor|
                                                        ----------------------------          --------------------------------

协议原理图

protocol img

reading note of mosquitto

背景

之前在游戏公司的时候,需要自己搭建一套推送服务,顺道研究了下一些开源实现。mosquito 的代码库,代码量少,而且也写得比较好懂,对推送协议的实现也是比较 ok 的,所以就撸了一番。虽然后来没用上,但是还是把当时的一些想法记录下来。

缺点

- 基于poll的事件模型,没有epoll的性能好
- 内存分配策略简单,来一个生成一个,存在优化空间
- 比如改用初始2倍,到达一定数量后,以后每次改用增加额定数量的算法
- 数据结构过于简单
- 常用结构为单向链表,查找耗时为O(n),存在性能问题
- 内存占用过大
- 没有使用数据库,数据都堆在内存里面,可能无法应付大数据量
继续阅读

notes of learning erlang

背景

之前因为要想实现一个基于 DHT 网络的站,就找了一些代码实现,发现一个前辈写的 erlang 实现,好奇也看了起来,顺便学了下 erlang。

感悟

  • erlang 太有趣啦,通过模拟进程创建,看到内存和 CPU 资源是怎么被吃掉的,給人很直觀的感覺哇~而且 erlang 同时支持事务和热代码替换,这两项特性碉堡了啊!!!
  • erlang 的并发编程模式,其实我觉得写起来还是读起来都非常的通俗,上手也不难,但有些约定有点反人类,或者语法有点多,约定俗成的东西还要靠看书来回忆…
继续阅读

sharding of mongodb

blog 教程

分片概念

集合可以被分片,一个片可以包含多个区间,一个区间可以包含多个块,一个块可以定大小。所有这些概念都是逻辑上的,真实的物理存储并不存在这样的一一对应关系。如下图:

分片1----
          |
          |
      +++++++++++
      +  |------ 块1   +     区间1
      +  |------ 块2   +
      +++++++++++
          |
          |
      +++++++++++
      +  |------ 块3   +     区间2
      +  |------ 块4   +
      +++++++++++
          |
          |
      +++++++++++
      +  |------ 块5   +     区间3
      +  |------ 块6   +
      +++++++++++
     逻辑概念与物理概念上并不一致

片键选择问题

Geo location

建立索引

源码阅读进度

  • 看了下整个架构
    • 基于 c++ 的一个项目,采用的库有 boost……
    • 多线程模型,通过锁机制来完成任务的调度
    • 事件循环采用最传统 select 机制
      • 每个客户端一个 threading,更优化的可能地方在内部的连接线程池,可以加快响应速度
    • [参考][http://blog.csdn.net/daizhj/article/category/803114]

经验记录

  • 传统的 master、slave 模式已经被弃用,mongo 推荐采用副本集,即 replica set。
    • 它的使用规则还是非常的简易。
      • 主从可以互相切换,当然也支持不切换的。
      • 第三方调用默认读写都走主,但可以调配副本提供读。这样就能有效分流读写的压力。
      • 副本集的提出主要是为了数据备份。
    • mongos 的提出是为了 sharding 的,它也是 mongodb 里面的节点类型之一。(PS:mongodb 有许多节点类型,单个数据库实例算一种,提供查询的 config 也是一种等等)
      • sharding 是为了把大量的数据从单台机分离出来,切分数据到不同的机子上去。避免内存被撑爆了。
      • 未完待续

notes of zhifubao pay

blog 参考资料

接口参考

代码参考

出问题可以参考的资料

开发流程

  • 生成 rsa 公钥、私钥
  • 上传我们的公钥到阿里云服务器(帮助
  • 下载阿里给的对应支付宝公钥,保存起来