Membase Java 教程

本文介绍如何使用Java客户端与Membase数据库交互,包括安装配置、基本的读写操作及模拟多客户端环境。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Membase 是一个NOSQL数据库。它被设计为在MEMCACHED(一个流行的内存缓存工具)之后的一个持久化存储。Membase相对比较新但是已经在高性能NOSQL世界有了一个扎实的落脚点。

本文是一个通过JAVA使用Membase数据库的快速教程。


安装MEMBASE


参考 Membase.org的说明


客户端


与Membase的交互类似与Memcached的交互。我们将会使用SpyMemcached Java 客户端。请从  这儿下载。


代码


本项目中所有用到的代码都提供在GitHub :  https://github.com/sujee/membase-tutorial
这一个elipse工程,并且已经可以运行。


让我们开始


这儿的JAVA代码-它将一串key,value写入Membase并且再将他们读取出来。

     
// MembaseTest1
package tutorial ;
import java.net.InetSocketAddress ;
import net.spy.memcached.MemcachedClient ;
/**
* Write / Read from Membase
*
* @author sujee
*
*/
public class MembaseTest1
{
     static int MAX = 100 ;
     static String server = "localhost" ;
     static int port = 11211 ;
     public static void main ( String [] args ) throws Exception
     {
         MemcachedClient cache = new MemcachedClient ( new InetSocketAddress ( server , port ));
         cache . flush (); // 清除所有
         long t1 = System . currentTimeMillis ();
         for ( int i = 0 ; i < MAX ; i ++)
         {
             String s = new Integer ( i ). toString ();
             // key : integer converted to String (keys are always string)
             // time to live : in seconds, 3600 seconds (1h), 0 means no expiration
             // value : actual integer. This can be an object. Our integer will be converted to 'Integer'
             // class by 'auto boxing' proess
             Object o = cache . set ( s , 0 , i );
             System . out . println ( "cache put : " + s + " : " + i + ", result " + o );
         }
         long t2 = System . currentTimeMillis ();
         System . out . println ( "Time for " + MAX + " puts is " + ( t2 - t1 ) + " ms" );
         t1 = System . currentTimeMillis ();
         int nulls = 0 ;
         for ( int i = 0 ; i < MAX ; i ++)
         {
             String s = new Integer ( i ). toString ();
             Object o = cache . get ( s );
             System . out . println ( "Cache get : " + s + " : " + o );
             if ( o == null )
                 nulls ++;
         }
         t2 = System . currentTimeMillis ();
         cache . shutdown ();
         System . out . println ( "Time for " + MAX + " gets is " + ( t2 - t1 ) + " ms. nulls " + nulls );
     }
}
你可以在eclipse中运行这个文件(MembaseTest1)。或者从命令行执行
         sh compile.sh

         sh run.sh

             or

          java -cp classes/:lib/memcached-2.5.jar tutorial.MembaseTest1

Membase运行在本地,端口为11211(默认的memcached端口)

我们在一开始就清洗了整个数据集,这样我们就可以有个干净的初始环境。

Set

cache.set (string_key,   expiration_time,   object_value)

我们的键是一串字符型的数字,我们的对象是是整数型对象。

下面是输出样例:


2010-11-29 23:36:33.234 INFO net.spy.memcached.MemcachedConnection:  Added {QA sa=localhost/127.0.0.1:11211, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue
2010-11-29 23:36:33.240 INFO net.spy.memcached.MemcachedConnection:  Connection state changed for sun.nio.ch.SelectionKeyImpl@b34bed0
cache put : 0 : 0,  result net.spy.memcached.internal.OperationFuture@578088c0
cache put : 1 : 1,  result net.spy.memcached.internal.OperationFuture@37922221
cache put : 2 : 2,  result net.spy.memcached.internal.OperationFuture@5afec107
cache put : 3 : 3,  result net.spy.memcached.internal.OperationFuture@b32e13d
cache put : 4 : 4,  result net.spy.memcached.internal.OperationFuture@39617189
cache put : 5 : 5,  result net.spy.memcached.internal.OperationFuture@2c64f6cd
...
...



Spy Memcache 客户端缓存了很多操作,这样可以提升性能。你可以看到cache.set方法返回了一个 'OperartionFuture' 对象。key-value最终将会在Membase中持久化。

Get

现在我们试着看看我们刚写的读取语句。 我们用了同样的客户端。输出结果就像下面所示:

Cache get : 96 : 96
Cache get : 97 : 97
Cache get : 98 : 98
Cache get : 99 : 99
Time for 100 gets is 77 ms.  nulls 0

我们密切注意NULL值。我们这次不应该获得NULL,如我们所希望的null个数为0。

代码也记录了时间戳,我们可以看到操作是多么得快。



模拟多个客户端


在上面的例子中我们从同一个客户端进行读写。但在实际场景中,多个客户端都会对Membase进行读写。现在我们用两个不同的客户端连接模拟这种情况。
在这个版本中,我们使用一个连接进行写操作另一个连接进行读操作。

     
// MembaseTest2
package tutorial ;
import java.net.InetSocketAddress ;
import net.spy.memcached.MemcachedClient ;
/**
* simulates writing / reading from two different clients
*/
public class MembaseTest2
{
     static int MAX = 1000 ;
     static String server = "localhost" ;
     static int port = 11211 ;
     public static void main ( String [] args ) throws Exception
     {
         MemcachedClient cache = new MemcachedClient ( new InetSocketAddress ( server , port ));
         cache . flush (); // clear all
         long t1 = System . currentTimeMillis ();
         for ( int i = 0 ; i < MAX ; i ++)
         {
             String s = new Integer ( i ). toString ();
               // key : integer converted to String (keys are always string)
             // time to live : in seconds, 3600 seconds (1h), 0 means no expiration
             // value : actual integer. This can be an object. Our integer will be converted to 'Integer'
             // class by 'auto boxing' proess
             Object o = cache . set ( s , 0 , i );
             System . out . println ( "cache put : " + s + " : " + i + ", result " + o );
         }
         long t2 = System . currentTimeMillis ();
         cache . shutdown (); // close the client
         System . out . println ( "Time for " + MAX + " puts is " + ( t2 - t1 ) + " ms" );
         // open another connection
         cache = new MemcachedClient ( new InetSocketAddress ( server , port ));
         t1 = System . currentTimeMillis ();
         int nulls = 0 ;
         for ( int i = 0 ; i < MAX ; i ++)
         {
             String s = new Integer ( i ). toString ();
             Object o = cache . get ( s );
             System . out . println ( "Cache get : " + s + " : " + o );
             if ( o == null )
                 nulls ++;
         }
         t2 = System . currentTimeMillis ();
         cache . shutdown ();
         System . out . println ( "Time for " + MAX + " gets is " + ( t2 - t1 ) + " ms. nulls " + nulls + "\n" );
     }
}
  java -cp classes/:lib/memcached-2.5.jar tutorial.MembaseTest2

Cache get : 0 : 0
Cache get : 1 : 1
.......
.....
Cache get : 997 : null
Cache get : 998 : null
Cache get : 999 : null
Time for 1000 gets is 540 ms.  nulls 42


现在就能看到一个情况,当我们读取刚刚设置的值的时候,就会有NULL产生的情况了。

那么这儿到底发生了些什么了?

请记住,Spy Memcache客户端为了提高性能缓存了不少操作。当我们调用“shutdown”的时候客户端没有把所有的缓存值写入数据库就退出了。所以这些键值就很简单的丢失了。

让我们修正这个问题。

当我们做完SET操作, 让我们更优雅的关闭这个客户端。我们给他10秒的时间再退出。希望这样可以让客户端有机会把所有的缓存操作都执行完成。

     
...
...
long t2 = System . currentTimeMillis ();
cache . shutdown ( 10 , TimeUnit . SECONDS ); // graceful shutdown
System . out . println ( "Time for " + MAX + " puts is " + ( t2 - t1 ) + " ms" );
// open another connection
cache = new MemcachedClient ( new InetSocketAddress ( server , port ));
...
...

java -cp classes/:lib/memcached-2.5.jar tutorial.MembaseTest3

output: 
...
...
Cache get : 998 : 998
Cache get : 999 : 999
Time for 1000 gets is 500 ms.  nulls 0

没有任何NULL值。我们获得了所有写入的值。

所以现在我们很成功的模拟了多个客户端的情况。有一件事情需要记住,客户端做了缓存所以需要优雅的关闭它保证没有数据丢失。
第一部分  NoSQL入门 第1章  NoSQL的概念及适用范围 2 1.1  定义和介绍 3 1.1.1  背景与历史 3 1.1.2  大数据 5 1.1.3  可扩展性 7 1.1.4  MapReduce 8 1.2  面向列的有序存储 9 1.3  键/值存储 11 1.4  文档数据库 14 1.5  图形数据库 15 1.6  小结 16 第2章  NoSQL上手初体验 17 2.1  第一印象——两个简单的例子 17 2.1.1  简单的位置偏好数据集 17 2.1.2  存储汽车品牌和型号数据 22 2.2  使用多种语言 30 2.2.1  MongoDB驱动 30 2.2.2  初识Thrift 33 2.3  小结 34 第3章  NoSQL接口与交互 36 3.1  没了SQL还剩什么 36 3.1.1  存储和访问数据 37 3.1.2  MongoDB数据存储与访问 37 3.1.3  MongoDB数据查询 41 3.1.4  Redis数据存储与访问 43 3.1.5  Redis数据查询 47 3.1.6  HBase数据存储与访问 50 3.1.7  HBase数据查询 52 3.1.8  Apache Cassandra数据存储与访问 54 3.1.9  Apache Cassandra数据查询 55 3.2  NoSQL数据存储的语言绑定 56 3.2.1  Thrift 56 3.2.2  Java 56 3.2.3  Python 58 3.2.4  Ruby 59 3.2.5  PHP 59 3.3  小结 60 第二部分  NoSQL基础 第4章  理解存储架构 62 4.1  使用面向列的数据库 63 4.1.1  使用关系型数据库中的表格和列 63 4.1.2  列数据库对比RDBMS 65 4.1.3  列数据库当做键/值对的嵌套映射表 67 4.1.4  Webtable布局 70 4.2  HBase分布式存储架构 71 4.3  文档存储内部机制 73 4.3.1  用内存映射文件存储数据 74 4.3.2  MongoDB集合和索引使用指南 75 4.3.3  MongoDB的可靠性和耐久性 75 4.3.4  水平扩展 76 4.4  键/值存储Memcached和Redis 78 4.4.1  Memcached的内部结构 78 4.4.2  Redis的内部结构 79 4.5  最终一致性非关系型数据库 80 4.5.1  一致性哈希 81 4.5.2  对象版本 82 4.5.3  闲话协议和提示移交 83 4.6  小结 83 第5章  执行CRUD操作 84 5.1  创建记录 84 5.1.1  在以文档为中心的数据库中创建记录 85 5.1.2  面向列数据库的创建操作 91 5.1.3  键/值映射表的创建操作 93 5.2  访问数据 96 5.2.1  用MongoDB访问文档 96 5.2.2  用HBase访问数据 97 5.2.3  查询Redis 98 5.3  更新和删除数据 98 5.3.1  使用MongoDB、HBase和Redis更新及修改数据 98 5.3.2  有限原子性和事务完整性 99 5.4  小结 100 第6章  查询NoSQL存储 101 6.1  SQL与MongoDB查询功能的相似点 101 6.1.1  加载MovieLens数据 103 6.1.2  MongoDB中的MapReduce 108 6.2  访问HBase等面向列数据库中的数据 111 6.3  查询Redis数据存储 113 6.4  小结 116 第7章  修改数据存储及管理演进 117 7.1  修改文档数据库 117 7.1.1  弱schema的灵活性 120 7.1.2  MongoDB的数据导入与导出 121 7.2  面向列数据库中数据schema的演进 124 7.3  HBase数据导入与导出 125 7.4  键/值存储中的数据演变 126 7.5  小结 126 第8章  数据索引与排序 127 8.1  数据库索引的基本概念 127 8.2  MongoDB的索引与排序 128 8.3  MongoDB里创建和使用索引 131 8.3.1  组合与嵌套键 136 8.3.2  创建唯一索引和稀疏索引 138 8.3.3  基于关键字的搜索和多重键 139 8.4  CouchDB的索引与排序 140 8.5  Apache Cassandra的索引与排序 141 8.6  小结 143 第9章  事务和数据完整性的管理 144 9.1  RDBMS和ACID 144 9.2  分布式ACID系统 147 9.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值