In http://www.aliyun.com/zixun/aggregation/13713.html ">hbase:the definitive Guide, Lars George introduced a new feature of HBase Counter Increment, which uses a column as a Counter, makes it easy to provide real-time statistical functionality for some online applications. (PS: such as the real-time browsing of posts: PV)
Traditionally, without counter, when we give a column a value of +1 or other values, we need to read the value from that column first, then modify the value on the client, and then write back to Region Server, a read-modify-write (RMW) Operation。 In this process, according to Lars's description 1, you also need to lock the row of the operation in advance, and then unlock it afterwards. This can cause many contention and many problems that come with it. The HBase increment interface ensures that a client request is done atomically at the Region server end.
As for the performance of increment, we only have to do tests to know. YCSB has provided the Read-modify-write test interface, and the increment interface needs to do 2 of its own.
Then create a new YCSB workload configuration file:
recordcount=12000
operationcount=12000000
Workload=com.yahoo.ycsb.workloads.coreworkload
Readallfields=false
Incrementproportion=1
Readproportion=0
Updateproportion=0
Scanproportion=0
Insertproportion=0
Requestdistribution=zipfan
recordcount=12000
operationcount=12000000
Workload=com.yahoo.ycsb.workloads.coreworkload
Readallfields=false
Readproportion=0
Updateproportion=0
Scanproportion=0
Insertproportion=0
Readmodifywriteproportion=1
Requestdistribution=zipfan
The test is carried out on the cluster: 1 master,6 units regionserver, independent zookeeper cluster, HDFS and HBase overlap at the bottom. Each Region Server is currently responsible for about 255 Region. YCSB on another machine, open 120 threads. The test results are as follows.
First look at the throughput:
The test diagram shows that the test time is basically long enough and that performance fluctuations are reflected. RMW Although the fluctuation is big, but overall performance is superior to Increment, this is quite unexpected thing. And Increment's performance is very stable. From the point of view of the box line diagram also consistent. Latency is similar.
Finally, the test results are simply analyzed. Unexpectedly, RMW did not imagine so bad, but the situation of the middle fluctuation is worth probing; the average latency of Increment is about 10ms, better than 15ms of RMW, and there is little performance fluctuation.
With a careful analysis of the code for YCSB's RMW operation, it simply encapsulates read () and update () 3:
Db.read (Table,keyname,fields, new HashMap < string,string > ());
Db.update (table,keyname,values);
It does not lock and unlock the row you are manipulating, it is simply a read rewrite. This is not acceptable in counter scenarios. Without locking in a large concurrency situation, it is easy to cause counter values to be inconsistent with expectations.
Continue to modify the YCSB, by initiating the requested client to lock the corresponding row 4. Then the performance comparison between Increment and RMW is performed.
What can be expected is that the performance of the new RMW will be very poor. Here is a fragment of the test result:
sec:15818 operations; 91.3 current ops/sec; [RMW averagelatency (ms) =2903.83]
210 sec:15818 operations; 0 current ops/sec;
sec:15818 operations; 0 current ops/sec;
230 sec:16880 operations; 106.2 current ops/sec; [RMW averagelatency (ms) =3136.13]
sec:16880 operations; 0 current ops/sec;
sec:16880 operations; 0 current ops/sec;
sec:17747 operations; 86.69 current ops/sec; [RMW averagelatency (ms) =4262.21]
270 sec:17747 operations; 0 current ops/sec;
280 sec:17747 operations; 0 current ops/sec;
290 sec:18412 operations; 66.5 current ops/sec; [RMW averagelatency (ms) =5508.39]
The key code to modify RMW here is:
Lock = _htable.lockrow (Bytes.tobytes (key));
r = _htable.get (g);
_htable.put (P);
_htable.unlockrow (lock);
That is, before reading before the lock, write after the lock. The previous RMW bottleneck was in the Read operation, and the put operation could be batched on the server side, where the introduction of the lock resulted in a contention spurt between threads. In other words, an increase in the number of threads does not necessarily lead to performance improvements, which may result in poor performance. We can do some testing on the number of threads (100s).
You can see that when the number of threads exceeds 16, the throughput is slightly worse, and worse, the latency is greatly improved. When the number of threads is set at 128, the situation becomes very bad: latency is basically a few seconds, or NA, and throughput can only stay around 200. This validates the previous idea.
So it is very important for HBase to introduce Increment/counter, which is "fatal" to some applications that require atomic change operations. In addition to the single Increment interface Incrementcolumnvalue (), there are batch increment interface increment (increment), which facilitates client invocation.
In addition, HBase is also in the development of coprocessor, so that the calculation directly on the Region Server, eliminating the tedious time-consuming data movement. (PS: This is called mobile computing is more cost-effective than moving data)
Tips: The above test data due to Hbase version is very old, plus the author hardware, cluster size limit, for reference only ~