ARTS是什么?
Algorithm:每周至少做一个leetcode的算法题;
Review:阅读并点评至少一篇英文技术文章;
Tip/Techni:学习至少一个技术技巧;
Share:分享一篇有观点和思考的技术文章。
一、Algorithm
Question: 622. Design Circular Queue(medium)
Design your implementation of the circular queue. The circular queue is a linear data structure in which the operations are performed based on FIFO (First In First Out) principle and the last position is connected back to the first position to make a circle. It is also called "Ring Buffer".
One of the benefits of the circular queue is that we can make use of the spaces in front of the queue. In a normal queue, once the queue becomes full, we cannot insert the next element even if there is a space in front of the queue. But using the circular queue, we can use the space to store new values.
Solution:
Use array list to construct a circular queue. There are three members of a circular queue : queue, head and tail. Head point to the first element, tail point to the next node of tail node. How to check if a queue is empty or full. Empty: head == tail. Full: (tail+1)%len(queue) == head. Notice that when it is full, the last item cant be used, must remain to be None. So when init a k len queue, we need create length of k+1 list.
class MyCircularQueue(object):
def __init__(self, k):
"""
Initialize your data structure here. Set the size of the queue to be k.
:type k: int
"""
self.q = [None]*(k+1)
self.head = 0
self.tail = 0
def enQueue(self, value):
"""
Insert an element into the circular queue. Return true if the operation is successful.
:type value: int
:rtype: bool
"""
if (self.tail+1)%len(self.q) == self.head:
return False
else:
self.q[self.tail] = value
self.tail = (self.tail+1)%len(self.q)
return True
def deQueue(self):
"""
Delete an element from the circular queue. Return true if the operation is successful.
:rtype: bool
"""
if self.head == self.tail:
return False
else:
self.q[self.head] = None
self.head = (self.head+1)%len(self.q)
return True
def Front(self):
"""
Get the front item from the queue.
:rtype: int
"""
if self.head != self.tail:
return self.q[self.head]
else:
return -1
def Rear(self):
"""
Get the last item from the queue.
:rtype: int
"""
if self.head != self.tail:
return self.q[self.tail-1]
else:
return -1
def isEmpty(self):
"""
Checks whether the circular queue is empty or not.
:rtype: bool
"""
return self.head == self.tail
def isFull(self):
"""
Checks whether the circular queue is full or not.
:rtype: bool
"""
return (self.tail+1)%len(self.q) == self.head
##二、Tech
最近补分布式的知识点,本周读的google的13年前的经典论文bigtable。Hbase 是基于bigtable的原理的开源实现。
读书笔记:
1. 背景
google不同的业务对数据存储有不同的需求。比如存储的内容从小的URL到网页以及卫星图像,延迟要求从后台批量处理到提供实时数据服务。希望有一个系统能满各种不同的需求。
2. 数据模型
A bigtable is a sparse, distributed, persistent mutidimensional sorted map.
上面关于bigtable的定义非常关键,我们依次来看下bigtable具有哪些特性。
- sparse:稀疏的,相对关系型数据库,bigtable中的一行,对应的列中的值可能没有,也可能有几十上百个,所以相对于来说是稀疏的。
- distributed:分布式的,bigtable本身是基于GFS存储的,自身也是分布式的,支持水平扩展。
- persistent:持久化,当你的程序结束或数据入口关闭后,保存在map中的数据会被持久化
- mutidimensional:多维度的,一个列可以有多个列,每个列中可能有多个值
- sorted:键值对以严格的字母顺序保存。所以域名的table,是反序的,(www.baidu.com存储为 com.baidu.www),方便同一个域名在排序后再相邻。其他的key则不逆序。
- map:map是由key和value组成的数据结构,其中每一个key和一个value相关联。
map的key为:(row:string, column:string, time:int64) → string,每一个key都有一个对应得了value,也就是实际存储的内容,比如s(com.cnn.www, contents,t3)对应了一个网页。存储的内容就是在t3时间抓取的网页内容。
2.1 行
行的键值为长度不超过64k的任务字符串,一般为10bytes到100bytes。对于操作的原子性,只提供了对单行读写操作的原子性,为了不降低系统的性能,没有提供更高层次的原子性操作。
每一个连续范围行,被称之为tablet,tablet是数据分布和负载均衡调整的最小单位。当操作只读行中很少几列的数据时效率很高,通常只需要很少几次机器间的通信即可完成。
2.2 列
列关键字组成的集合叫做列族,比如关键字content,anchor就是两个列族。访问控制,磁盘和内存的使用统计都是在列族层面进行的,在webtable的例子中,上述的控制权能帮助管理不同类型的应用,比如某些应用可以添加新的数据,某些应用能读取所有数据,部分应用则只能读取部分列的数据。
2.3 时间戳
表中的每一个数据项都可以包含同一份数据的不同版本,比如不同时间抓取的网页快照,不同版本的数据通过时间戳来索引,所以map中的key中一定包含了时间戳。
一般来说,数据保存的不同版本数量是有上限的,这就是单独的垃圾回收机制了。可以设定只保留最新的一份数据,可以保留最新的N份数据,同一个列族中的不同版本数据是按时间戳逆序排列的,最新的数据排放在最上面,方便读取。
3 API
bigtable提供了建立和删除表及列族的API函数,还提供了修改集群、表和列族的元数据的API,比如修改访问权限。
bigtable支持单行上的事物处理,利用这个功能,用户可以对存储在一个行关键字下面的数据进行源自行的读-更新-写操作。脚本程序使用Goolge开发的Sawzall数据处理语言,同时可以和mapReduce一起使用。
4 BigTable组件
GFS:存储日志文件和数据文件,BigTable集群运行在共享的机器池中,和其他应用共享服务器资源。这依赖集群管理系统来调度任务、管理共享的机器上的资源、处理机器的故障、以及监视机器的状态。
SSTable:bigtable内部存储数据的文件是google SSTable格式的,SSTable是一个持久化的、排序的、不可更改的Map结构,而Map是一个key-value映射的数据结构,key和value的值都是任意的Byte串。
Chubby:高可用的、序列化的分布式锁服务组件。一个 Chubby 服务包括 了 5 个活动的副本,其中的一个副本被选为 Master,并且处理请求。只有在大多数副本都是正常运行的,并 且彼此之间能够互相通信的情况下,Chubby 服务才是可用的。当有副本失效的时候,Chubby 使用 Paxos 算法 来保证副本的一致性。Chubby 提供了一个名字空间,里面包括了目录和小文件。每个目录或者文件 可以当成一个锁,读写文件的操作都是原子的。Chubby 客户程序库提供对 Chubby 文件的一致性缓存。每个 Chubby 客户程序都维护一个与 Chubby 服务的会话。如果客户程序不能在租约到期的时间内重新签订会话的 租约,这个会话就过期失效了。当一个会话失效时,它拥有的锁和打开的文件句柄都失效了。Chubby 客户 程序可以在文件和目录上注册回调函数,当文件或目录改变、或者会话过期时,回调函数会通知客户程序。
Bigtable 使用 Chubby 完成以下的几个任务:
- 确保在任何给定的时间内最多只有一个活动的 Master 副本;
- 存储 BigTable 数据的自引导指令的位置(参考 5.1 节);
- 查找 Tablet 服务器,以及在 Tablet 服务器失效时进行善后(5.2 节);
- 存储 BigTable 的模式信息(每张表的列族信息);
- 以及存储访问控制列表。
5 实施
bigtable包含三个主要组件:一个master、多个tablet server、每个客户端使用的库。master负责把tablets分配到不同的tablet server,负载均衡,垃圾回收等。每个tablet server负责管理几十到上千个tablet,tablet server负责响应读写等请求。
客户端处理数据不需要通过master,而是直接和tablet server交互。
5.1 tablet 位置
使用3层的,类似于B+树的结构来索引tablet的位置信息。
第一层存放在chubby,chubby保存着root tablet的信息。root tablet保存着所有tablets的信息。
5.2 tablet分配
在任何一个时刻,一个 Tablet 只能分配给一个 Tablet 服务器。Master 服务器记录了当前有哪些活跃的 Tablet 服务器、哪些 Tablet 分配给了哪些 Tablet 服务器、哪些 Tablet 还没有被分配。当一个 Tablet 还没有被分配、 并且刚好有一个 Tablet 服务器有足够的空闲空间装载该 Tablet 时,Master 服务器会给这个 Tablet 服务器发送 一个装载请求,把 Tablet 分配给这个服务器。
BigTable 使用 Chubby 跟踪记录 Tablet 服务器的状态。当一个 Tablet 服务器启动时,它在 Chubby 的一个 指定目录下建立一个有唯一性名字的文件,并且获取该文件的独占锁。Master 服务器实时监控着这个目录(服 务器目录),因此 Master 服务器能够知道有新的 Tablet 服务器加入了。如果 Tablet 服务器丢失了 Chubby 上的 独占锁 — 比如由于网络断开导致 Tablet 服务器和 Chubby 的会话丢失 — 它就停止对 Tablet 提供服务。
三、Tip
vim的高级功能,
0 → 到行头
^ → 到本行的第一个非blank字符
$ → 到行尾
g_ → 到本行最后一个不是blank字符的位置。
fa → 到下一个为a的字符处,你也可以fs到下一个为s的字符。
t, → 到逗号前的第一个字符。逗号可以变成其它字符。
3fa → 在当前行查找第三个出现的a。
F 和 T → 和 f 和 t 一样,只不过是相反方向。
有时候我们经常想删除部分字符,而cw(删除当前单词)又不够用
for i in range(10):
我先2fr定位到rang的字母r位置,然后想删除range(10),只需要输入dt:。就会变成
for i in :
四、Share
1、不要有日程安排,做此刻最值得做的事;
2、睡前列出第二天要做的3到5件事;
3、第二天列出完成了的3到5件事
4、每天批量处理电子邮件,早上及下班前,保持inbox zero