Berkeley DB 使用SecondKey给数据排序

项目中用到了nosql数据库BDB,借此机会研究了一下它的用法。它的官方示例和文档比较丰富,感觉比较容易学习

在开发过程中出现了一个需求,要把数据根据插入时间遍历,个人认为通过第二主键(SecondKey)比较容易实现。以下是我的基本实现过程

1.在ValueBean中加入insertTime属性

public class ValueBean{
	
	private String insertTime;
	private String hostName;
	private byte[] value;
	

	public String getHostName() {
		return hostName;
	}
	public void setHostName(String hostName) {
		this.hostName = hostName;
	}
	public String getInsertTime() {
		return insertTime;
	}
	public void setInsertTime(String insertTime) {
		this.insertTime = insertTime;
	}
	public byte[] getValue() {
		return value;
	}
	public void setValue(byte[] value) {
		this.value = value;
	}


}
其中的hostName属性在主从同步和生成插入时间时用到,value属性就是key-value中的值


2.TupleBinding类

public class ValueBeanBinding extends TupleBinding<ValueBean> {

	@Override
	public ValueBean entryToObject(TupleInput input) {
        String time = input.readString();
        String name = input.readString();
        byte[] value = new byte[input.getBufferLength()-input.getBufferOffset()];//获得value长度
        input.read(value);
        
        ValueBean data = new ValueBean();
        data.setInsertTime(time);
        data.setHostName(name);
        data.setValue(value);
        
        return data;
	}

	@Override
	public void objectToEntry(ValueBean object, TupleOutput output) {
		ValueBean value = object;
		output.writeString(value.getInsertTime());
		output.writeString(value.getHostName());
		output.write(value.getValue());
	}
	
}

此类用于将ValueBean和DatabaseEntry进行转换,两个方法中的属性读写顺序要统一。


3.SecondaryKeyCreator,第二主键生成器

public class SecondKeyCreator implements SecondaryKeyCreator{
	private TupleBinding<ValueBean> theBinding;
	
	
	SecondKeyCreator(TupleBinding<ValueBean> theBinding) {
		this.theBinding = theBinding;
	}

	@Override
	public boolean createSecondaryKey(SecondaryDatabase secondary,
			DatabaseEntry key, DatabaseEntry data, DatabaseEntry result) {
		ValueBean v =
             (ValueBean) theBinding.entryToObject(data);
		String time=v.getInsertTime();

		result.setData(time.getBytes());

		return true;
	}
	
	


}

指定insertTime属性作为第二主键


在插入一个新数据时生成insertTime十分关键,尤其在高并发和互为主从同步时极易出现“第二主键重复”的错误,造成数据无法插入,我了使用当前时间毫秒数+AtomicInteger自增+hostName的asc码之和,保证insertTime的前后大小顺序。

System.currentTimeMillis()*1000000+(add_num.getAndIncrement()%1000)*1000 + host_key


4.创建第二数据库,用于存储secondkey

SecondaryConfig mySecConfig = new SecondaryConfig();
        mySecConfig.setAllowCreate(true);
        mySecConfig.setSortedDuplicates(false);
TupleBinding<ValueBean> tb =new ValueBeanBinding();
SecondKeyCreator  keyCreator = new  SecondKeyCreator(tb);
        mySecConfig.setKeyCreator(keyCreator);
        mySecConfig.setTransactional(envConfig.getTransactional());
        String secDbName = "mySecondaryDatabase";
        
        mySecDb = myEnv.openSecondaryDatabase(null, secDbName,
        		storeDb, mySecConfig);


到此,便可以使用SecondaryCursor的getNext()和getPrev()前后遍历了,getSearchKey()可以找到你想要的位置


=========================================================================================================

今天发了一个问题,cursor在未关闭之前会把所指的记录锁住。在修改被锁数据的时候会报错。

com.sleepycat.je.LockTimeoutException: (JE 4.1.10) Lock expired. Locker 25268096 7_New I/O server worker #1-2_Txn: waited for lock on database=testdb LockAddr:15430449 node=21 type=WRITE grant=WAIT_NEW timeoutMillis=1000 startTime=1323757856515 endTime=1323757857515
Owners: [<LockInfo locker="8385974 -1_New I/O server worker #1-1_ThreadLocker" type="READ"/>]
Waiters: []


所以在打开指针时要指定锁模式

问题代码:


mySecCursor = sdb.openCursor(null, null);

修改为:

CursorConfig config = new CursorConfig();
	    config.setReadUncommitted(true);
		mySecCursor = sdb.openCursor(null, config);







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值