进程组/会话

简要概念:

  • 进程组:N(N>=1)个进程的集合,通常在同一作业中关联起来(通过管道)。进程组的ID(PGID)即为进程组组长的PID。进程必定且只能属于一个进程组,只有进程组中一个进程存在,进程组就存在,与组长进程终止与否无关。进程组的概念提出主要是为了进程管理与信号分发
  • 会话:N(N>=1)个进程组的集合,创建会话的进程叫会话首进程。会话ID即为会话首进程PID
  • 控制终端:如果会话有控制终端,建立与控制终端连接的会话首进程叫控制进程(通常就是Shell进程),当前与终端交互的进程组为前台进程组,其余进程组成为后台进程组
  • 无论合适输入终端的退出键,都会将退出信号发送到前台进程组的所有进程
  • 如果控制终端断开连接,则将挂掉信号(SIGHUP)发送至控制进程(会话首进程),SIGHUP信号默认将导致控制进程终止
阅读全文 »

关于GS设计的一些体会,纯属个人理解。

一. 系统结构

解耦是在做系统设计时,最应该铭记于心的原则,解耦的目的是让系统组件可以独立变化,构建易于理解,测试,维护的系统。

解耦的手段通常有如下几种:

1. 依赖倒置

依赖倒置的原则:上层模块不应该依赖于下层模块,它们共同依赖于一个抽象。抽象不能依赖于具象,具象依赖于抽象。

依赖倒置原则的目的是把高层次组件从对低层次组件的依赖中解耦出来,这样使得重用不同层级的组件实现变得可能。如模块A依赖于模块B,那么在A和B之间加一层接口(interface),A调用(依赖)该接口,B实现(依赖)该接口,这样,只要接口稳定,A,B即可独立变化。

这种依赖抽象的思想,在GOF的设计模式中,有大量宝贵实践,如策略模式,模板方法模式等。

阅读全文 »

一些简单的web学习笔记,用于在需要时快速搭建一个可用的网站。

基础知识

  • HTML: 通过一套标记标签,定义网页的内容
  • CSS: 通过选择器和层叠次序,定义网页的布局
  • JavaScript: 通过可编程的文档对象模型(DOM)和事件响应,定义网页的行为
阅读全文 »

一. 关键指标

  • 慢查询:当MongoDB处理能力不足时,找出系统中的慢查询,分析原因,看能否通过建立索引或重新设计schema改进
  • 内存使用:MongoDB吃内存(特别是MMAPv1),至少要给MongoDB足够的内存存放索引,最理想的情况是能够存放所有数据。当内存占用过高,或者page faults过高时,考虑能不能给MongoDB预留更多的内存。
  • 磁盘占用:特别是对于MMAPv1,涉及到磁盘占用的因素有很多,不合理的schema(文档频繁移动)或集合/文档的删除都可能会导致磁盘空间利用不足。前期需要设计好schema,后期维护也需要定期整理磁盘数据。
  • 连接数:MongoDB为每个连接分配一个线程,因此连接是占资源的,并且也不是越多连接越好。合理地控制连接数。
  • 索引不命中:查看所有查询的索引不命中情况,尽量让所有查询都通过索引
  • 锁等待:锁等待的原因有很多,连接数过多,操作频繁,慢操作,schema设计过于反范式化等,可从上面的原因针对性解决。
阅读全文 »

前几天又翻了翻《深入理解计算机系统》,相比几年前刚看这本书有了更多的理解,这也许就是一本好书的价值吧。因此尝试提炼和总结出对自己有用的东西,把书读薄。其中也加了一些自己的理解和查阅的相关资料。

虚拟存储器的意义

虚拟存储器提供了三个重要的能力:

  • 将主存看作是存储在磁盘上的高速缓存,并根据需要在磁盘和主存中传送数据,高效地运用主存
  • 为每个进程提供一致性的地址空间,简化了存储器管理
  • 保护每个进程的地址空间不被其它进程破坏

下面分别从这三个方面来谈虚拟存储器

阅读全文 »

MongoDB目前支持三种存储引擎:MMAPv1 Storage Engine,In-Memory Storage Engine, WiredTiger Storage Engine。

MMAPv1 Storage Engine

MongoDB3.2之前版本的默认引擎。

1. 存储原理

文档在磁盘中连续存放,文档所占用的磁盘空间包括文档数据所占空间和文档填充(padding)。

摘自:MongoDB MMAPv1内部实现:http://www.mongoing.com/archives/1484

阅读全文 »

一. 查询

1.1 “多段式”查询

当执行find操作的时候,只是返回一个游标,并不立即查询数据库,这样在执行之前可以给查询附加额外选项。几乎所有游标对象的方法都返回游标本身,因此可以按任意顺序组成方法链。以下查询是等价的:

> var cursor = db.foo.find().sort({"x":1}).limit(1).skip(10)
> var cursor = db.foo.find().limit(1).sort({"x":1}).skip(10)
> var cursor = db.foo.find().skip(10).limit(1).sort({"x":1})

此时,我们只是构造了一个查询,并没有执行实际操作,当我们执行:

> cursor.hasNext()

这时,查询被发往服务器,sell立即获取第一个块(前101个文档或前1M数据,取其小者),这样下次调用next或hasNext时,就不必再次向服务器发起一次查询。客户端用完了第一组结果,shell会再次向服务器获取下一组结果(大小不超过4MB), 直至结果全部返回。可通过batchSize设置游标返回的块的文档数量。

注:如果在shell中,没有将返回的游标赋给一个var,shell将自动迭代游标20次,显示出前20调记录。

阅读全文 »

一. 什么是分片

分片(shards)是使用多个机器存储数据的方法,MongoDB使用分片以支持巨大的数据存储量和对数据的操作。它将一个很大的集合分割成多个片(shard),每个分片存储于不同的机器或副本集中,每个分片都是一个独立的数据库。

分片为提高系统吞吐量和大数据的存储提供了方法:

  • 使用分片减少了每个分片需要处理的请求数
  • 使用分片减少了每个分片存储的数据量
阅读全文 »

一. 接入远程节点

1. JCL

erl -sname n2 -setcookie 123
(n2@T4F-MBP-11)1>        //^G
User switch command
 --> r 'n1@T4F-MBP-11'
 --> c
Eshell V8.1  (abort with ^G)
(n1@T4F-MBP-11)1>

2. remsh

erl -setcookie abc -name node_2@127.0.0.1 -remsh node_1@127.0.0.1

和第一种JCL方式是同一个原理,这也是rebar2 remote_console的实现方式。

3. erl_call

    erl_call -s -a 'erlang memory ' -name node_1@127.0.0.1 -c abc

4. run_erl

    run_erl -daemon tmp/ log/ "exec erl -eval 't:start_link().'"

run_erl是随OTP发布的命令,它通过管道来与Erlang节点交互,仅类Unix系统下可用。上面的命令启动Erlang节点,将tmp/目录设为节点管道目录,之后run_erl会在tmp下创建erlang.pipe.1.r erlang.pipe.1.w两个管道文件,外部系统可通过该管道文件向节点写入/读取数据。可用OTP提供的to_erl命令通过管道连接到节点:

阅读全文 »

使用binary而不是lists

所有能用binary的地方都用binary,配置,协议,DB,网络接口,等等,如果驱动或第三方库不能很好地支持binary,就换一个或者重写接口,如果项目一开始就这么做,会在后期省掉很多麻烦。

不要动态生成 atom

atom不被Erlang GC,在代码中要时刻警惕诸如list(binary)_to_atom/2binary_to_term/1等动态生成atom的API,特别是这些API的输入源来自于网络或客户端等不可信源,可用list(binary)_to_existing_atom/2binary_to_term/2替换之,前者只能转换为已经存在的原子,否则会报错,后者功能类似,确保不会生成新的atom,函数引用,Pid等(这些资源都是不会被GC回收的)。

可通过erlang:memory/0来观察atom内存使用状况。

阅读全文 »