登录 注册

【设计】关于简单个人博客的设计

关于自己设计和简写的一个个人博客系统的相关设计思路
时间:2016-04-17 23:42:52 作者:Mr.d

       个人博客是当前比较流行的一个将个人学习、经验、情感抒发的方式,以文字的形式记录下当时的点点滴滴,当某一天看到时,又是一种不一样的感受。


        当前有很多开源的博客系统(例如:hexo—逼格挺高的一个基于github的开源博客),只需要修改相应的一些主题,或者相关配置,就可以完整的实现整个博客的功能,各有个的特点,而我的这个博客是纯粹的自己架构,自己手写的代码,不是为了别的,只是为了能够培养一下自己在架构、设计方面的能力。


        博客的架构其实很简单,没有太多的业务逻辑,也没有太多的复杂的东西,只需要将内容展现出来就好。


数据库设计


        数据库方面来说仅有几张表就可以满足,一张User(用户)表,一张Blog(文章)表,一张Commont(评论)表,一张Theme(主题)表,就可以了, 如果还希望能有一些点赞、关注,也可以加上一张Zan(点赞),一张Interest(关注)表。在设计数据库的时候,将一些表和表之间的关联关系,以主键的方式存储在字段中,避免了真正的表和表之间的主外键关联约束,这里我在网上查到一个词,叫做“弱关联”,有兴趣的可以查一下。

        我不太清楚我画的这个图叫什么图了,但是整体的设计流程可以简要的理解为这样一句话:用户(User),通过选择主题(Theme),发布了一篇博文(Blog),其他用户可以对这篇博文进行评论(Comment),点赞(Zan)。

        数据库表结构


详细设计

        在设计中,由于博文(Blog)中只记录了作者(author_id)和主题(theme_id)所对应的ID,那么在显示时,必然会产生表关联的行为,例如当查询某一篇文章时,会用到sql 

select b.*,u.nick_name from blog b left join user u on b.author_id = u.user_id where b.id = ?

虽然小数据量、同一个库的关联不会产生性能上的问题, 但为了减少这种关联操作,我做了一个简单的设计,当程序第一次读取文章的时候,将关联查询出来的结果放到Redis中进行存储,以blog_id为Key,blog内容为Value,那么再下一次的读取文章时,只需根据blog_id从Redis中对应获取即可,减少了数据库的操作,而整篇文章数据中,资源占用最大的部分也是文章的内容,那么在获取博客列表的时候只需要将需要的字段获取即可,不需要查询内容信息了。


        博客的点赞和评论功能,有单独的表进行记录, 每一个评论、点赞都会对应生成一条记录,相应的,在进行取消赞或删除评论时,将该记录状态置为不可用,使用“软删除”的方式保存数据, 这样的话可以针对其中的不可用数据进行一些简单的用户行为分析。我在博客(Blog)表中增设了两个字段分别为zan_count、commont_count 分别记录点赞和评论的个数,这个数值的操作为触发修改, 当有人进行评论、点赞时对应增加字段数值,取消、删除时对应减小。这样的操作,避免了在列表显示时,对评论、点赞数量统计还需要在SQL中进行count表的操作,减小的性能的消耗。


        既然程序中用到了Redis,那么我也顺道做了一个简单的消息队列的功能,以用户ID为Key在触发操作某些事件时将某些信息异步的放入到Redis队列中,利用Redis可持久化的特点,保证了数据的安全性,也避免了重复的对数据库的操作,增设了一个简单的消息列表的功能,在Redis中存放着“未读消息”,当用户操作,将消息置为“已读”时,将消息在Redis队列中移除,并持久化到数据库中。

//线程池
	private static ExecutorService executorService = new ThreadPoolExecutor(5, 5, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(100) ,new RejectedExecutionHandler() {
		@Override
		public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
			Logs.geterrorLogger().error("MessageUtil msg is too many ,discard it.");
		}
	});
	
	
	public static void pushMessage(final RobotBlogMessage message){
		executorService.execute(new Runnable() {
			
			@Override
			public void run() {
				//设置默认id ,当做key获取
				message.setId(System.currentTimeMillis());
				message.setContent(MessageUtil.getMessageString(message.getType()));
				message.setCreatedDate(new Date());
				JedisUtil.putMapValue(CacheKeys.MESSAGE_KEY+message.getUserId()
										,message.getId()+""
										,JSON.toJSONString(message));
				
			}
		});
		
	}
	
	
	
	private static String MESSAGE_INTEREST_AUTHOR = "恭喜您,有新的用户关注了您哟!~";
	private static String MESSAGE_COMMONT_BLOG = "您的博客有新评论!~";
	private static String MESSAGE_LIKE_BLOG = "恭喜您,有新的用户对您的文章点赞了哟!~";
	private static String MESSAGE_AUTHOR_PUBLISH = "您所关注的作者有新文章发布了哟!~";
	private static String MESSAGE_REPLAY_COMMONT = "您的评论有人回复了哦!~";
	
	public static String getMessageString(int type) {
		String str = "";
		switch(type){
			case 1:str = MESSAGE_INTEREST_AUTHOR;break;
			case 2:str = MESSAGE_COMMONT_BLOG;break;
			case 3:str = MESSAGE_LIKE_BLOG;break;
			case 4:str = MESSAGE_AUTHOR_PUBLISH;break;
			case 5:str = MESSAGE_REPLAY_COMMONT;break;
		}
		return str;
	}


写在后面

        程序使用SpringMVC+JDBC+mysql+Redis,作为服务端程序处理,前段使用了Bootstrap的博客模板进行布局,基本可以实现响应式的布局要求。

        程序基本的设计就是这样的,没有太多新鲜的花样, 只是将一些大的读取放到了Redis中,也算是针对当下主流的NoSql数据库进行了一个小小的测试和试验。

        代码有写好的,有兴趣的可以可以联系我。QQ:2410508062





评论


暂无评论