0%

在经济学和商业决策制定过程中,会用到“沉没成本(Sunk Cost)”(或称沉淀成本或既定成本)的概念,代指已经付出且不可收回的成本。沉没成本常用来和可变成本作比较,可变成本可以被改变,而沉没成本则不能被改变。在微观经济学理论中,做决策时仅需要考虑可变成本。如果同时考虑到沉没成本(这被微观经济学理论认为是错误的),那结论就不是纯粹基于事物的价值作出的。
举例来说,如果你预订了一张电影票,已经付了票款且假设不能退票。此时你付的价钱已经不能收回,就算你不看电影钱也收不回来,电影票的价钱算作你的沉没成本。
当然有时候沉没成本只是价格的一部分。比方说你买了一辆自行车,然后骑了几天低价在二手市场卖出。此时原价和你的卖出价中间的差价就是你的沉没成本。而且这种情况下,沉没成本随时间而改变,你留着那辆自行车骑的时间越长,一般来说你的卖出价会越低(折旧)。
多数经济学家们认为,如果你是理性的,那就不该在做决策时考虑沉没成本。比如在前面提到的看电影的例子中,会有两种可能结果:
1、付钱后发觉电影不好看,但忍受着看完;
2、付钱后发觉电影不好看,退场去做别的事情。
两种情况下你都已经付钱,所以应该不考虑这件事情。如果你后悔买票了,
那么你当前的决定应该是基于你是否想继续看这部电影,而不是你为这部电影付了多少钱。此时的决定不应该考虑到买票的事,而应该以看免费电影的心态来作判断。经济学家们往往建议选择后者,这样你只是花了点冤枉钱,还可以通过腾出时间来做其他更有意义的事来降低机会成本,而选择前者你还要继续受冤枉罪。这就是生活或者投资的智慧!**

一、查看系统负荷

如果你的电脑很慢,你或许想查看一下,它的工作量是否太大了。
在Linux系统中,我们一般使用uptime命令查看(w命令和top命令也行)。(另外,它们在苹果公司的Mac电脑上也适用。)
你在终端窗口键入uptime,系统会返回一行信息。

这行信息的后半部分,显示"load average",它的意思是"系统的平均负荷",里面有三个数字,我们可以从中判断系统负荷是大还是小。

阅读全文 »

1.FIFO算法

  FIFO(First in First out),先进先出。其实在操作系统的设计理念中很多地方都利用到了先进先出的思想,比如作业调度(先来先服务),为什么这个原则在很多地方都会用到呢?因为这个原则简单、且符合人们的惯性思维,具备公平性,并且实现起来简单,直接使用数据结构中的队列即可实现。
  在FIFO Cache设计中,核心原则就是:如果一个数据最先进入缓存中,则应该最早淘汰掉。也就是说,当缓存满的时候,应当把最先进入缓存的数据给淘汰掉。在FIFO Cache中应该支持以下操作;

阅读全文 »

在hexo github 的issue里找到了解决办法,解决Hexo置顶问题,只需两步:

  1. 用文章中的js代码替换node_modules/hexo-generator-index/lib/generator.js (见下文代码段)
  2. 在需要置顶的文章的front-matter中添加top值,值越大越置顶。
1
2
3
4
5
title: 某某文章
date:
tags:
categories:
top: 1000
阅读全文 »

讲LSM树之前,需要提下三种基本的存储引擎,这样才能清楚LSM树的由来:

1、哈希存储引擎

是哈希表的持久化实现,支持增、删、改以及随机读取操作,但不支持顺序扫描,对应的存储系统为key-value存储系统。对于key-value的插入以及查询,哈希表的复杂度都是O(1),明显比树的操作O(n)快,如果不需要有序的遍历数据,哈希表就是your Mr.Right

2、B树存储引擎

是B树的持久化实现,不仅支持单条记录的增、删、读、改操作,还支持顺序扫描(B+树的叶子节点之间的指针),对应的存储系统就是关系数据库(Mysql等)。

3、LSM树(Log-Structured Merge Tree)存储引擎

和B树存储引擎一样,同样支持增、删、读、改、顺序扫描操作。而且通过批量存储技术规避磁盘随机写入问题。当然凡事有利有弊,LSM树和B+树相比,LSM树牺牲了部分读性能,用来大幅提高写性能。
通过以上的分析,应该知道LSM树的由来了,LSM树的设计思想非常朴素:将对数据的修改增量保持在内存中,达到指定的大小限制后将这些修改操作批量写入磁盘,不过读取的时候稍微麻烦,需要合并磁盘中历史数据和内存中最近修改操作,所以写入性能大大提升,读取时可能需要先看是否命中内存,否则需要访问较多的磁盘文件。极端的说,基于LSM树实现的HBase的写性能比Mysql高了一个数量级,读性能低了一个数量级。
LSM树原理把一棵大树拆分成N棵小树,它首先写入内存中,随着小树越来越大,内存中的小树会flush到磁盘中,磁盘中的树定期可以做merge操作,合并成一棵大树,以优化读性能。

4、HBase存储的设计主要思想

因为小树先写到内存中,为了防止内存数据丢失,写内存的同时需要暂时持久化到磁盘,对应了HBase的MemStore和HLog
MemStore上的树达到一定大小之后,需要flush到HRegion磁盘中(一般是Hadoop DataNode),这样MemStore就变成了DataNode上的磁盘文件StoreFile,定期HRegionServer对DataNode的数据做merge操作,彻底删除无效空间,多棵小树在这个时机合并成大树,来增强读性能。

一、索引的原理

说白了,索引问题就是一个查找问题。数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用B树及其变种B+树。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。
为表设置索引要付出代价的:一是增加了数据库的存储空间,二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)。

上图展示了一种可能的索引方式。左边是数据表,一共有两列七条记录,最左边的是数据记录的物理地址(注意逻辑上相邻的记录在磁盘上也并不是一定物理相邻的)。为了加快Col2的查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就可以运用二叉查找在O(\(\log _{2}n\) )的复杂度内获取到相应数据。

阅读全文 »

1、进程

进程的出现是为了更好的利用CPU资源使到并发成为可能。 假设有两个任务A和B,当A遇到IO操作,CPU默默的等待任务A读取完操作再去执行任务B,这样无疑是对CPU资源的极大的浪费。聪明的老大们就在想若在任务A读取数据时,让任务B执行,当任务A读取完数据后,再切换到任务A执行。注意关键字切换,自然是切换,那么这就涉及到了状态的保存,状态的恢复,加上任务A与任务B所需要的系统资源(内存,硬盘,键盘等等)是不一样的。自然而然的就需要有一个东西去记录任务A和任务B分别需要什么资源,怎样去识别任务A和任务B等等。登登登,进程就被发明出来了。通过进程来分配系统资源,标识任务。如何分配CPU去执行进程称之为调度,进程状态的记录,恢复,切换称之为上下文切换。进程是系统资源分配的最小单位,进程占用的资源有:地址空间,全局变量,文件描述符,各种硬件等等资源。

2、线程

线程的出现是为了降低上下文切换的消耗,提高系统的并发性,并突破一个进程只能干一样事的缺陷,使到进程内并发成为可能。假设,一个文本程序,需要接受键盘输入,将内容显示在屏幕上,还需要保存信息到硬盘中。若只有一个进程,势必造成同一时间只能干一样事的尴尬(当保存时,就不能通过键盘输入内容)。若有多个进程,每个进程负责一个任务,进程A负责接收键盘输入的任务,进程B负责将内容显示在屏幕上的任务,进程C负责保存内容到硬盘中的任务。这里进程A,B,C间的协作涉及到了进程通信问题,而且有共同都需要拥有的东西-------文本内容,不停的切换造成性能上的损失。若有一种机制,可以使任务A,B,C共享资源,这样上下文切换所需要保存和恢复的内容就少了,同时又可以减少通信所带来的性能损耗,那就好了。是的,这种机制就是线程。线程共享进程的大部分资源,并参与CPU的调度, 当然线程自己也是拥有自己的资源的,例如,栈,寄存器等等。 此时,进程同时也是线程的容器。线程也是有着自己的缺陷的,例如健壮性差,若一个线程挂掉了,整一个进程也挂掉了,这意味着其它线程也挂掉了,进程却没有这个问题,一个进程挂掉,另外的进程还是活着。

阅读全文 »

1.定义介绍

(1).XML定义

扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 XML使用DTD(document type definition)文档类型定义来组织数据;格式统一,跨平台和语言,早已成为业界公认的标准。
XML是标准通用标记语言 (SGML) 的子集,非常适合 Web 传输。XML 提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。

(2).JSON定义

JSON(JavaScript Object Notation)一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性。可在不同平台之间进行数据交换。JSON采用兼容性很高的、完全独立于语言文本格式,同时也具备类似于C语言的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)体系的行为。这些特性使JSON成为理想的数据交换语言。
JSON基于JavaScript Programming Language , Standard ECMA-262 3rd Edition - December 1999 的一个子集。

阅读全文 »

KV-存储 之 Hash算法

散列函数(或散列算法,又称哈希函数,英语:Hash Function)是一种从任何一种数据中创建小的数字“指纹”的方法。散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。该函数将数据打乱混合,重新创建一个叫做散列值(hash values,hash codes,hash sums,或hashes)的指纹。散列值通常用一个短的随机字母和数字组成的字符串来代表。好的散列函数在输入域中很少出现散列冲突。在散列表和数据处理中,不抑制冲突来区别数据,会使得数据库记录更难找到。

常见hash算法的原理:
散列表,它是基于高速存取的角度设计的,也是一种典型的“空间换时间”的做法。顾名思义,该数据结构能够理解为一个线性表,可是当中的元素不是紧密排列的,而是可能存在空隙。

阅读全文 »