文章目录 
		
			
		
		
		
		像put()、delete()、checkAndPut()这样的修改操作是独立执行的,这意味着在一个串行方式的执行中,对于每一行必须保证行级别的操作是原子性的。region服务器提供了一个行锁(row lock的特性,这个特性保证了只有一个客户端能获取一行数据相应的锁。同时对该行进行修改,在实践中,大部分客户端应用程序都没有提供显示的锁,而是使用这个机制来保障每个操作的独立性。用户应该尽可能的避免使用行锁,就像在RDBMS中,两个客户端很可能在拥有对方要请求的锁时,又同时请求对方已拥有的锁,这样便形成了一个死锁。 
RowLock lockRow (byte[] row)  void unlockRow (RowLock r1)  
第一个调用lockRow()需要一个行键作为参数,返回一个RowLock的实例,这个实例可以供后续的Put或者Delete的构造函数使用。一旦不再需要锁时,必须通过unLockRow()调用来释放它。
<property >   <name > hbase.regionserver.lease.period</name >    <value > 120000</value >  </property > 
通过添加以上代码,超时时间被设置为原来的两倍——120秒也就是2分钟。小心不要将这个值设得太大,因为每一个想获取被锁住的行的客户端都会被阻塞并等待锁的恢复。
显示使用行锁代码如下:
import  java.io.IOException;import  org.apache.hadoop.conf.Configuration;import  org.apache.hadoop.hbase.HBaseConfiguration;import  org.apache.hadoop.hbase.client.HTable;import  org.apache.hadoop.hbase.client.Put;import  org.apache.hadoop.hbase.client.RowLock;import  org.apache.hadoop.hbase.util.Bytes;public  class  HBaseRowLock {	private  final  static  byte [] ROW1 = Bytes.toBytes("row1" ); 	private  final  static  byte [] ROW2 = Bytes.toBytes("row2" ); 	private  final  static  byte [] COLFMA1 = Bytes.toBytes("colfam1" ); 	private  final  static  byte [] COLFMA2 = Bytes.toBytes("colfam2" ); 	private  final  static  byte [] QUAL1 = Bytes.toBytes("qual1" ); 	private  final  static  byte [] QUAL2 = Bytes.toBytes("qual2" ); 	private  static  byte [] COLFAM1; 	private  final  static  byte [] VAL1 = Bytes.toBytes("val1" ); 	private  final  static  byte [] VAL2 = Bytes.toBytes("val2" ); 	private  final  static  byte [] VAL3 = Bytes.toBytes("val3" ); 	static  class  UnlockedPut implements  Runnable { 		@Override 		public  void  run() { 			try  { 				Configuration conf = HBaseConfiguration.create(); 				HTable table = new  HTable(conf, "testtable" ); 				Put put = new  Put(ROW1); 				put.add(COLFAM1, QUAL1, VAL3); 				table.put(put); 				long  time = System.currentTimeMillis(); 				System.out.println ("Thread trying to put same rwo now" ); 				table.put(put); 				System.out.println ("Wait time:"  						+ (System.currentTimeMillis() - time) + "ms" ); 			} catch  (Exception e) { 				System.err.println ("Thread error :"  + e); 			} 			try  { 				Configuration conf = HBaseConfiguration.create(); 				HTable table = new  HTable(conf, "testtable" ); 				RowLock lock = table.lockRow(ROW1); 				System.out.println ("Lock ID:"  + lock.getLockId()); 				Put put1 = new  Put(ROW1, lock); 				put1.add(COLFAM1, QUAL1, VAL1); 				table.put(put1); 				Put put2 = new  Put(ROW1, lock); 				put2.add(COLFAM1, QUAL1, VAL2); 				table.put(put2); 			} catch  (IOException e) { 			} finally  { 			} 			System.out.println ("Takin out lock..." ); 			Thread thread = new  Thread(new  UnlockedPut()); 			thread.start(); 			try  { 				System.out.println ("Sleeping 5secs in main().." ); 				Thread.sleep(5000 ); 			} catch  (Exception e) { 				 			} 		} 	} } 
控制台输出如下:
Taking  out lock...Lock  ID : 4751274798057238718 Sleeping  5 secs in  main()...Thread  trying to put same row now...Releasing  lock..Wait  time: 5007 msAfter  thread ended...KV :row1/colfam1 :qual1/ 1300775520118 /Put /vlen=4 ,Value :val2 KV :row1/colfam1 :qual1/ 1300775520113 /Put /vlen=4 ,Value :val1 KV :row1/colfam1 :qual1/ 1300775520116 /Put /vlen=4 ,Value :val3 
主线程的锁一释放,阻塞线程的run()方法就继续执行并调用了第三个put。观察put操作在服务器端的执行情况,会觉得很有意思。KeyValue实例的时间戳显示了第三个put拥有的最小时间戳,虽然这个put表面上是最后执行的。这是因为线程中的put()调用是在两个主线程中的put()之前执行的,这之后主线程休眠了5秒。当put被发送到服务器时,如果它的时间戳没有被显式指定,服务器端会帮它设定时间戳,同时试图获得这一行的锁。但是示例代码中主线程已经获得了改行的锁,因此服务器端的处理一直等待了5秒多,锁被释放才得已继续。主线程中的两个put()调用的执行以及行的解锁只花费了7毫秒的时间。Get需要锁吗?