大型在线阅读网站的技术拆迁

星期日, 2015-06-21 | Author: Lee | JAVA-and-J2EE, 读书 | 一条评论 2,783 views

在原有的系统上抽离出新新的系统,重新设计能避免原来系统的种种问题,事实上哪有那多的重新演化,推倒重来也会遇到各种问题;

逐步迭代,逐步更新更来的实际废话不多了,想在线看书可以移步这里 爱阅读

遇到的问题(要分表分库无规律可循):
1.在线阅读书籍的数量越来越多,章节单表存储遭遇上限(记录几百万查询速度变慢)

2.章节的id是UUID 没有按照书籍信息进行编码拆分,即无法和书籍关联起来

解决方法:
1.设计和书籍绑定id,此问题不存在,直接分表分库
2.既然原来的不能动,那就加中间层,来次中间rehash 重新转换,完全解耦
以前的开发模式和流程完全不变,只需要中间层拆分数据层即可

小结:中间层的增加,直观上直接增加了程序的执行时间,但是可以支持无限扩展模式;

遇到问题解决问题才是王道,让合适的事情在合适的地方去拆解,没有那么多重新设计和开发

在看开源的代码、系统架构和其他别人的系统的时候,多去想想为什么,有时候看似有点多余的设计,也是有实际情况的限制

在软件行业快速发展的今天,貌似我们遇到的问题,90%都已经被别人遇到,没有那么多不可能,多的是自己实力不到

10%的问题的解决方案你能遇到并解决之,岂不快哉,探索的世界永远值得探索,保持对未知事情的兴趣.

centos快速安装redis部署

星期二, 2015-06-16 | Author: Lee | linux, webgame | 没有评论 3,376 views

每次部署环境的时候都要去安装下,写下文章记录下:
官方快速引导地址:http://redis.io/topics/quickstart

这里只是安装单实例版本,默认是6379的端口版本,预留配置文件等做多实例部署

1.安装redis最新的3.0.2版本

$ wget http://download.redis.io/releases/redis-3.0.2.tar.gz
$ tar xvzf redis-3.0.2.tar.gz
$ cd redis-3.0.2
$ make

2.复制执行文件到bin下(或者执行make install),若执行make test 请先yum install tcl

$ cp src/redis-server /usr/local/bin/
$ cp src/redis-cli /usr/local/bin/

› 继续阅读

Tags: , , ,

java捕获kill信号来处理程序信息

星期五, 2015-05-29 | Author: Lee | JAVA-and-J2EE, linux | 一条评论 8,550 views

在c中常要控制对应的信号信息,在java中也可以实现简单的信号捕获;
可以作为程序的关闭时候清理数据做参考,
程序如下:
› 继续阅读

Tags: ,

双hash减少用户名冲突JAVA版

星期五, 2015-05-08 | Author: Lee | JAVA-and-J2EE, 游戏开发 | 没有评论 3,831 views

游戏中要去校验用户名是否重复,redis中放中文的key貌似蛮怪的吧,还是hash后放数字吧,从而校验是否冲突;

hash冲突 例如“Af”和“BG”哈希值相同,则有“AfAf”,“AfBG”,“BGAf”,“BGBG”的哈希值也相同

具体关于java的Hash冲突攻击 可以参考此文章:http://keary.cn/?p=845

不废话了,实际双hash用途很多,还有就是java中的自带hash会出现负数比如 (-8%3) 就为-2 依赖取模后的值就会出问题;

上代码:
› 继续阅读

Tags: ,

PHP中获取当前页面的URL的方法

星期五, 2015-05-01 | Author: Lee | php | 没有评论 3,735 views

脚本语言就是方便,随便写随便更新
要做以前的域名调整要把参数也调用过来,又设计到指定的不能直接转,有点绕了,废话不说了;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
测试网址:     http://localhost/blog/testurl.php?id=359
//获取域名或主机地址 
echo $_SERVER['HTTP_HOST']."<br>"; #localhost

//获取网页地址 
echo $_SERVER['PHP_SELF']."<br>"; #/blog/testurl.php

//获取网址参数 
echo $_SERVER["QUERY_STRING"]."<br>"; #id=359

//获取用户代理 
echo $_SERVER['HTTP_REFERER']."<br>"; 
 
//获取完整的url
echo 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
echo 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'];
#http://localhost/blog/testurl.php?id=359

//包含端口号的完整url
echo 'http://'.$_SERVER['SERVER_NAME'].':'.$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"]; 
#http://localhost:80/blog/testurl.php?id=359

//只取路径
$url='http://'.$_SERVER['SERVER_NAME'].$_SERVER["REQUEST_URI"]; 
echo dirname($url);
#http://localhost/blog

Tags:

wp升级小计

星期二, 2015-04-28 | Author: Lee | wordpress | 没有评论 3,378 views

风险提示wp4.0的版本有xss的匿名评论的漏洞,要赶快打补丁

就升级了,下载最先的版本,覆盖即可,登录后台点击升级搞定;

记得后台关闭 表情的功能,否则就等着一直load那些我们无法访问的表情图片吧

没有遇到诡异的事情,聊记一下

Tags: ,

Lucene查询速度慢的简单优化

星期一, 2015-04-27 | Author: Lee | JAVA-and-J2EE | 没有评论 6,891 views

算不上比较高深的优化,只是增加了内存就效果明显,表现原因

1.数据量在100W,索引的文件大小90M,算是比较小的了,查询下来需要1000ms
让我很是不解,在本地测试的时候都未出现此情况,只有第一次初始查询出现超过1000ms,
无法接受的速度

2.查看内存使用情况,发现可用内存太少所致,每次都要重新缓存索引,gc内存,(我压榨了阿里云的最大使用率),升级内存,重启OK,速度终于在10ms

3.使用了FSDirectory,使用RAMDirectory效果不明显,而且占用不少内存(实在没有必要)

小结:服务器的性能还没有本地开发机性能好的时候,只有尽快优化了,既要降低cpu的使用率,又不能大量占用内存,真是愁啥人啊

Tags: ,

升级spring4.1.6和支持java8

星期五, 2015-04-24 | Author: Lee | JAVA-and-J2EE, linux | 没有评论 6,031 views

系统使用的是spring-core-3.2.1.RELEASE 的版本,在使用jdk8的时候启动tomcat报错,发现无法启动 servlet 启动报错;

但是使用jdk7的版本是好的,网上google了下发现是jdk8引起的,spring3.x的系列不支持,于是有了下列升级问题,记录

1.替换spring3.x的版本到spring4.x的版本,使用到的spring包都替换(废话了)
下载地址:http://repo.spring.io/libs-release-local/org/springframework/spring/

2.系统有用到 quartz的定时任务,也需要替换 老版本是用的是quartz-all-1.6.0 需要升级到 2.x的版本下载了最新的 quartz-2.2.1.jar,quartz-jobs-2.2.1.jar
下载地址:http://quartz-scheduler.org/

3.调整 applicationContext-quartz.xml 使用的触发类
org.springframework.scheduling.quartz.CronTriggerBean 替换成 org.springframework.scheduling.quartz.CronTriggerFactoryBean

到此,升级成功,还要检测系统稳定性部分,测试下应该没有大问题后,即可更新到正式服了

Tags: , , ,

拆解游戏开发中策划配置动态公式问题

星期一, 2015-04-13 | Author: Lee | JAVA-and-J2EE, 游戏开发 | 没有评论 2,703 views

游戏开发中,策划总希望自己能配置奖励等公式,从程序这边对于这种太动态的东西是有点不太想去实现添加它;

既然有需求也要实现,从spring里剥离的SpelExpressionParser 可以很好的解决这个问题, 支持常见的 +—X/(加减乘除) 和指数计算^等

依赖 spring-expression-3.2.8.RELEASE.jar, 运行还需要 核心库 spring-core-3.2.8.RELEASE.jar
上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.i5a6.semp.test;
 
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
 
public class TestExpress {
 
	public static void main(String[] args) {
		int num = dynamicCalOutput(2, 2, "#playerLevel^(1/2.7)*100*#num");
 
		System.out.println((Math.pow(2, (1 / 2.7)) * 100));
		System.out.println(num);
 
	}
 
	public static int dynamicCalOutput(int lev, int num, String arithmetic) {
		if (arithmetic == null || arithmetic.length() <= 0) {
			return 0;
		}
		ExpressionParser parser = new SpelExpressionParser();
		Expression expression = parser.parseExpression(arithmetic);
 
		EvaluationContext context = new StandardEvaluationContext();
		context.setVariable("playerLevel", lev);
		context.setVariable("num", num);
		return expression.getValue(context, Integer.class);
	}
}

Tags: , ,

一个类说明Java 信号量 Semaphore 的用法

星期五, 2015-04-10 | Author: Lee | JAVA-and-J2EE | 没有评论 5,996 views

在用Semaphore 信号量的时候,感觉对公平调度比较有用,可以控制多线程争夺资源时候,最大可以几个在执行,随手写了代码测试下,如下:
说明: 1. acquire() 获取一个许可,如果没有就等待
2. release() 释放一个许可
3. Semaphore可以控制某个资源可被同时访问的个数,自行初始化的数量,为1当然就顺序执行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package com.i5a6.semp.test;
 
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
 
public class SemaphoreTest {
 
	private Semaphore semp;
 
	private ExecutorService executorPool;
 
	public SemaphoreTest(int threadNum) {
		semp = new Semaphore(threadNum);
		executorPool = Executors.newFixedThreadPool(threadNum);
	}
 
	public void doEnd() {
		this.executorPool.shutdown();
	}
 
	public void doMsg(int num) {
		try {
			semp.acquire();
			executorPool.execute(new HelloUExecutor(num));
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
 
	class HelloUExecutor implements Runnable {
		private int num;
 
		public HelloUExecutor(int num) {
			this.num = num;
		}
 
		Random r = new Random();
 
		@Override
		public void run() {
			try {
				System.out.println(num);
				Thread.sleep(r.nextInt(1000));
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				semp.release();
			}
		}
	}
 
	public static void main(String[] args) {
		// 初始化为1 顺序执行
		SemaphoreTest st = new SemaphoreTest(5);
		for (int i = 0; i < 20; i++) {
			st.doMsg(i);
		}
		st.doEnd();
	}
 
}

Tags: ,

Search

文章分类

Links

Meta