What hurts more, the pain of hard work or the pain of regret?

0%

rabbitmq 介绍

接触了一下rabbitmq,原来在选型的时候是在rabbitmq跟kafka之间做选择,网上搜了一下之后发现kafka的优势在于吞吐量,而rabbitmq相对注重可靠性,因为应用在im上,需要保证消息不能丢失所以就暂时选定rabbitmq,
Message Queue的需求由来已久,80年代最早在金融交易中,高盛等公司采用Teknekron公司的产品,当时的Message queuing软件叫做:the information bus(TIB)。 TIB被电信和通讯公司采用,路透社收购了Teknekron公司。之后,IBM开发了MQSeries,微软开发了Microsoft Message Queue(MSMQ)。这些商业MQ供应商的问题是厂商锁定,价格高昂。2001年,Java Message queuing试图解决锁定和交互性的问题,但对应用来说反而更加麻烦了。
RabbitMQ采用Erlang语言开发。Erlang语言由Ericson设计,专门为开发concurrent和distribution系统的一种语言,在电信领域使用广泛。OTP(Open Telecom Platform)作为Erlang语言的一部分,包含了很多基于Erlang开发的中间件/库/工具,如mnesia/SASL,极大方便了Erlang应用的开发。OTP就类似于Python语言中众多的module,用户借助这些module可以很方便的开发应用。
于是2004年,摩根大通和iMatrix开始着手Advanced Message Queuing Protocol (AMQP)开放标准的开发。2006年,AMQP规范发布。2007年,Rabbit技术公司基于AMQP标准开发的RabbitMQ 1.0 发布。所有主要的编程语言均有与代理接口通讯的客户端库。

简单的使用经验

通俗的理解

这里介绍下其中的一些概念,connection表示和队列服务器的连接,一般情况下是tcp连接, channel表示通道,可以在一个连接上建立多个通道,这里主要是节省了tcp连接握手的成本,exchange可以理解成一个路由器,将消息推送给对应的队列queue,其实是像一个订阅的模式。

集群经验

rabbitmqctl stop这个是关闭rabbitmq,在搭建集群时候先关闭服务,然后使用rabbitmq-server -detached静默启动,这时候使用rabbitmqctl cluster_status查看集群状态,因为还没将节点加入集群,所以只能看到类似

1
2
3
4
Cluster status of node rabbit@rabbit1 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
{running_nodes,[rabbit@rabbit2,rabbit@rabbit1]}]
...done.

然后就可以把当前节点加入集群,

1
2
3
4
5
6
7
rabbit2$ rabbitmqctl stop_app #这个stop_app与stop的区别是前者停的是rabbitmq应用,保留erlang节点,
#后者是停止了rabbitmq和erlang节点
Stopping node rabbit@rabbit2 ...done.
rabbit2$ rabbitmqctl join_cluster rabbit@rabbit1 #这里可以用--ram指定将当前节点作为内存节点加入集群
Clustering node rabbit@rabbit2 with [rabbit@rabbit1] ...done.
rabbit2$ rabbitmqctl start_app
Starting node rabbit@rabbit2 ...done.

其他可以参考官方文档

一些坑

消息丢失

这里碰到过一个坑,对于使用exchange来做消息路由的,会有一个情况,就是在routing_key没被订阅的时候,会将该条找不到路由对应的queue的消息丢掉What happens if we break our contract and send a message with one or four words, like "orange" or "quick.orange.male.rabbit"? Well, these messages won't match any bindings and will be lost.对应链接,而当使用空的exchange时,会保留消息,当出现消费者的时候就可以将收到之前生产者所推送的消息对应链接,这里就是用了空的exchange。

集群搭建

集群搭建的时候有个erlang vm生成的random cookie,这个是用来做集群之间认证的,相同的cookie才能连接,但是如果通过vim打开复制后在其他几点新建文件写入会多一个换行,导致集群建立是报错,所以这里最好使用scp等传输命令直接传输cookie文件,同时要注意下cookie的文件权限。
另外在集群搭建的时候如果更改过hostname,那么要把rabbitmq的数据库删除,否则启动后会马上挂掉

spark 的一些粗浅使用经验

工作中学习使用了一下Spark做数据分析,主要是用spark的python接口,首先是pyspark.SparkContext(appName=xxx),这是初始化一个Spark应用实例或者说会话,不能重复,
返回的实例句柄就可以调用textFile(path)读取文本文件,这里的文本文件可以是HDFS上的文本文件,也可以普通文本文件,但是需要在Spark的所有集群上都存在,否则会
读取失败,parallelize则可以将python生成的集合数据读取后转换成rdd(A Resilient Distributed Dataset (RDD),一种spark下的基本抽象数据集),基于这个RDD就可以做
数据的流式计算,例如map reduce,在Spark中可以非常方便地实现

简单的mapreduce word count示例

1
2
3
4
textFile = sc.parallelize([(1,1), (2,1), (3,1), (4,1), (5,1),(1,1), (2,1), (3,1), (4,1), (5,1)])
data = textFile.reduceByKey(lambda x, y: x + y).collect()
for _ in data:
print(_)

结果

1
2
3
4
5
(3, 2)
(1, 2)
(4, 2)
(2, 2)
(5, 2)

PHP抽象类和接口

  • 抽象类与接口
  • 抽象类内可以包含非抽象函数,即可实现函数
  • 抽象类内必须包含至少一个抽象方法,抽象类和接口均不能实例化
  • 抽象类可以设置访问级别,接口默认都是public
  • 类可以实现多个接口但不能继承多个抽象类
  • 类必须实现抽象类和接口里的抽象方法,不一定要实现抽象类的非抽象方法
  • 接口内不能定义变量,但是可以定义常量

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
interface int1{
const INTER1 = 111;
function inter1();
}
interface int2{
const INTER1 = 222;
function inter2();
}
abstract class abst1{
public function abstr1(){
echo 1111;
}
abstract function abstra1(){
echo 'ahahahha';
}
}
abstract class abst2{
public function abstr2(){
echo 1111;
}
abstract function abstra2();
}
class normal1 extends abst1{
protected function abstr2(){
echo 222;
}
}

result

1
2
3
PHP Fatal error:  Abstract function abst1::abstra1() cannot contain body in new.php on line 17

Fatal error: Abstract function abst1::abstra1() cannot contain body in php on line 17

problem

Given a sorted integer array without duplicates, return the summary of its ranges.

For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"].

题解

每一个区间的起点nums[i]加上j是否等于nums[i+j]
参考

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
vector<string> summaryRanges(vector<int>& nums) {
int i = 0, j = 1, n;
vector<string> res;
n = nums.size();
while(i < n){
j = 1;
while(j < n && nums[i+j] - nums[i] == j) j++;
res.push_back(j <= 1 ? to_string(nums[i]) : to_string(nums[i]) + "->" + to_string(nums[i + j - 1]));
i += j;
}
return res;
}
};

problem

Given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the sum ≥ s. If there isn’t one, return 0 instead.

For example, given the array [2,3,1,2,4,3] and s = 7,
the subarray [4,3] has the minimal length under the problem constraint.

题解

参考,滑动窗口,跟之前Data Structure课上的online算法有点像,链接

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int len = nums.size();
if(len == 0) return 0;
int minlen = INT_MAX;
int sum = 0;

int left = 0;
int right = -1;
while(right < len)
{
while(sum < s && right < len)
sum += nums[++right];
if(sum >= s)
{
minlen = minlen < right - left + 1 ? minlen : right - left + 1;
sum -= nums[left++];
}
}
return minlen > len ? 0 : minlen;
}
};

problem

A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 LEDs on the bottom represent the minutes (0-59).

Each LED represents a zero or one, with the least significant bit on the right.

For example, the above binary watch reads “3:25”.

Given a non-negative integer n which represents the number of LEDs that are currently on, return all possible times the watch could represent.

Example:

1
2
Input: n = 1
Return: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", "0:16", "0:32"]

Note:

  • The order of output does not matter.
  • The hour must not contain a leading zero, for example “01:00” is not valid, it should be “1:00”.
  • The minute must be consist of two digits and may contain a leading zero, for example “10:2” is not valid, it should be “10:02”.

题解

又是参(chao)考(xi)别人的代码,嗯,就是这么不要脸,链接

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
vector<string> readBinaryWatch(int num) {
vector<string> res;
for (int h = 0; h < 12; ++h) {
for (int m = 0; m < 60; ++m) {
if (bitset<10>((h << 6) + m).count() == num) {
res.push_back(to_string(h) + (m < 10 ? ":0" : ":") + to_string(m));
}
}
}
return res;
}
};

question

34. Search for a Range

Original Page

Given a sorted array of integers, find the starting and ending position of a given target value.

Your algorithm’s runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].

analysis

一开始就想到了二分查找,但是原来做二分查找的时候一般都是找到确定的那个数就完成了,
这里的情况比较特殊,需要找到整个区间,所以需要两遍查找,并且一个是找到小于target
的最大索引,一个是找到大于target的最大索引,代码参考leetcode discuss,这位仁
兄也做了详细的分析解释。

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> ret(2, -1);
int i = 0, j = nums.size() - 1;
int mid;
while(i < j){
mid = (i + j) / 2;
if(nums[mid] < target) i = mid + 1;
else j = mid;
}
if(nums[i] != target) return ret;
else {
ret[0] = i;
if((i+1) < (nums.size() - 1) && nums[i+1] > target){
ret[1] = i;
return ret;
}
} //一点小优化
j = nums.size() - 1;
while(i < j){
mid = (i + j) / 2 + 1;
if(nums[mid] > target) j = mid - 1;
else i = mid;
}
ret[1] = j;
return ret;
}
};

玩一下swoole的websocket

WebSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,WebSocketAPI被W3C定为标准。
,在web私信,im等应用较多。背景和优缺点可以参看wiki

环境准备

因为swoole官方还不支持windows,所以需要装下linux,之前都是用ubuntu,
这次就试一下centos7,还是满好看的,虽然虚拟机会默认最小安装,需要在安装
时自己选择带gnome的,当然最小安装也是可以的,只是最后需要改下防火墙。
然后是装下PHP,Nginx什么的,我是用Oneinstack,可以按需安装
给做这个的大大点个赞。

Read more »

Invert a binary tree

     4
   /   \
  2     7
 / \   / \
1   3 6   9

to

     4
   /   \
  7     2
 / \   / \
9   6 3   1

Trivia:
This problem was inspired by this original tweet by Max Howell:

Google: 90% of our engineers use the software you wrote (Homebrew),
but you can’t invert a binary tree on a whiteboard so fuck off.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root == NULL) return root;
TreeNode* temp;
temp = invertTree(root->left);
root->left = invertTree(root->right);
root->right = temp;
return root;
}
};