从目前看,基于数据库的接口性能尚未达预期,后续拟增加批量转账接口,并对批量转账接口进行压测
从分散风险的角度出发,在进行sql调优,批量转账接口的同时,从架构角度进行新的设计,并对关键技术进行验证
“两条腿走路”
在现有的日志条件下,以用户注册为例,目前瓶颈在数据库上
第一次发送,数据库里面啥都没有,时间消耗在插入 耗时:428ms
第二次发送,java直接缓存返回,没有经过数据库 耗时:5ms
既然主要时间费在持久化层,由于mysql的插入需要经过多个环节:sql解析,执行计划,undolog,redolog,binlog等等,于是考虑引入更轻量的持久化层
SSDB是Redis+leveldb,兼有了Redis的高速度(内存缓存)和leveldb的海量容量,获2014年中国开源优秀项目奖项
目前我们框架5大类,受影响的主要是Impl类采用新的Dao就行,修改相对比较简单,笔者用了半个上午时间就可以完成开户模块的修改
SSDB ssdb = new SSDB("127.0.0.1", 9888);
ssdb.set("a", "123");
byte[] val = ssdb.get("a");
System.out.println("value is :" + new String(val));
ssdb.close();
具体的替代UserDao的类,使用了其set和get方法,User这个model类直接序列化和反序列化,以uid为key,value序列化后作为byte数组入SSDB(背后是leveldb的本地存储) leveldb的参考:leveldb日知录
public class UserSSDBDao {
public static final String TABLE = "..."; //此处略去方案中敏感信息
public static final String PREFIX = "U";
public User selectByUid(String uid) {
User user = null;
SSDB ssdb = ConnFactory.applyUsable();
try {
byte[] tmp = ssdb.get(PREFIX+uid);
if (tmp != null) {
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(tmp));
user = (User) ois.readObject();
}
} catch (Exception e) {
e.printStackTrace();
}
ConnFactory.putBack(ssdb);
return user;
}
public int insert(User user){
SSDB ssdb = ConnFactory.applyUsable();
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(user);
byte[] tmp = bos.toByteArray();
ssdb.set(PREFIX+user.getUid(), tmp);
} catch (Exception e) {
e.printStackTrace();
}
ConnFactory.putBack(ssdb);
return 1;
}
}
imple类具体的修改(进行数据库操作前,会通过工厂类获得SSDB连接)
private UserSSDBDao userDao = new UserSSDBDao();
@Override
public User getUserByUid(String uid) {
return userDao.selectByUid(uid);
}
单机性能测试指标
指标 | mysql | redis+leveldb |
---|---|---|
纯insert | 300tps | 90000tps |
用户开户业务场景 | 40tps | 4000tps |
亿级流量网站架构核心技术作者 Redis/SSDB+Twenproxy安装和使用
SSDB作者国内博客
Twenproxy 基于redis的高可用方案
SSDB入门基础
官网