Bind+Berkeley DB实现DNS动态更新

简介:

本文介绍使用Bind+Berkerley DB驱动(BDBHPT)实现DNS的动态更新。

 一、Bind配置

1.  在named.conf下的基本配置

dlz “bdbhpt zone” {       database “bdbhpt T(or C or P) /dns-root dnsdata.db”; };

2.  三种方式

Transactional mode.:  Highest safety – lowest speed. support commit or rollback operations
Concurrent mode:    Lower safety (no rollback) – higher speed.
Private mode:      No inter-process communication & no locking. Lowest saftey – highest speed.

二、Berkerley DB

1.DB 综述

DB最初开发的目的是以新的HASH访问算法来代替旧的hsearch函数和大量的dbm实现(如AT&T的dbm,Berkeley的ndbm,GNU项目的gdbm),DB的第一个发行版在1991年出现,当时还包含了B+树数据访问算法。在1992年,BSD UNIX第4.4发行版中包含了DB1.85版。基本上认为这是DB的第一个正式版。在1996年中期,Sleepcat软件公司成立,提供对DB的商业支持,后来被Oracle收购,全世界拥有达2亿多用户。在这以后,DB得到了广泛的应用,当前最新版本是4.6.19。

DB支持几乎所有的现代操作系统,如LINUX、UNIX、WINDOWS等,也提供了丰富的应用程序接口,支持C、C++、JAVA、PERL、TCL、PYTHON、PHP等,新版提供的只有C、C++、JAVA详细的文档API,对java有je-3.2.23工具包。

值得注意的是DB是嵌入式数据库系统,而不是常见的关系/对象型数据库,对SQL语言不支持,也不提供数据库常见的高级功能,如存储过程,触发器等。

2. DB的设计思想

DB的设计思想是简单、小巧、可靠、高性能。如果说一些主流数据库系统是大而全的话,那么DB就可称为小而精。DB提供了一系列应用程序接口(API),调用本身很简单,应用程序和DB所提供的库在一起编译成为可执行程序。这种方式从两方面极大提高了DB的效率。第一:DB库和应用程序运行在同一个地址空间,没有客户端程序和数据库服务器之间昂贵的网络通讯开销,也没有本地主机进程之间的通讯;第二:不需要对SQL代码解码,对数据的访问直截了当。

DB对需要管理的数据看法很简单,DB数据库包含若干条记录,每一个记录由关键字和数据(KEY/VALUE)构成。数据可以是简单的数据类型,也可以是复杂的数据类型,例如C语言中结构。DB对数据类型不做任何解释, 完全由程序员自行处理,典型的C语言指针的”自由”风格。如果把记录看成一个有n个字段的表,那么第1个字段为表的主键,第2–n个字段对应了其它数据。DB应用程序通常使用多个DB数据库,从某种意义上看,也就是关系数据库中的多个表。DB库非常紧凑,不超过500K,但可以管理大至256T的数据量。

DB的设计充分体现了UNIX的基于工具的哲学,即若干简单工具的组合可以实现强大的功能。DB的每一个基础功能模块都被设计为独立的,也即意味着其使用领域并不局限于DB本身。例如加锁子系统可以用于非DB应用程序的通用操作,内存共享缓冲池子系统可以用于在内存中基于页面的文件缓冲。

  1. DB核心数据结构

数据库句柄结构DB:包含了若干描述数据库属性的参数,如数据库访问方法类型、逻辑页面大小、数据库名称等;同时,DB结构中包含了大量的数据库处理函数指针,大多数形式为(*dosomething)(DB *, arg1, arg2, …)。其中最重要的有open,close,put,get等函数。

数据库记录结构DBT:DB中的记录由关键字和数据构成,关键字和数据都用结构DBT表示。实际上完全可以把关键字看成特殊的数据。结构中最重要的两个字段是 void * data和u_int32_t size,分别对应数据本身和数据的长度。

数据库游标结构DBC:游标(cursor)是数据库应用中常见概念,其本质上就是一个关于特定记录的遍历器。注意到DB支持多重记录(duplicate records),即多条记录有相同关键字,在对多重记录的处理中,使用游标是最容易的方式。

数据库环境句柄结构DB_ENV:环境在DB中属于高级特性,本质上看,环境是多个数据库的包装器。当一个或多个数据库在环境中打开后,环境可以为这些数据库提供多种子系统服务,例如多线/进程处理支持、事务处理支持、高性能支持、日志恢复支持等。

4. DB数据访问算法

在数据库领域中,数据访问算法对应了数据在硬盘上的存储格式和操作方法。在编写应用程序时,选择合适的算法可能会在运算速度上提高1个甚至多个数量级。大多数数据库都选用B+树算法,DB也不例外,同时还支持HASH算法、Recno算法和Queue算法。

B+树算法:B+树是一个平衡树,关键字有序存储,并且其结构能随数据的插入和删除进行动态调整。为了代码的简单,DB没有实现对关键字的前缀码压缩。B+树支持对数据查询、插入、删除的常数级速度。关键字可以为任意的数据结构。

HASH算法:DB中实际使用的是扩展线性HASH算法(extended linear hashing),可以根据HASH表的增长进行适当的调整。关键字可以为任意的数据结构。

Recno算法:要求每一个记录都有一个逻辑纪录号,逻辑纪录号由算法本身生成。实际上,这和关系型数据库中逻辑主键通常定义为int AUTO型是同一个概念。Recho建立在B+树算法之上,提供了一个存储有序数据的接口。记录的长度可以为定长或不定长。

Queue算法:和Recno方式接近, 只不过记录的长度为定长。数据以定长记录方式存储在队列中,插入操作把记录插入到队列的尾部,相比之下插入速度是最快的。

对算法的选择首先要看关键字的类型,如果为复杂类型,则只能选择B+树或HASH算法,如果关键字为逻辑记录号,则应该选择Recno或Queue算法。当工作集关键字有序时,B+树算法比较合适;如果工作集比较大且基本上关键字为随机分布时,选择HASH算法。Queue算法只能存储定长的记录,在高的并发处理情况下,Queue算法效率较高;如果是其它情况,则选择Recno算法,Recno算法把数据存储为平面文件格式。

注:bind+bdbhpt中我们使用了hash+btree,以下介绍都是以此为基。

5.Berkeley Db的详细API,方法见Berkerley的文档

三、Dns数据在Berkeley中的关系以及存储方式

1.数据结构

定义:

typedef struct bdb_instance { 
       DB_ENV  *dbenv;         
       DB   *data;            
       DBC *cursor;  
       DBC *cursor2;  
       DBC *cursor3;  
       DBC *cursor4;  
       DB   *zone;           
       DB   *xfr;               
       DB   *client;    
} bdbhpt_instance_t; 

2.  表及算法 包括: dns_data dns_zone dns_host dns_client

Dns_data Hash key Zone+a space+host
value Dns data
Dns_xfr Hash key zone
value host
Dns_zone Btree key Reverse zone
value NULL
Dns_client Hash key Zone
value Xfr ip

 

  1. dns data字段:
Order Name Data Type Description
1 replication_id string a unique alpha-numeric id for this record.
2 host string DNS host name
3 ttl string (num) Time to live (string must convert to number)
4 type string DNS data type
5 mx_priority string (num) MX Priority (only for MX DNS types)
6 data string IP address / Host name / Full domain name
7 primary_ns string Primary name server SOA record (SOA ONLY)
8 resp_person string Responsible person SOA record (SOA ONLY)
9 serial string (num) Serial # for SOA record (SOA ONLY)
10 refresh string (num) Refresh timefor SOA record (SOA ONLY)
11 retry string (num) Retry time for SOA record (SOA ONLY)
12 expire string (num) Expire time for SOA record (SOA ONLY)
13 minimum string (num) Minimum time for SOA record (SOA ONLY)
  1. 各表之间的逻辑关系

Dns_client是控制客户端多台同步 Dns_xfr是Dns_client允许增量传输的zone和host Dns_zone是reverse zone能提高查询速度,其值为空,当查询zone的时候其关系为:     Dns_zone–>dns_xfr–>dns_data Dns_data 是最终数据集,当查host时的关系为:     Dns_xfr–>dns_data

5.实例数据 注:bind+bdbhpt官方文档有几个错误,数据要严格按照下面的来定义
[dns_zone] key: moc.tset , data: [dns_client] key: test.com , data: 127.0.0.1 [dns_client] key: test.com , data: 192.168.1.10 [dns_xfr] key: test.com , data: @ [dns_data] key: test.com @ , data: 1 @ 86400 SOA ns1.test.com. hostmaster.test.com. 2006112401 28800 7200 604800 86400 [dns_xfr] key: test.com , data: download [dns_data] key: test.com download , data: 18 download 600 A 192.168.1.15 [dns_data] key: test.com download , data: 19 download 600 A 192.168.1.16 [dns_xfr] key: test.com , data: video [dns_data] key: test.com video , data: 20 video 600 A 192.168.1.17 [dns_data] key: test.com video , data: 21 video 600 A 192.168.1.18 [dns_xfr] key: test.com , data: www [dns_data] key: test.com www , data: 10 www 600 A 192.168.1.19 [dns_data] key: test.com www , data: 11 www 600 A 192.168.1.10 [dns_data] key: test.com www , data: 12 www 600 A 192.168.1.20

四、程序设计与实现(以下是以c来实现的)

1.  需求:

据以上来看,由于数据库只有API,不支持sql,也没server概念,数据库的维护管理全由程序来完成,其基本模块为:

A:添加 B:查找 C:删除 D:同步

2.  细节(子模块)

从上面我们知道要实现上面的功能,其子模块有:

A:复制ID的获得

通过取得dns_xfr中的zone+a space+host遍历dns_data的值,复制ID初值为1(为SOA的),其后相同的zone,复制ID++;

B:reverse zone

也就是把zone反向存储.

C:分离字符串判断是否为SOA记录,如果是则repid=1,否则repid++;

D:把整数转化为字符串函数

E:字符串分离与连接函数

F:命令行getop获取参数函数

H:btree和hash表要实现一Key多值,必须支持key值的复制,而且要提高查找的速度的话,还要支持数据的排序,默认为字典顺序,实现更好的算法则以自定义的callback函数来实现。

3.  程序实现

#include  
#include  
#define dlz_data "dns_data" 
#define dlz_zone "dns_zone" 
#define dlz_xfr "dns_xfr" 
#define dlz_client "dns_client" 
 
//………………………………………………. 
void Usage(void) 
char *soa(char *str); 
int bdbhpt_open(DBTYPE db_type, DB **db_out, const char *db_name, int flags); 
int bdbhpt_create(void); 
void put_data(char *db_name, char *input_key, char *input_data); 
void bdbhpt_close(void); 
void bdbhpt_find(void ); 
void bdbhpt_dele(); 
void bdbhpt_add(void); 
static char * bdbhpt_strrev (char *str); 
int get_last_repid(void); 
int IntToStr(int num, char *buffer); 
//………………………………………………………… 
 
int main(int argc, char *argv[]) 
{ 
    char ch; 
    int ret; 
    opterr = 0; 
    while ((ch = getopt(argc, argv, "c:f:h:i:j:m:z:adsn")) != -1) 
    { 
        switch (ch) 
        { 
            case 'a': 
                operation = add; 
                break; 
            case 'd': 
                operation = dele; 
                break; 
            case 's': 
                operation = list; 
                break; 
            case 'n': 
                key_val =1; 
                operation = add; 
                break; 
            case 'z': 
                zone = optarg; 
                break; 
            case 'h': 
                host = optarg; 
                break; 
            case 'c': 
                c_zone = optarg; 
                break; 
            case 'i': 
                c_ip = optarg; 
                break; 
            case 'j': 
                a_data = optarg; 
                break; 
            case 'm': 
                db_envdir = optarg; 
                break; 
            case 'f': 
                db_file = optarg; 
                break; 
            case '?': 
            default: 
                printf("please use -H\n"); 
                Usage(); 
        } 
      } 
    if (argc < 2) 
    { 
        fprintf(stderr, "Both a Berkeley DB environment and file must be specified\n"); 
    } 
 
    switch(operation) 
    { 
        case list: 
            bdbhpt_find(); 
            break; 
        case dele: 
            bdbhpt_dele(); 
            break; 
        case add: 
            bdbhpt_add(); 
            break; 
        default: 
            fprintf(stderr, "\nNo operation was selected. "\ 
                          "Select an operation (s d a f)\n"); 
            break; 
    } 
} 

四、应用

1.  帮助

###############show record##################

Find Zone=>     bdbhpt -s -z test.com

Find Host=>     bdbhpt -s -z test.com -h www

Find Client=>   bdbhpt -s -c test.com

###############show record##################

Drop Zone=>     bdbhpt -d -z test.com

Drop Host=>     bdbhpt -d -z test.com -h www

Drop Client=>   bdbhpt -d -c test.com

###############show record##################

New Create=>    bdbhpt -n -z test.com -h @ -j "@ 10 SOA ns1.example.com. root.example.com. 2 2800 7200 604800 86400"   -m /dns-root -f dbfile

Append Data=>   bdbhpt -a -z test.com -h www -j "www 10 A 192.168.0.1" -m /dns-root -f dbfile

Append Client=> bdbhpt -a -c test.com -i 192.168.1.11

1.      添加数据

A: 添加SOA

新建库:

bdbhpt -n -z test.com -h @ -j "@ 86400 SOA ns1.test.com. hostmaster.test.com. 2006112401 28800 7200 604800 86400" -m /dns-root -f demo.db

追加:

bdbhpt -a -z test1.com -h @ -j "@ 86400 SOA ns1.test1.com. hostmaster.test1.com. 2006112401 28800 7200 604800 86400" -m /dns-root -f demo.db

添加A记录:

bdbhpt -a -z test.com -h www -j "www 600 A 192.168.1.11" -m /dns-root -f demo.db

添加client:

bdbhpt -a -c test.com -i 192.168.1.10 -m /dns-root -f demo.db

2.      查找数据

查找zone:

bdbhpt -s -z test.com -m /dns-root/test/main/ -f demo.db

查找host:

bdbhpt -s -z test.com -h www -m /dns-root/test/main/ -f demo.db

查找client:

bdbhpt -s -c test.com  -m /dns-root/test/main/ -f demo.db

3.      删除数据

删除整个client:

bdbhpt -d -c test.com  -m /dns-root/test/main/ -f demo.db

删除一个client的IP:

bdbhpt -d -c test2.com -i 192.168.1.15 -m /dns-root/test/main/ -f demo.db

删除整个zone:

bdbhpt -d -z test.com  -m /dns-root/test/main/ -f demo.db

删除zone所属host:

bdbhpt -d -z test2.com -h www  -m /dns-root/test/main/ -f demo.db

删除zone所属host的一个记录:

bdbhpt -d -z test2.com -h www -j "4 www 600 A 192.168.1.13" -m /dns-root/test/main/ -f demo.db

五、测试

测试环境: linux AS4 kernel: 2.6.9-22.Elsmp bind9.4.1 测试工具: DnsPerf
服务器配置: 双cpu Intel(R) Xeon(TM) CPU 3.00GHz L2 CPU: L2 cache: 2048K RAM:4G 测试方法 : 查询10个WIDIP,时间限定6分,不同测试点并发,查看其CPU与RAM的使用情况以及qps数

Node Chn-hz-3-574 Cnc-xa-1-571 Chn-fs-1-573 Chn-sh-2-571
Queries sent 173295 27033 90522 178760
Queries completed 173274 26927 90259 178512
Queries lost 21 106 263 248
Percentage completed 99.99% 99.61% 99.71% 99.86%
Percentage lost 0.01% 0.39% 0.29% 0.14%
Queries per second 481.27 73.45 245.83 484.41

Cpu占用:80%左右

Ram占用:0.2%

发表评论