001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.regionserver.regionreplication; 019 020import static org.junit.jupiter.api.Assertions.assertNotNull; 021import static org.junit.jupiter.api.Assertions.assertTrue; 022 023import java.io.IOException; 024import java.util.Arrays; 025import java.util.List; 026import org.apache.hadoop.conf.Configuration; 027import org.apache.hadoop.hbase.HBaseTestingUtil; 028import org.apache.hadoop.hbase.StartTestingClusterOption; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 031import org.apache.hadoop.hbase.client.Consistency; 032import org.apache.hadoop.hbase.client.Durability; 033import org.apache.hadoop.hbase.client.Get; 034import org.apache.hadoop.hbase.client.Mutation; 035import org.apache.hadoop.hbase.client.Put; 036import org.apache.hadoop.hbase.client.RegionReplicaUtil; 037import org.apache.hadoop.hbase.client.Result; 038import org.apache.hadoop.hbase.client.Table; 039import org.apache.hadoop.hbase.client.TableDescriptor; 040import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 041import org.apache.hadoop.hbase.regionserver.HRegion; 042import org.apache.hadoop.hbase.regionserver.HRegionServer; 043import org.apache.hadoop.hbase.regionserver.Region; 044import org.apache.hadoop.hbase.testclassification.LargeTests; 045import org.apache.hadoop.hbase.testclassification.RegionServerTests; 046import org.apache.hadoop.hbase.util.Bytes; 047import org.apache.hadoop.hbase.util.ServerRegionReplicaUtil; 048import org.junit.jupiter.api.AfterAll; 049import org.junit.jupiter.api.BeforeAll; 050import org.junit.jupiter.api.Tag; 051import org.junit.jupiter.api.Test; 052 053@Tag(RegionServerTests.TAG) 054@Tag(LargeTests.TAG) 055public class TestRegionReplicationForSkipWAL { 056 057 private static final byte[] FAM1 = Bytes.toBytes("family_test1"); 058 059 private static final byte[] QUAL1 = Bytes.toBytes("qualifier_test1"); 060 061 private static final byte[] FAM2 = Bytes.toBytes("family_test2"); 062 063 private static final byte[] QUAL2 = Bytes.toBytes("qualifier_test2"); 064 065 private static final byte[] FAM3 = Bytes.toBytes("family_test3"); 066 067 private static final byte[] QUAL3 = Bytes.toBytes("qualifier_test3"); 068 069 private static final byte[] FAM4 = Bytes.toBytes("family_test4"); 070 071 private static final byte[] QUAL4 = Bytes.toBytes("qualifier_test4"); 072 073 private static final byte[] FAM5 = Bytes.toBytes("family_test5"); 074 075 private static final byte[] QUAL5 = Bytes.toBytes("qualifier_test5"); 076 077 private static final byte[] FAM6 = Bytes.toBytes("family_test6"); 078 079 private static final byte[] QUAL6 = Bytes.toBytes("qualifier_test6"); 080 081 private static final HBaseTestingUtil HTU = new HBaseTestingUtil(); 082 private static final int NB_SERVERS = 2; 083 084 private static final String strTableName = "TestRegionReplicationForSkipWAL"; 085 086 @BeforeAll 087 public static void setUp() throws Exception { 088 Configuration conf = HTU.getConfiguration(); 089 conf.setBoolean(ServerRegionReplicaUtil.REGION_REPLICA_REPLICATION_CONF_KEY, true); 090 conf.setBoolean(RegionReplicaUtil.REGION_REPLICA_WAIT_FOR_PRIMARY_FLUSH_CONF_KEY, false); 091 HTU.startMiniCluster(StartTestingClusterOption.builder().numRegionServers(NB_SERVERS).build()); 092 } 093 094 @AfterAll 095 public static void tearDown() throws Exception { 096 HTU.shutdownMiniCluster(); 097 } 098 099 /** 100 * This test is for HBASE-26933,make the new region replication framework introduced by 101 * HBASE-26233 work for table which DURABILITY is Durability.SKIP_WAL. 102 */ 103 @Test 104 public void testReplicateToReplicaWhenSkipWAL() throws Exception { 105 final HRegion[] skipWALRegions = this.createTable(true); 106 byte[] rowKey1 = Bytes.toBytes(1); 107 byte[] value1 = Bytes.toBytes(2); 108 109 byte[] rowKey2 = Bytes.toBytes(2); 110 byte[] value2 = Bytes.toBytes(4); 111 112 // Test the table is skipWAL 113 skipWALRegions[0].batchMutate(new Mutation[] { new Put(rowKey1).addColumn(FAM1, QUAL1, value1), 114 new Put(rowKey2).addColumn(FAM2, QUAL2, value2) }); 115 116 try (Table skipWALTable = HTU.getConnection().getTable(getTableName(true))) { 117 HTU.waitFor(30000, () -> checkReplica(skipWALTable, FAM1, QUAL1, rowKey1, value1) 118 && checkReplica(skipWALTable, FAM2, QUAL2, rowKey2, value2)); 119 } 120 121 byte[] rowKey3 = Bytes.toBytes(3); 122 byte[] value3 = Bytes.toBytes(6); 123 byte[] rowKey4 = Bytes.toBytes(4); 124 byte[] value4 = Bytes.toBytes(8); 125 byte[] rowKey5 = Bytes.toBytes(5); 126 byte[] value5 = Bytes.toBytes(10); 127 byte[] rowKey6 = Bytes.toBytes(6); 128 byte[] value6 = Bytes.toBytes(12); 129 130 // Test the table is normal,but the Put is skipWAL 131 final HRegion[] normalRegions = this.createTable(false); 132 normalRegions[0].batchMutate(new Mutation[] { new Put(rowKey3).addColumn(FAM3, QUAL3, value3), 133 new Put(rowKey4).addColumn(FAM4, QUAL4, value4).setDurability(Durability.SKIP_WAL), 134 new Put(rowKey5).addColumn(FAM5, QUAL5, value5).setDurability(Durability.SKIP_WAL), 135 new Put(rowKey6).addColumn(FAM6, QUAL6, value6) }); 136 137 try (Table normalTable = HTU.getConnection().getTable(getTableName(false))) { 138 HTU.waitFor(30000, 139 () -> checkReplica(normalTable, FAM3, QUAL3, rowKey3, value3) 140 && checkReplica(normalTable, FAM4, QUAL4, rowKey4, value4) 141 && checkReplica(normalTable, FAM5, QUAL5, rowKey5, value5) 142 && checkReplica(normalTable, FAM6, QUAL6, rowKey6, value6)); 143 } 144 } 145 146 private static boolean checkReplica(Table table, byte[] fam, byte[] qual, byte[] rowKey, 147 byte[] expectValue) throws IOException { 148 Get get = new Get(rowKey).setConsistency(Consistency.TIMELINE).setReplicaId(1); 149 Result result = table.get(get); 150 byte[] value = result.getValue(fam, qual); 151 return value != null && value.length > 0 && Arrays.equals(expectValue, value); 152 } 153 154 private TableName getTableName(boolean skipWAL) { 155 return TableName.valueOf(strTableName + (skipWAL ? "_skipWAL" : "")); 156 } 157 158 private HRegion[] createTable(boolean skipWAL) throws Exception { 159 TableName tableName = getTableName(skipWAL); 160 TableDescriptorBuilder builder = 161 TableDescriptorBuilder.newBuilder(tableName).setRegionReplication(NB_SERVERS) 162 .setColumnFamilies(Arrays.asList(ColumnFamilyDescriptorBuilder.of(FAM1), 163 ColumnFamilyDescriptorBuilder.of(FAM2), ColumnFamilyDescriptorBuilder.of(FAM3), 164 ColumnFamilyDescriptorBuilder.of(FAM4), ColumnFamilyDescriptorBuilder.of(FAM5), 165 ColumnFamilyDescriptorBuilder.of(FAM6))); 166 if (skipWAL) { 167 builder.setDurability(Durability.SKIP_WAL); 168 169 } 170 TableDescriptor tableDescriptor = builder.build(); 171 172 HTU.getAdmin().createTable(tableDescriptor); 173 final HRegion[] regions = new HRegion[NB_SERVERS]; 174 for (int i = 0; i < NB_SERVERS; i++) { 175 HRegionServer rs = HTU.getMiniHBaseCluster().getRegionServer(i); 176 List<HRegion> onlineRegions = rs.getRegions(tableName); 177 for (HRegion region : onlineRegions) { 178 int replicaId = region.getRegionInfo().getReplicaId(); 179 assertTrue(regions[replicaId] == null); 180 regions[region.getRegionInfo().getReplicaId()] = region; 181 } 182 } 183 for (Region region : regions) { 184 assertNotNull(region); 185 } 186 return regions; 187 } 188}