这里的文字主要是为了记录下我的一些思路,以防日后遗忘。中途会经历相当多的修改。有兴趣的朋友欢迎指教。
关于我的网站应该提供一些什么样的功能、使用什么样的用户交互方式,雏形在我的脑中基本已经形成了,但是还不系统。我需要赶快把它们记录下来,免得以后忘了。当然,在开发的过程中,我的思路随时都会发生变化,因此这里记下的东西也会发生很多修改。一想到网站的功能,马上就会想到要设计什么样的数据库来支持它。所以,这里的记录主要是怎么设计数据库。
数据库软件使用MySQL,先修改my.ini配置文件,默认使用UTF-8编码、InnoDB数据库引擎,并启动二进制日志,以使得数据库备份的工作变简单些。
default-character-set = utf8
datadir = " D:/MySQL_Data/ "
innodb_data_home_dir = ./ibdata
innodb_log_group_home_dir = ./ibdata
innodb_data_file_path = ibdata1:50M:autoextend:max:1G
log-bin = ./bin_log/binlog
binlog-do-db = YumDaysIndex
binlog-do-db = YumDays001
然后开始创建数据库,经过前面在网站架构方面的设想,我需要创建最少两个数据库:一个索引数据库,一个或多个内容数据库。我把索引数据库命名为YumDaysIndex,内容数据库命名为YumDaysNNN,其中的NNN是数字编号,在刚开始的时候,肯定只要一个YumDays001就够了。
GRANT ALL PRIVILEGES ON YumDaysIndex.* TO '********'@'%' IDENTIFIED BY '********' WITH GRANT OPTION;
GRANT ALL PRIVILEGES ON YumDays001.* TO '********'@'%' IDENTIFIED BY '********' WITH GRANT OPTION;
CREATE DATABASE YumDaysIndex;
CREATE DATABASE YumDays001; 选择YumDays001数据库,创建用户表:
USE YumDays001;
CREATE TABLE users(
id char(32) NOT NULL PRIMARY KEY,
name varchar(30) NOT NULL,
password char(32) NOT NULL,
monicker varchar(30) NOT NULL,
question varchar(30) NOT NULL,
answer varchar(30) NOT NULL,
email varchar(30) NOT NULL,
qq varchar(12) NOT NULL,
roleid char(32) NOT NULL,
score int NOT NULL DEFAULT 0,
albumusage int NOT NULL DEFAULT 0,
regtime timestamp NOT NULL DEFAULT '2008-01-01 00:00:00',
logintime timestamp NOT NULL DEFAULT '2008-01-01 00:00:00',
isdeleted varchar(2) NOT NULL DEFAULT '0',
INDEX(name),
INDEX(monicker)
);
这样一些字段分别代表ID、用户名、密码、昵称、密码问题、答案、email、QQ号、用户角色、积分、相册已经使用的磁盘空间、注册时间、登录时间、是否删除等。设计这个表的思路如下:
1、name只能用英文,因为它将是URL的组成部分,为了便于用户之间的识别,所以需要monicker(昵称)字段;
2、根据用户的score字段可以算出用户的相册容量,每次上传图片的时候,都增加albumusage字段的值,如果空间已经被使用完,则不容许上传;
3、ID使用UUID类型,所以它的列类型为char(32),之所以使用UUID,是因为users表会被分割到很多个数据库中,使用UUID可以保证ID的唯一性;
4、isdelete的列类型也比较奇怪,为varchar(2),而默认值却是'0'(字符串),这是因为SpringSide的实现中,在删除数据的时候,会把这个字段设置为'-1'(字符串)。
从这个表中可以看出,这里涉及到一个用户角色的问题,不同的角色拥有不同的权限,所以需要一个Roles表。考虑到Roles表包含的记录数不会太多,而且分布到多个服务器上也不好维护,所以Roles表应该放到索引服务器中。用户登录这样的过程也应该由索引服务器处理,然后将用户的一些信息保存到Cookie中,不过如果用户操作的时候需要查看权限,则一定要向索引服务器请求,索引服务器通过提供WebService来响应请求,因为在Cookie中保存权限会出现安全问题。
创建Roles表的代码如下:
USE YumDaysIndex;
CREATE TABLE roles(
id char(32) NOT NULL PRIMARY KEY,
name varchar(20) NOT NULL,
privilegesflag varchar(255),
INDEX(name)
);
这里需要说明的是privilegesflag字段,该字段我设计为一个用逗号隔开的字符串,比如“post,reply”,代表用户具有发帖、回帖的权限。这么设计的好处就是在开发过程中,不用为了增加权限而修改数据表的结构,只用往这个表中加入新的字符串就行了,而Java代码中,分割字符串又是那么的方便。
在这个表中,我初步设计的角色有四个,它们分别是管理员、超级用户、普通用户和被锁定用户。当然,如果网站规模越来越大,需要有人帮着把关时(否则肯定黄帖广告贴泛滥),可能需要版主、编辑这样的角色。
在我刚开始设计这个系统时,本来是加入了用户群组的功能的,但是经过这两天的沉淀,我决定暂时还是不要这个功能了。以后再加上都可以,但是开发初期我不想为自己找太多麻烦。
文章要进行分类,因此需要创建一个分类表,这个表依然保留在索引服务器上:
CREATE TABLE catalogs(
id char(32) NOT NULL PRIMARY KEY,
name varchar(20) NOT NULL,
INDEX(name)
);
这个表的内容很简单,无需解释。
再下面,就是用来保存文章的表了:
USE YumDays001
CREATE TABLE topics(
id char(32) NOT NULL PRIMARY KEY,
catalogid char(32) NOT NULL,
subject varchar(60) DEFAULT NULL,
content text,
summary varchar(300) default NULL,
mainpicture varchar(100) NOT NULL,
userid char(32) NOT NULL,
time timestamp NOT NULL default CURRENT_TIMESTAMP,
lastedittime timestamp NOT NULL default '2007-01-01 00:00:00',
lastreplytime timestamp NOT NULL default '2007-01-01 00:00:00',
visitcount int NOT NULL,
accessmod tinyint NOT NULL,
INDEX(subject),
INDEX(userid),
INDEX(time),
INDEX(lastreplytime)
);
该表应该保存到内容数据库中。其中的字段都很好理解,从名字即可看出意义。其中需要解释的两个字段如下:
1、mainpicture:我希望每一篇文章都有一个主题图片,该图片在显示文章列表的时候也可以显示(当然是缩略图)。其内容是一个URL。
2、accessmod:该字段保存了该文章的安全属性,即是否公开。取值为1则不公开,取值为3则完全公开。那么2呢?那是我为用户群保留的,取值为2则只正对该文章所属的群公开。
至于索引,那是要根据网站需要提供什么样的功能来设计的。当网站需要按照哪一个规则对文章进行查找的时候,就要在该字段上建立索引,以便加快查找速度。
再往下,则是用来保存回复的表:
CREATE TABLE replys(
id char(32) NOT NULL PRIMARY KEY,
subject varchar(50) NOT NULL,
content text,
userid char(32) NOT NULL,
time timestamp NOT NULL default CURRENT_TIMESTAMP
);
自己回复了哪些文章,心里也要有个数,所以要建立一个表,用来记录用户参与了的文章:
CREATE TABLE participation(
id char(32) NOT NULL PRIMARY KEY,
userid char(32) NOT NULL,
topicid char(32) NOT NULL,
INDEX(userid)
);
再然后,是用来管理相册和相片的表:
create table albums(
id char(32) NOT NULL PRIMARY KEY,
userid char(32) NOT NULL,
name varchar(20) NOT NULL,
description varchar(200) DEFAULT NULL,
photopath varchar(30) NOT NULL,
miniphotopath varchar(30) NOT NULL,
accessmod tinyint NOT NULL,
INDEX(userid)
);
这里的photopath是该相册在服务器上的文件路径,而miniphotopath则是缩略图的路径。accessmod也是起安全控制作用的,意义同前。
CREATE TABLE photos(
id char(32) NOT NULL PRIMARY KEY,
albumid char(32) NOT NULL,
filename varchar(20) NOT NULL,
INDEX(albumid)
);
这样,内容数据库的表已经差不多了,剩下的在开发过程中再逐步完善。而索引服务器还只有前面提到的Roles表和Catalogs表,但是索引服务器要提供显示首页的功能,要提供反向代理的功能,要提供统计排序的功能。因此,我在索引数据库中设计了以下表。
首先,索引服务器中也应该保存有Users的所有数据,需要保存所有的记录,但是不需要保存所有的字段。初步的设计如下:
USE YumDaysIndex;
CREATE TABLE users(
id char(32) NOT NULL PRIMARY KEY,
name varchar(30) NOT NULL,
password char(32) NOT NULL,
monicker varchar(30) NOT NULL,
roleid char(32) NOT NULL,
score int NOT NULL DEFAULT 0,
webserver varchar(10) NOT NULL,
INDEX(name),
INDEX(score)
);
这里保存有用户的验证信息,因此简单的验证功能都可以通过索引服务器来完成。这里有两个字段值得一提,一是score,用来保存用户的分数,主要是为了实现用户排名;另一个字段是webserver,它保存了该用户会被分配到那个Web服务器。
索引服务器还应该保存所有Topics的记录,当然,它不需要保存所有的字段,和Users表一样,它只需要知道到哪个Web服务器可以找到这个Topic的所有数据就行了。初步设计如下:
CREATE TABLE topics(
id char(32) NOT NULL PRIMARY KEY,
catalogid char(32) NOT NULL,
time timestamp NOT NULL default CURRENT_TIMESTAMP,
webserver varchar(10) NOT NULL,
INDEX(time)
);
这个表非常简单,只是维护了一个所有Topic的索引而已,通过webserver字段就知道到哪里找它的详细信息,索引服务器显示主页的时候,可以通过AJAX调用相应的webserver来显示它的摘要信息。time字段是用来排序的,catalog字段是用来分类的。
我还有一个想法,就是想能够按照最新的回复来对Topic进行排序,基本上所有的论坛都是采取的这种方法,只需要有人回复,文章就会被顶上去。但是,由于Topics是分布存储的,所以需要有一个表用来保存最近被回复的文章的信息,而其它的服务器则可以通过定时服务,每隔几分钟在自己的服务器上统计最新被回复的文章,然后提交到索引服务器。其结构如下:
CREATE TABLE hottopics(
id char(32) NOT NULL PRIMARY KEY,
subject varchar(60) NOT NULL,
lastreplytime timestamp NOT NULL default '2007-01-01 00:00:00',
sebserver varchar(10) NOT NULL,
INDEX(lastreplytime)
);
这个表,只需要保存少量的纪录就够了。
还要一个统计表,维护一些统计信息,如注册用户数、文章总数、回复总数、响应新用户注册的当前服务器等等,如下:
CREATE TABLE statistic(
usercount int NOT NULL,
topiccount int NOT NULL,
replycount int NOT NULL,
currentwebserver varchar(10) NOT NULL
);
这个表的名字是单数形式,因为这个表只需要一条纪录就够了。
索引服务器还需要维护所有的相册信息,同Topics表一样,其结构如下:
CREATE TABLE albums(
id char(32) NOT NULL PRIMARY KEY,
time timestamp NOT NULL default CURRENT_TIMESTAMP,
webserver varchar(10) NOT NULL,
INDEX(time)
);
数据库的设计到此告一段落,下一步就开始写代码了。数据库设计中的缺陷,只有经过实战的检验才能够体现出来。