0%

codis在迁移方案上下了不少功夫,我认为codis和twemproxy最大的区别之一是:

codis是面向slot的管理,而twemproxy只是面向redis后端的管理

codis迁移是由Topom结构体的SlotCreateAction方法开始的,这个方法也许叫做SlotMoveToGroupCreateAction更加容易让人理解

这个方法需要两个参数,slot id以及group id,目的是吧这个slot(以及该slot的所有key)迁移到目标group中

SlotCreateAction检测了一些边界条件,例如slot正在被迁移,或者该slot已经存在与目标group

阅读全文 »

记录下踩到的坑

一 接口

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package main                                                                       

import (
"fmt"
"bytes"
)

type Stringer interface{
String() string
}

type Point struct{X,Y float64}

func (p *Point) String() string{
var buf bytes.Buffer
fmt.Fprintf(&buf, "%f-%f",p.X,p.Y)
return buf.String()
}

func main(){
r1 := Point{1,2}
var r2 Stringer
r2 = &r1
fmt.Println(&r1) //1.000000-2.000000
fmt.Println(r1) //{1 2}
fmt.Println(r1.String()) //1.000000-2.000000
fmt.Println(r2) //1.000000-2.000000
}
```

第一个语句是调用了带指针的String()结果

第二个Print语句输出r1,是Point结构体的,因为没有声明带指针的String方法,因此fmt输出了默认String方法,也就是{1,2}

第三个语句r1.String()为何能正确执行呢,这是因为编译器自动加了&r1.String()

第四个语句r2是接口类型,赋值r1以后检查类型Stringer实现的接口都被Point实现了,因此可以赋值,并且在调用时调用了r2带指针的String方法,而不是默认的那个

这里要注意的是,r2 = &r1是必须的,因为Point没有声明不带指针的String方法,如果要调用带指针的方法,必须对这个结构体取地址

**二 切片**

```go
package main

import "fmt"

func main() {
array1 := [3]int{1,2}
array2 := [5]int{}
array3 := [...]int{}
array4 := []int{1,2,3,4}
array5 := []int{}
fmt.Println(array1) //[1 2 0]
fmt.Println(array2) //[0 0 0 0 0]
fmt.Println(array3) //[]
fmt.Println(array4) //[1 2 3 4]
fmt.Println(array5) //[]
}
```

切片和数组的声明很类似,困扰了我好久

array1,2,3都是数组类型,4,5是切片类型

在类型的[]里,有数字或者...的都是数组,如果什么都没有则是切片

在我的理解看来,切片是对数组的封装,保存了一个数组的指针

1 切片赋值为数组或者切片并且append小于原来的尺寸

```go
//demo1
array1 := [3]int{1,2}
array2 := []int{}
array2 = array1[0:1]
array2 = append(array2, 3, 4)

//demo2
array3 := []int{1,2}
array4 := []int{}
array4 = array3[0:1]
array4 = append(array4, 3)

fmt.Println(array1) //[1 3 4]
fmt.Println(array2) //[1 3 4]
fmt.Println(array3) //[1 3]
fmt.Println(array4) //[1 3]

对于demo1来说数组能够容纳下这一块数据,因此array2依然指向array1,array1被改为[1 3 4]

对于demo2来说array3底层的数组能够容纳下这一块数据,因此array4依然指向array3底层的数组,array3被改为[1,3]

阅读全文 »

codis3.0内置了ha方案(在3.0以前ha是独立项目)

codis HA架构图

本文大致分析一下他的代码,试图找出他这样设计的目的,是否还存在什么缺点以及分析缺点的解决方案

本文的对象是对redis集群有一定经验,基本了解过codis方案的读者


阅读全文 »

最近出现了网络超时的问题要排查,大致按照如图思路去排查

分层图

排除了代码逻辑问题,TCP相关可能的BUG,内核参数等问题后

在排查KVM问题时,在同一个宿主机的不同KVM上,复现了超时问题。

发现大部分异常连接时长都在1s左右,通过抓包分析,可以看到这部分的包被重传了,重传的时间固定为1秒。

阅读全文 »

zookeeper的库用起来很麻烦,建议使用我封装的zookeeper c库,能考虑更少的zookeeper本身的逻辑

链接:

ylibzkevent


在上一篇文章查CLOSE_WAIT泄漏问题的时候稍微看了下zookeeper c源码,大致对他的流程来做一个分析。

阅读全文 »

对于C/S模型而言,传统的请求和回复是这样的

1
2
3
4
5
6
req ------------->
<------------- rsp
req ------------->
<------------- rsp
req ------------->
<------------- rsp

而pipeline模式是这样的

1
2
3
4
5
6
7
8
9
10
req1 ------------->
req2 ------------->
req3 ------------->
req4 ------------->
<------------- rsp1
req5 ------------->
<------------- rsp2
<------------- rsp3
req6 ------------->
<------------- rsp4

pipeline模式下的客户端可以狂吐数据,而不用等待服务端回复,服务端会按顺序返回rsp。

阅读全文 »

为了提高代码质量,在同事的帮助下学习了如何使用gtest进行单元测试

准备工作

1 首先从googlecode上下载gtest的源码(googlecode明年一月即将关闭不知道这个项目会何去何从呢)

解压后参考README文件进行编译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
GTEST_TARGET=googletest ./travis.sh
GTEST_TARGET=googlemock ./travis.sh
```

此时目录下会生成一个build目录,代码的单元测试依赖的就是这个目录里的静态库文件

2 安装lcov

一般yum即可安装,如果不行的话,那就下载安装

这里不用编译,直接make install即可

```c
wget http://downloads.sourceforge.net/ltp/lcov-1.11.tar.gz
tar xvf lcov-1.11.tar.gz
cd lcov-1.11
make install
阅读全文 »

首先这个问题相当小白,如果已经了解的同学看到这个标题应该就明白了,就能略过不看了。

我遇到这个问题是对改造的twemproxy做异常测试时出现的。

首先简介一下改造的多进程版本的twemproxy原理。

改造的twemproxy会连接zk去获取一些信息,建立监视使得后端redis掉线(使用一个watchdog来将redis注册到zookeeper上)能够通过zookeeper被通知到。

而后才会fork出子进程,主进程当获取到zookeeper的watch消息后,会通过管道来通知子进程去连接此时正常的redis。

阅读全文 »

经常能看到线上的服务器报出超时,除了自己代码的问题,因为网络环境导致超时的原因是各种各样的:

硬件上:各层交换机微突发;芯片转发;链路,网卡阻塞等等

软件上:在负载较高的情况下,KVM之类的虚拟化性能更不上(同一宿主机的两台KVM虚拟机压测时会报出大量超时);

网络导致的超时,简单的可以用ping -f来观察,但是有些细微的超时,需要借助更加细微的工具来发现

我遇到的网络问题,大部分情况下都能使用下面的代码测试验证

阅读全文 »

内存方面的知识真是博大精深,把一些看到的零碎的知识点做个笔记总结下。

这些知识只是自己的理解,并不能保证正确,ULK和《深入理解Linux虚拟内存管理》这两本书看完以后还会来更新这篇的内容。

free

top


阅读全文 »