Archive for the ‘c/c++’ Category.

线程安全–彻底搞懂volatile关键字

对于volatile这个关键字,相信很多朋友都听说过,甚至使用过,这个关键字虽然字面上理解起来比较简单,但是要用好起来却不是一件容易的事。
这篇文章将从多个方面来讲解volatile,让你对它更加理解。

Continue reading ‘线程安全–彻底搞懂volatile关键字’ »

KETAMA算法:基于虚节点的一致性哈希算法

一致性哈希算法(Consistent Hashing Algorithm)是一种分布式算法,常用于负载均衡。Memcached client也选择这种算法,解决将key-value均匀分配到众多Memcached server上的问题。它可以取代传统的取模操作,解决了取模操作无法应对增删Memcached Server的问题(增删server会导致同一个key,在get操作时分配不到数据真正存储的server,命中率会急剧下降),详细的介绍在这篇帖 子中http://www.iteye.com/topic/611976(后文指代这篇文章的地方均称为引文)。

[下面以Memcached的分布式问题为讨论点,但将Memcached server抽象为节点(Node)]
引文中描述的一致性Hash算法有个潜在的问题是:
将节点hash后会不均匀地分布在环上,这样大量key在寻找节点时,会存在key命中各个节点的概率差别较大,无法实现有效的负载均衡。
如有三个节点Node1,Node2,Node3,分布在环上时三个节点挨的很近,落在环上的key寻找节点时,大量key顺时针总是分配给Node2,而其它两个节点被找到的概率都会很小。 

这种问题的解决方案可以有:
改善Hash算法,均匀分配各节点到环上;[引文]使用虚拟节点的思想,为每个物理节点(服务器)在圆上分配100~200个点。这样就能抑制分布不均 匀,最大限度地减小服务器增减时的缓存重新分布。用户数据映射在虚拟节点上,就表示用户数据真正存储位置是在该虚拟节点代表的实际物理服务器上。

在查看Spy Memcached client时,发现它采用一种称为Ketama的Hash算法,以虚拟节点的思想,解决Memcached的分布式问题。
Continue reading ‘KETAMA算法:基于虚节点的一致性哈希算法’ »

多思多想,根据函数定义找隐藏信息

今天遇到一个很长时间都没发现的问题

先看看这个函数定义:

struct tm *localtime(const time_t *clock);

一般情况下大家都不会觉得这个函数有什么问题

使用的时候通常会根据习惯这样写:

struct tm *pTime = localtime(const time_t *clock);

当然,一般这样用是没问题的,函数返回指针,我用指针接收它,当然不会有问题

但是当你仔细想想这个指针的存储位置时,你可能会想到一个很容易被忽略的问题:

第一:它不可能是栈地址,原因不用说,因为从下层堆栈返回一个栈地址给上层堆栈肯定是用不了的,会报段错误。

第二:它可能是new出来的堆地址,如果真是这样他肯定还会写一个回收这个地址的接口。或者他也会在说明文档里说明,那就要调用者自己去delete,当然这样很不友好,容易导致内存泄露,一般不会这样做。

第三:它可能是一个静态地址,如果真是这样。那你就得注意了,任何调用这个接口的地方返回的都是同一个地址,你必须即取即用。

第四:它可能是一个上层堆栈传进去的上层栈地址,但是从这个接口来看根本没有传地址进去,所有这个情况也不可能。

说了这么多,那么我们来看看这个函数的说明:

The return value points to a statically allocated struct which might be
overwritten by subsequent calls to any of the date and time functions.

这里已经清楚的说明这个函数是返回了一个静态结构体指针。每次调用都会覆盖里面的数据。

localtime和localtime_r

上程序:

#include <cstdlib>
#include <iostream>
#include <time.h>
#include <stdio.h>

using namespace std;

int main(int argc, char *argv[])
{
    time_t tNow =time(NULL);
    time_t tEnd = tNow + 1800;
    //注意下面两行的区别
    struct tm* ptm = localtime(&tNow);
    struct tm* ptmEnd = localtime(&tEnd);

    char szTmp[50] = {0};
    strftime(szTmp,50,"%H:%M:%S",ptm);
    char szEnd[50] = {0};
    strftime(szEnd,50,"%H:%M:%S",ptmEnd);

    printf("%s /n",szTmp);
    printf("%s /n",szEnd);

    system("PAUSE");
    return EXIT_SUCCESS;
}

最后出来的结果是:

21:18:39

21:18:39

和最初想法不一致。

Continue reading ‘localtime和localtime_r’ »

C++ signal的使用

1. 头文件
#include <signal.h>
2. 功能
设置某一信号的对应动作
3. 函数原型
void (*signal(int signum,void(* handler)(int)))(int);
   分解来看:
   typedef void (*sig_t) (int);
sig_t signal(int sig, sig_t func);

第一个参数是目标信号。func参数是一个指针,指向某个处理该信号的函数。这个处理信号函数带有一个int型参数,并应返回void。
func参数也可以设定为下面的一些值:
   SIG_IGN: 如果func参数被设置为SIG_IGN,该信号将被忽略。
   SIG_DFL: 如果func参数被设置为SIG_DFL,该信号会按照确定行为处理。