Redis代码阅读3--Redis网络监听(3)



是介绍Redis网络监听的最后一篇文章,着重分析定时时间处理函数serverCron,这个函数其实已经和网络监听没多大关系了,当时因为其绑定在Redis自定义的事件库的定时事件上,所以放到一起来讲。serverCron的这个函数对Redis的正常运行来说很重要,对于Redis的使用者来说,最重要的就是能够迅速直观地看到Redis的当前的运行状况(keys,sizes,memory等),serverCron就能够使用户得知这些信息,此外,serverCron这个方法定时周期地运行,还承担了AOF
Write,VM Swap,BGSAVE,Rehash的操作,使得Redis的运行更加平稳。还是来直接通过代码来分析:

C代码  

  1. int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {  
  2.     int j, loops = server.cronloops;  
  3.     REDIS_NOTUSED(eventLoop);  
  4.     REDIS_NOTUSED(id);  
  5.     REDIS_NOTUSED(clientData);  
  6.   
  7.     /* We take a cached value of the unix time in the global state because 
  8.      * with virtual memory and aging there is to store the current time 
  9.      * in objects at every object access, and accuracy is not needed. 
  10.      * To access a global var is faster than calling time(NULL) */  
  11.     server.unixtime = time(NULL);  
  12.     /* We have just 22 bits per object for LRU information. 
  13.      * So we use an (eventually wrapping) LRU clock with 10 seconds resolution. 
  14.      * 2^22 bits with 10 seconds resoluton is more or less 1.5 years. 
  15.      * 
  16.      * Note that even if this will wrap after 1.5 years it's not a problem, 
  17.      * everything will still work but just some object will appear younger 
  18.      * to Redis. But for this to happen a given object should never be touched 
  19.      * for 1.5 years. 
  20.      * 
  21.      * Note that you can change the resolution altering the 
  22.      * REDIS_LRU_CLOCK_RESOLUTION define. 
  23.      */  
  24.     updateLRUClock();  
  25.   
  26.     /* We received a SIGTERM, shutting down here in a safe way, as it is 
  27.      * not ok doing so inside the signal handler. */  
  28.     if (server.shutdown_asap) {  
  29.         if (prepareForShutdown() == REDIS_OK) exit(0);  
  30.         redisLog(REDIS_WARNING,"SIGTERM received but errors trying to shut down the server, check the logs for more information");  
  31.     }  
  32.   
  33.     /* Show some info about non-empty databases */  
  34.     for (j = 0; j < server.dbnum; j++) {  
  35.         long long size, used, vkeys;  
  36.   
  37.         size = dictSlots(server.db[j].dict);  
  38.         used = dictSize(server.db[j].dict);  
  39.         vkeys = dictSize(server.db[j].expires);  
  40.         if (!(loops % 50) && (used || vkeys)) {  
  41.             redisLog(REDIS_VERBOSE,"DB %d: %lld keys (%lld volatile) in %lld slots HT.",j,used,vkeys,size);  
  42.             /* dictPrintStats(server.dict); */  
  43.         }  
  44.     }  
  45.   
  46.     /* We don't want to resize the hash tables while a bacground saving 
  47.      * is in progress: the saving child is created using fork() that is 
  48.      * implemented with a copy-on-write semantic in most modern systems, so 
  49.      * if we resize the HT while there is the saving child at work actually 
  50.      * a lot of memory movements in the parent will cause a lot of pages 
  51.      * copied. */  
  52.     if (server.bgsavechildpid == -1 && server.bgrewritechildpid == -1) {  
  53.         if (!(loops % 10)) tryResizeHashTables();  
  54.         if (server.activerehashing) incrementallyRehash();  
  55.     }  
  56.   
  57.     /* Show information about connected clients */  
  58.     if (!(loops % 50)) {  
  59.         redisLog(REDIS_VERBOSE,"%d clients connected (%d slaves), %zu bytes in use",  
  60.             listLength(server.clients)-listLength(server.slaves),  
  61.             listLength(server.slaves),  
  62.             zmalloc_used_memory());  
  63.     }  
  64.   
  65.     /* Close connections of timedout clients */  
  66.     if ((server.maxidletime && !(loops % 100)) || server.bpop_blocked_clients)  
  67.         closeTimedoutClients();  
  68.   
  69.     /* Check if a background saving or AOF rewrite in progress terminated */  
  70.     if (server.bgsavechildpid != -1 || server.bgrewritechildpid != -1) {  
  71.         int statloc;  
  72.         pid_t pid;  
  73.   
  74.         if ((pid = wait3(&statloc,WNOHANG,NULL)) != 0) {  
  75.             if (pid == server.bgsavechildpid) {  
  76.                 backgroundSaveDoneHandler(statloc);  
  77.             } else {  
  78.                 backgroundRewriteDoneHandler(statloc);  
  79.             }  
  80.             updateDictResizePolicy();  
  81.         }  
  82.     } else {  
  83.         /* If there is not a background saving in progress check if 
  84.          * we have to save now */  
  85.          time_t now = time(NULL);  
  86.          for (j = 0; j < server.saveparamslen; j++) {  
  87.             struct saveparam *sp = server.saveparams+j;  
  88.   
  89.             if (server.dirty >= sp->changes &&  
  90.                 now-server.lastsave > sp->seconds) {  
  91.                 redisLog(REDIS_NOTICE,"%d changes in %d seconds. Saving...",  
  92.                     sp->changes, sp->seconds);  
  93.                 rdbSaveBackground(server.dbfilename);  
  94.                 break;  
  95.             }  
  96.          }  
  97.     }  
  98.   
  99.     /* Expire a few keys per cycle, only if this is a master. 
  100.      * On slaves we wait for DEL operations synthesized by the master 
  101.      * in order to guarantee a strict consistency. */  
  102.     if (server.masterhost == NULL) activeExpireCycle();  
  103.   
  104.     /* Swap a few keys on disk if we are over the memory limit and VM 
  105.      * is enbled. Try to free objects from the free list first. */  
  106.     if (vmCanSwapOut()) {  
  107.         while (server.vm_enabled && zmalloc_used_memory() >  
  108.                 server.vm_max_memory)  
  109.         {  
  110.             int retval = (server.vm_max_threads == 0) ?  
  111.                         vmSwapOneObjectBlocking() :  
  112.                         vmSwapOneObjectThreaded();  
  113.             if (retval == REDIS_ERR && !(loops % 300) &&  
  114.                 zmalloc_used_memory() >  
  115.                 (server.vm_max_memory+server.vm_max_memory/10))  
  116.             {  
  117.                 redisLog(REDIS_WARNING,"WARNING: vm-max-memory limit exceeded by more than 10%% but unable to swap more objects out!");  
  118.             }  
  119.             /* Note that when using threade I/O we free just one object, 
  120.              * because anyway when the I/O thread in charge to swap this 
  121.              * object out will finish, the handler of completed jobs 
  122.              * will try to swap more objects if we are still out of memory. */  
  123.             if (retval == REDIS_ERR || server.vm_max_threads > 0) break;  
  124.         }  
  125.     }  
  126.   
  127.     /* Replication cron function -- used to reconnect to master and 
  128.      * to detect transfer failures. */  
  129.     if (!(loops % 10)) replicationCron();  
  130.   
  131.     server.cronloops++;  
  132.     return 100;  
  133. }  
  134.   
  135. /* This function gets called every time Redis is entering the 
  136.  * main loop of the event driven library, that is, before to sleep 
  137.  * for ready file descriptors. */  
  138. void beforeSleep(struct aeEventLoop *eventLoop) {  
  139.     REDIS_NOTUSED(eventLoop);  
  140.     listNode *ln;  
  141.     redisClient *c;  
  142.   
  143.     /* Awake clients that got all the swapped keys they requested */  
  144.     if (server.vm_enabled && listLength(server.io_ready_clients)) {  
  145.         listIter li;  
  146.   
  147.         listRewind(server.io_ready_clients,&li);  
  148.         while((ln = listNext(&li))) {  
  149.             c = ln->value;  
  150.             struct redisCommand *cmd;  
  151.   
  152.             /* Resume the client. */  
  153.             listDelNode(server.io_ready_clients,ln);  
  154.             c->flags &= (~REDIS_IO_WAIT);  
  155.             server.vm_blocked_clients--;  
  156.             aeCreateFileEvent(server.el, c->fd, AE_READABLE,  
  157.                 readQueryFromClient, c);  
  158.             cmd = lookupCommand(c->argv[0]->ptr);  
  159.             redisAssert(cmd != NULL);  
  160.             call(c,cmd);  
  161.             resetClient(c);  
  162.             /* There may be more data to process in the input buffer. */  
  163.             if (c->querybuf && sdslen(c->querybuf) > 0)  
  164.                 processInputBuffer(c);  
  165.         }  
  166.     }  
  167.   
  168.     /* Try to process pending commands for clients that were just unblocked. */  
  169.     while (listLength(server.unblocked_clients)) {  
  170.         ln = listFirst(server.unblocked_clients);  
  171.         redisAssert(ln != NULL);  
  172.         c = ln->value;  
  173.         listDelNode(server.unblocked_clients,ln);  
  174.         c->flags &= ~REDIS_UNBLOCKED;  
  175.   
  176.         /* Process remaining data in the input buffer. */  
  177.         if (c->querybuf && sdslen(c->querybuf) > 0)  
  178.             processInputBuffer(c);  
  179.     }  
  180.   
  181.     /* Write the AOF buffer on disk */  
  182.     flushAppendOnlyFile();  
  183. }  
int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
    int j, loops = server.cronloops;
    REDIS_NOTUSED(eventLoop);
    REDIS_NOTUSED(id);
    REDIS_NOTUSED(clientData);

    /* We take a cached value of the unix time in the global state because
     * with virtual memory and aging there is to store the current time
     * in objects at every object access, and accuracy is not needed.
     * To access a global var is faster than calling time(NULL) */
    server.unixtime = time(NULL);
    /* We have just 22 bits per object for LRU information.
     * So we use an (eventually wrapping) LRU clock with 10 seconds resolution.
     * 2^22 bits with 10 seconds resoluton is more or less 1.5 years.
     *
     * Note that even if this will wrap after 1.5 years it's not a problem,
     * everything will still work but just some object will appear younger
     * to Redis. But for this to happen a given object should never be touched
     * for 1.5 years.
     *
     * Note that you can change the resolution altering the
     * REDIS_LRU_CLOCK_RESOLUTION define.
     */
    updateLRUClock();

    /* We received a SIGTERM, shutting down here in a safe way, as it is
     * not ok doing so inside the signal handler. */
    if (server.shutdown_asap) {
        if (prepareForShutdown() == REDIS_OK) exit(0);
        redisLog(REDIS_WARNING,"SIGTERM received but errors trying to shut down the server, check the logs for more information");
    }

    /* Show some info about non-empty databases */
    for (j = 0; j < server.dbnum; j++) {
        long long size, used, vkeys;

        size = dictSlots(server.db[j].dict);
        used = dictSize(server.db[j].dict);
        vkeys = dictSize(server.db[j].expires);
        if (!(loops % 50) && (used || vkeys)) {
            redisLog(REDIS_VERBOSE,"DB %d: %lld keys (%lld volatile) in %lld slots HT.",j,used,vkeys,size);
            /* dictPrintStats(server.dict); */
        }
    }

    /* We don't want to resize the hash tables while a bacground saving
     * is in progress: the saving child is created using fork() that is
     * implemented with a copy-on-write semantic in most modern systems, so
     * if we resize the HT while there is the saving child at work actually
     * a lot of memory movements in the parent will cause a lot of pages
     * copied. */
    if (server.bgsavechildpid == -1 && server.bgrewritechildpid == -1) {
        if (!(loops % 10)) tryResizeHashTables();
        if (server.activerehashing) incrementallyRehash();
    }

    /* Show information about connected clients */
    if (!(loops % 50)) {
        redisLog(REDIS_VERBOSE,"%d clients connected (%d slaves), %zu bytes in use",
            listLength(server.clients)-listLength(server.slaves),
            listLength(server.slaves),
            zmalloc_used_memory());
    }

    /* Close connections of timedout clients */
    if ((server.maxidletime && !(loops % 100)) || server.bpop_blocked_clients)
        closeTimedoutClients();

    /* Check if a background saving or AOF rewrite in progress terminated */
    if (server.bgsavechildpid != -1 || server.bgrewritechildpid != -1) {
        int statloc;
        pid_t pid;

        if ((pid = wait3(&statloc,WNOHANG,NULL)) != 0) {
            if (pid == server.bgsavechildpid) {
                backgroundSaveDoneHandler(statloc);
            } else {
                backgroundRewriteDoneHandler(statloc);
            }
            updateDictResizePolicy();
        }
    } else {
        /* If there is not a background saving in progress check if
         * we have to save now */
         time_t now = time(NULL);
         for (j = 0; j < server.saveparamslen; j++) {
            struct saveparam *sp = server.saveparams+j;

            if (server.dirty >= sp->changes &&
                now-server.lastsave > sp->seconds) {
                redisLog(REDIS_NOTICE,"%d changes in %d seconds. Saving...",
                    sp->changes, sp->seconds);
                rdbSaveBackground(server.dbfilename);
                break;
            }
         }
    }

    /* Expire a few keys per cycle, only if this is a master.
     * On slaves we wait for DEL operations synthesized by the master
     * in order to guarantee a strict consistency. */
    if (server.masterhost == NULL) activeExpireCycle();

    /* Swap a few keys on disk if we are over the memory limit and VM
     * is enbled. Try to free objects from the free list first. */
    if (vmCanSwapOut()) {
        while (server.vm_enabled && zmalloc_used_memory() >
                server.vm_max_memory)
        {
            int retval = (server.vm_max_threads == 0) ?
                        vmSwapOneObjectBlocking() :
                        vmSwapOneObjectThreaded();
            if (retval == REDIS_ERR && !(loops % 300) &&
                zmalloc_used_memory() >
                (server.vm_max_memory+server.vm_max_memory/10))
            {
                redisLog(REDIS_WARNING,"WARNING: vm-max-memory limit exceeded by more than 10%% but unable to swap more objects out!");
            }
            /* Note that when using threade I/O we free just one object,
             * because anyway when the I/O thread in charge to swap this
             * object out will finish, the handler of completed jobs
             * will try to swap more objects if we are still out of memory. */
            if (retval == REDIS_ERR || server.vm_max_threads > 0) break;
        }
    }

    /* Replication cron function -- used to reconnect to master and
     * to detect transfer failures. */
    if (!(loops % 10)) replicationCron();

    server.cronloops++;
    return 100;
}

/* This function gets called every time Redis is entering the
 * main loop of the event driven library, that is, before to sleep
 * for ready file descriptors. */
void beforeSleep(struct aeEventLoop *eventLoop) {
    REDIS_NOTUSED(eventLoop);
    listNode *ln;
    redisClient *c;

    /* Awake clients that got all the swapped keys they requested */
    if (server.vm_enabled && listLength(server.io_ready_clients)) {
        listIter li;

        listRewind(server.io_ready_clients,&li);
        while((ln = listNext(&li))) {
            c = ln->value;
            struct redisCommand *cmd;

            /* Resume the client. */
            listDelNode(server.io_ready_clients,ln);
            c->flags &= (~REDIS_IO_WAIT);
            server.vm_blocked_clients--;
            aeCreateFileEvent(server.el, c->fd, AE_READABLE,
                readQueryFromClient, c);
            cmd = lookupCommand(c->argv[0]->ptr);
            redisAssert(cmd != NULL);
            call(c,cmd);
            resetClient(c);
            /* There may be more data to process in the input buffer. */
            if (c->querybuf && sdslen(c->querybuf) > 0)
                processInputBuffer(c);
        }
    }

    /* Try to process pending commands for clients that were just unblocked. */
    while (listLength(server.unblocked_clients)) {
        ln = listFirst(server.unblocked_clients);
        redisAssert(ln != NULL);
        c = ln->value;
        listDelNode(server.unblocked_clients,ln);
        c->flags &= ~REDIS_UNBLOCKED;

        /* Process remaining data in the input buffer. */
        if (c->querybuf && sdslen(c->querybuf) > 0)
            processInputBuffer(c);
    }

    /* Write the AOF buffer on disk */
    flushAppendOnlyFile();
}

 i.    首先将server.cronloops的值赋给loops,server.cronloops指的是serverCron函数的运行次数,每运行一次serverCron函数,server.cronloops++,server.cronloops的内部执行逻辑随着server.cronloops值的不同而改变;
ii.    用server.unixtime = time(NULL)来保存当前时间,因为在virtual memory and aging的时候,需要知道每次Object的access时间,但是这个时间不需要很精确,所以通过全局变量来获取时间比调用time(NULL)快多了;
iii.    记录Redis的最大内存使用量;如果收到了SIGTERM信号,则试图终止Redis
iv.    serverCron方法每运行50次显示Redis内各个非空的DB的使用情况(used,keys,sizes)及当前连接的clients,使用的内存大小;
v.    serverCron方法每运行10次,将试图进行一次Rehash,如果一个a bacground saving正在进行,则不进行rehash,以免造成部分数据丢失;
vi.    关闭timeout的clients;
vii.    如果在执行BGSAVE期间,client执行了bgrewriteaof这个命令,则在serverCron将开始执行a scheduled AOF rewrite
viii.    如果当前Redis正在进行BGSAVE或者AOF rewrite,则check BGSAVE或者AOF rewrite是否已经终止,如果终止则调用相应的函数处理(backgroundSaveDoneHandler/backgroundRewriteDoneHandler),如果当前没有BGSAVE或者AOF rewrite操作,则判断是否进行此类操作,如果需要,则触发此类操作;
ix.    如果有AOF buffer flush操作被暂停了,则每次调用serverCron的时候,恢复AOF buffer flush操作
x.    如果是Master,则周期性地使某些key(随即挑选的)过期,注意这个操作仅仅只针对Master,如果是slaves,则只有通过master的del操作来同步key,以做到强一致性;
xi.    VM的Swap操作
xii.    每运行10次,进行replicationCron,如果存在slaves的话
xiii.    返回100,表示serverCron方法每100毫秒被调用一次,这一点在processTimeEvent这个方法里得以体现:

C代码  

  1. if (retval != AE_NOMORE) {  
  2.                 aeAddMillisecondsToNow(retval,&te->when_sec,&te->when_ms);  
  3.             } else {  
  4.                 aeDeleteTimeEvent(eventLoop, id);  
  5.             }  
if (retval != AE_NOMORE) {
                aeAddMillisecondsToNow(retval,&te->when_sec,&te->when_ms);
            } else {
                aeDeleteTimeEvent(eventLoop, id);
            }

            

通过上面的分析,ServerCron侧重在Rehash,VM Swap, AOF write,BGSAVE等操作,而这些操作都是耗时,而且影响Redis对Clients的响应速度的,因此我们在实际应用的时候可以根据具体情况通过改变类似这样的操作:”loops % 10“来决定上述耗时操作的执行频率,有空我会测试下在不同频率下,redis在压力测试下的性能。

 

此次, Redis的网络监听部分都介绍完了。再回过头来看前面提到的几个问题:

1.         Redis支持 epoll, select, kquque,,通过配置文件来决定采取哪一种

2.         支持文件读写事件和定时事件

3.         采用数组来维护文件事件,链表来保存定时事件(在查找定时事件时,性能不高,有待提高)

4.         Redis Server单线程响应事件,按照先后顺序来响应事件,因此单台 Redis服务器的吞吐量会随着连接的 clients越来越多而下降,可以通过增加更多的 Redis服务器来解决这个问题

5.         Redis在很多代码里都考虑到了尽快地响应各种事件,如在 aeProcessEvent里面,轮询的 wait时间等于当前时间和最近的定时事件响应时间的差值;每次进入轮询 wait之前,在 beforesleep方法里先响应刚刚
unblock的 clients等。

时间: 2024-09-20 12:38:33

Redis代码阅读3--Redis网络监听(3)的相关文章

Redis代码阅读3--Redis网络监听(2)

 这篇文章接上一篇,主要介绍Redis网络监听流程的各个步骤. aeCreateEventLoop :创建用于循环监听的 eventLoop , Redis 支持主流的三种事件触发机制: select ,epoll, kqueue, 可以通过在 config.h 里面配置 HAVE_EPOLL/ HAVE_KQUEUE 来根据不同的操作系统选择合适的机制:调用 ae_epoll.c/ae_select.c/ae_kqueue.c中的 aeApiCreate:创建 eventLoop 的时候没

Redis代码阅读1--Redis启动原理

 前面写了一篇文章简单介绍Redis的list结构.再写完之后,我觉得有必要熟悉Redis的启动过程和如何读取Redis的命令,因此本文将通过分析代码来介绍Redis的启动过程,通过查看Redis 的启动脚本,得知Redis的启动时从Redis.c的main方法开始的.Redis启动可以分为以下几个步骤: 初始化Redis服务器全局配置 重置服务器Save参数(具体下文详解)和加载配置文件 初始化服务器 加载数据库 开始网络监听    一,初始化Redis服务器全局配置.这一步骤主要是主要是

基于VC实现的网络监听功能程序实例_C 语言

本文所述VC++网络监听器代码,可以实现监听网络连接所使用的协议.源IP地址.目标IP地址等信息的功能,并且能把数据内容绑定到网格控件中显示.具体功能代码部分如下所示: //线程函数 UINT ThreadFun( LPVOID pParam ) { CSniffAppDlg* pDlg = static_cast<CSniffAppDlg*>(pParam); MSG msg; char buffer[1000],sourceip[32] ,*tempbuf; char *ptemp; BY

用原始套接字实现网络监听

1.引言 网络监听工具(sinff)是提供给网络管理员的一类管理工具.在以太网中(Ethernet),当网络上连接多台计算机时,某瞬间只能有一台计算机可以传送数据.以太网中,数据是以被称为帧的数据结构为单位进行交换的.通常,在计算机网络上交换的数据结构体的单位是数据包.而在以太网中则称为帧.这种数据包是由记录着数据包发送给对方所必需信息的报头部分和记录着发送信息的报文部分构成.报头部分包含接收端的地址.发送端的地址.数据校验码等信息. 在以太网上,帧(数据包)是被称为带碰撞检测的载波侦听多址访问

如何防止网络监听与端口扫描

1.使用安全工具 有许多工具可以让我们发现系统中的漏洞,如SATAN等.SATAN是一个分析网络的管理.测试和报告许多信息,识别一些与网络相关的安全问题. 对所发现的问题,SATAN提供对这个问题的解释以及可能对系统和网络安全造成影响的程度,并且通过工具所附的资料,还能解释如何处理这些问题. 当然还有很多像这样的安全工具.包括对TCP端口的扫描或者对多台主机的所有TCP端口实现监听:分析网络协议.监视控制多个网段等,正确使用这些安全工具,及时发现系统漏洞,才能防患于未然. 而对于WindowsN

怎样防御网络监听

  尽管网络监听看上去无所不能,但是它也有一个致命弱点,就是只能作为第二波攻击手段,黑客必须已经侵入一台主机才能安放网络监听工具.而且只有在网段内部才会有广播数据,而网段之间是不会有广播数搪的,所以网络监听的局限性在于必须把它放在目标网段上. 所以对策是:尽量敢好安全防范工作,防止黑客侵人,这样就从源头堵住了网络监听的危害,另外如果xp系统中被安放了网络监听,那也会有蛛丝马迹可循.比如说网速变慢,发出的数据包无法总是被目标主机接受,你可以发Ping验证,如果经常收不到目标主机的回应,那有可能就是

UNIX系统管理:网络监听概念

网络监听工具的提供给管理员的一类管理工具.使用这种工具,可以监视网络的状态.数据流动情况以及网络上传输的信息. 但是网络监听工具也是黑客们常用的工具.当信息以明文的形式在网络上传输时,便可以使用网络监听的方式来进行攻击.将网络接口设置在监听模式,便可以源源不断地将网上传输的信息截获. 网络监听可以在网上的任何一个位置实施,如局域网中的一台主机.网关上或远程网的调制解调器之间等.黑客们用得最多的是截获用户的口令. 1什么是网络监听 网络监听是黑客们常用的一种方法.当成功地登录进一台网络上的主机,并

DTCC2013:基于网络监听数据库安全审计

本文讲的是DTCC2013:基于网络监听数据库安全审计,2013年4月18-20日,第四届中国数据库技术大会(DTCC 2013)在北京福朋喜来登酒店拉开序幕.在为期三天的会议中,大会将围绕大数据应用.数据架构.数据管理(数据治理).传统数据库软件等技术领域展开深入探讨,并将邀请一批国内顶尖的技术专家来进行分享.本届大会将在保留数据库软件应用实践这一传统主题的基础上,向大数据.数据结构.数据治理与分析.商业智能等领域进行拓展,以满足于广大从业人士和行业用户的迫切需要. 自2010年以来,国内领先

数据中心面对的网络监听技术

数据中心里最宝贵的就是数据,这些数据里隐含着很多私有的.机密信息,小到个人隐私,大到国家安全,所以保护数据是数据中心最为关键的任务,数据一旦被窃取被泄露,给数据中心带来的损失无法估计.然而,这些数据在数据中心里以及外部并不是静止的,躺在存储硬盘里睡大觉,而是通过网络在不断传递和变化着,网络成为数据传递的最为重要通道,无论是数据中心内部还是外部.对网络进行监听,就可以掌握数据的基本信息和特征,听起来网络监听这个词语贬义成分居多.而实际上,对网络监听对于数据中心管理非常重要.不过的确是凡事都有其两面