1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.io.hfile;
19
20 import java.io.IOException;
21 import java.lang.management.ManagementFactory;
22 import java.lang.management.MemoryUsage;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hadoop.classification.InterfaceAudience;
27 import org.apache.hadoop.conf.Configuration;
28 import org.apache.hadoop.hbase.HColumnDescriptor;
29 import org.apache.hadoop.hbase.HConstants;
30 import org.apache.hadoop.hbase.io.hfile.BlockType.BlockCategory;
31 import org.apache.hadoop.hbase.io.hfile.bucket.BucketCache;
32 import org.apache.hadoop.hbase.regionserver.StoreFile;
33 import org.apache.hadoop.hbase.util.DirectMemoryUtils;
34 import org.apache.hadoop.util.StringUtils;
35
36
37
38
39 @InterfaceAudience.Private
40 public class CacheConfig {
41 private static final Log LOG = LogFactory.getLog(CacheConfig.class.getName());
42
43
44
45
46
47 public static final String CACHE_BLOCKS_ON_WRITE_KEY =
48 "hbase.rs.cacheblocksonwrite";
49
50
51
52
53
54 public static final String CACHE_INDEX_BLOCKS_ON_WRITE_KEY =
55 "hfile.block.index.cacheonwrite";
56
57
58
59
60 public static final String CACHE_BLOOM_BLOCKS_ON_WRITE_KEY =
61 "hfile.block.bloom.cacheonwrite";
62
63
64
65
66
67 public static final String CACHE_DATA_BLOCKS_COMPRESSED_KEY =
68 "hbase.rs.blockcache.cachedatacompressed";
69
70
71
72
73
74 public static final String EVICT_BLOCKS_ON_CLOSE_KEY =
75 "hbase.rs.evictblocksonclose";
76
77
78
79
80 public static final String BUCKET_CACHE_IOENGINE_KEY = "hbase.bucketcache.ioengine";
81 public static final String BUCKET_CACHE_SIZE_KEY = "hbase.bucketcache.size";
82 public static final String BUCKET_CACHE_PERSISTENT_PATH_KEY =
83 "hbase.bucketcache.persistent.path";
84 public static final String BUCKET_CACHE_COMBINED_KEY =
85 "hbase.bucketcache.combinedcache.enabled";
86 public static final String BUCKET_CACHE_COMBINED_PERCENTAGE_KEY =
87 "hbase.bucketcache.percentage.in.combinedcache";
88 public static final String BUCKET_CACHE_WRITER_THREADS_KEY = "hbase.bucketcache.writer.threads";
89 public static final String BUCKET_CACHE_WRITER_QUEUE_KEY =
90 "hbase.bucketcache.writer.queuelength";
91
92
93
94 public static final boolean DEFAULT_BUCKET_CACHE_COMBINED = true;
95 public static final int DEFAULT_BUCKET_CACHE_WRITER_THREADS = 3;
96 public static final int DEFAULT_BUCKET_CACHE_WRITER_QUEUE = 64;
97 public static final float DEFAULT_BUCKET_CACHE_COMBINED_PERCENTAGE = 0.9f;
98
99
100
101 public static final boolean DEFAULT_CACHE_DATA_ON_READ = true;
102 public static final boolean DEFAULT_CACHE_DATA_ON_WRITE = false;
103 public static final boolean DEFAULT_IN_MEMORY = false;
104 public static final boolean DEFAULT_CACHE_INDEXES_ON_WRITE = false;
105 public static final boolean DEFAULT_CACHE_BLOOMS_ON_WRITE = false;
106 public static final boolean DEFAULT_EVICT_ON_CLOSE = false;
107 public static final boolean DEFAULT_COMPRESSED_CACHE = false;
108
109
110 private final BlockCache blockCache;
111
112
113
114
115
116 private boolean cacheDataOnRead;
117
118
119 private final boolean inMemory;
120
121
122 private boolean cacheDataOnWrite;
123
124
125 private final boolean cacheIndexesOnWrite;
126
127
128 private final boolean cacheBloomsOnWrite;
129
130
131 private boolean evictOnClose;
132
133
134 private final boolean cacheCompressed;
135
136
137
138
139
140
141
142 public CacheConfig(Configuration conf, HColumnDescriptor family) {
143 this(CacheConfig.instantiateBlockCache(conf),
144 family.isBlockCacheEnabled(),
145 family.isInMemory(),
146
147
148 conf.getBoolean(CACHE_BLOCKS_ON_WRITE_KEY,
149 DEFAULT_CACHE_DATA_ON_WRITE) || family.shouldCacheDataOnWrite(),
150 conf.getBoolean(CACHE_INDEX_BLOCKS_ON_WRITE_KEY,
151 DEFAULT_CACHE_INDEXES_ON_WRITE) || family.shouldCacheIndexesOnWrite(),
152 conf.getBoolean(CACHE_BLOOM_BLOCKS_ON_WRITE_KEY,
153 DEFAULT_CACHE_BLOOMS_ON_WRITE) || family.shouldCacheBloomsOnWrite(),
154 conf.getBoolean(EVICT_BLOCKS_ON_CLOSE_KEY,
155 DEFAULT_EVICT_ON_CLOSE) || family.shouldEvictBlocksOnClose(),
156 conf.getBoolean(CACHE_DATA_BLOCKS_COMPRESSED_KEY, DEFAULT_COMPRESSED_CACHE)
157 );
158 }
159
160
161
162
163
164
165 public CacheConfig(Configuration conf) {
166 this(CacheConfig.instantiateBlockCache(conf),
167 DEFAULT_CACHE_DATA_ON_READ,
168 DEFAULT_IN_MEMORY,
169
170 conf.getBoolean(CACHE_BLOCKS_ON_WRITE_KEY, DEFAULT_CACHE_DATA_ON_WRITE),
171 conf.getBoolean(CACHE_INDEX_BLOCKS_ON_WRITE_KEY,
172 DEFAULT_CACHE_INDEXES_ON_WRITE),
173 conf.getBoolean(CACHE_BLOOM_BLOCKS_ON_WRITE_KEY,
174 DEFAULT_CACHE_BLOOMS_ON_WRITE),
175 conf.getBoolean(EVICT_BLOCKS_ON_CLOSE_KEY, DEFAULT_EVICT_ON_CLOSE),
176 conf.getBoolean(CACHE_DATA_BLOCKS_COMPRESSED_KEY,
177 DEFAULT_COMPRESSED_CACHE)
178 );
179 }
180
181
182
183
184
185
186
187
188
189
190
191
192
193 CacheConfig(final BlockCache blockCache,
194 final boolean cacheDataOnRead, final boolean inMemory,
195 final boolean cacheDataOnWrite, final boolean cacheIndexesOnWrite,
196 final boolean cacheBloomsOnWrite, final boolean evictOnClose,
197 final boolean cacheCompressed) {
198 this.blockCache = blockCache;
199 this.cacheDataOnRead = cacheDataOnRead;
200 this.inMemory = inMemory;
201 this.cacheDataOnWrite = cacheDataOnWrite;
202 this.cacheIndexesOnWrite = cacheIndexesOnWrite;
203 this.cacheBloomsOnWrite = cacheBloomsOnWrite;
204 this.evictOnClose = evictOnClose;
205 this.cacheCompressed = cacheCompressed;
206 }
207
208
209
210
211
212 public CacheConfig(CacheConfig cacheConf) {
213 this(cacheConf.blockCache, cacheConf.cacheDataOnRead, cacheConf.inMemory,
214 cacheConf.cacheDataOnWrite, cacheConf.cacheIndexesOnWrite,
215 cacheConf.cacheBloomsOnWrite, cacheConf.evictOnClose,
216 cacheConf.cacheCompressed);
217 }
218
219
220
221
222 public boolean isBlockCacheEnabled() {
223 return this.blockCache != null;
224 }
225
226
227
228
229
230 public BlockCache getBlockCache() {
231 return this.blockCache;
232 }
233
234
235
236
237
238 public boolean shouldCacheDataOnRead() {
239 return isBlockCacheEnabled() && cacheDataOnRead;
240 }
241
242
243
244
245
246
247 public boolean shouldCacheBlockOnRead(BlockCategory category) {
248 boolean shouldCache = isBlockCacheEnabled()
249 && (cacheDataOnRead ||
250 category == BlockCategory.INDEX ||
251 category == BlockCategory.BLOOM);
252 return shouldCache;
253 }
254
255
256
257
258 public boolean isInMemory() {
259 return isBlockCacheEnabled() && this.inMemory;
260 }
261
262
263
264
265
266 public boolean shouldCacheDataOnWrite() {
267 return isBlockCacheEnabled() && this.cacheDataOnWrite;
268 }
269
270
271
272
273
274
275 public void setCacheDataOnWrite(boolean cacheDataOnWrite) {
276 this.cacheDataOnWrite = cacheDataOnWrite;
277 }
278
279
280
281
282
283 public boolean shouldCacheIndexesOnWrite() {
284 return isBlockCacheEnabled() && this.cacheIndexesOnWrite;
285 }
286
287
288
289
290
291 public boolean shouldCacheBloomsOnWrite() {
292 return isBlockCacheEnabled() && this.cacheBloomsOnWrite;
293 }
294
295
296
297
298
299 public boolean shouldEvictOnClose() {
300 return isBlockCacheEnabled() && this.evictOnClose;
301 }
302
303
304
305
306
307
308 public void setEvictOnClose(boolean evictOnClose) {
309 this.evictOnClose = evictOnClose;
310 }
311
312
313
314
315 public boolean shouldCacheCompressed() {
316 return isBlockCacheEnabled() && this.cacheCompressed;
317 }
318
319 @Override
320 public String toString() {
321 if (!isBlockCacheEnabled()) {
322 return "CacheConfig:disabled";
323 }
324 return "CacheConfig:enabled " +
325 "[cacheDataOnRead=" + shouldCacheDataOnRead() + "] " +
326 "[cacheDataOnWrite=" + shouldCacheDataOnWrite() + "] " +
327 "[cacheIndexesOnWrite=" + shouldCacheIndexesOnWrite() + "] " +
328 "[cacheBloomsOnWrite=" + shouldCacheBloomsOnWrite() + "] " +
329 "[cacheEvictOnClose=" + shouldEvictOnClose() + "] " +
330 "[cacheCompressed=" + shouldCacheCompressed() + "]";
331 }
332
333
334
335
336
337
338
339 private static BlockCache globalBlockCache;
340
341
342 private static boolean blockCacheDisabled = false;
343
344
345
346
347
348
349
350 private static synchronized BlockCache instantiateBlockCache(
351 Configuration conf) {
352 if (globalBlockCache != null) return globalBlockCache;
353 if (blockCacheDisabled) return null;
354
355 float cachePercentage = conf.getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY,
356 HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT);
357 if (cachePercentage == 0L) {
358 blockCacheDisabled = true;
359 return null;
360 }
361 if (cachePercentage > 1.0) {
362 throw new IllegalArgumentException(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY +
363 " must be between 0.0 and 1.0, and not > 1.0");
364 }
365
366
367 MemoryUsage mu = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
368 long lruCacheSize = (long) (mu.getMax() * cachePercentage);
369 int blockSize = conf.getInt("hbase.offheapcache.minblocksize",
370 HConstants.DEFAULT_BLOCKSIZE);
371 long offHeapCacheSize =
372 (long) (conf.getFloat("hbase.offheapcache.percentage", (float) 0) *
373 DirectMemoryUtils.getDirectMemorySize());
374 if (offHeapCacheSize <= 0) {
375 String bucketCacheIOEngineName = conf
376 .get(BUCKET_CACHE_IOENGINE_KEY, null);
377 float bucketCachePercentage = conf.getFloat(BUCKET_CACHE_SIZE_KEY, 0F);
378
379 long bucketCacheSize = (long) (bucketCachePercentage < 1 ? mu.getMax()
380 * bucketCachePercentage : bucketCachePercentage * 1024 * 1024);
381
382 boolean combinedWithLru = conf.getBoolean(BUCKET_CACHE_COMBINED_KEY,
383 DEFAULT_BUCKET_CACHE_COMBINED);
384 BucketCache bucketCache = null;
385 if (bucketCacheIOEngineName != null && bucketCacheSize > 0) {
386 int writerThreads = conf.getInt(BUCKET_CACHE_WRITER_THREADS_KEY,
387 DEFAULT_BUCKET_CACHE_WRITER_THREADS);
388 int writerQueueLen = conf.getInt(BUCKET_CACHE_WRITER_QUEUE_KEY,
389 DEFAULT_BUCKET_CACHE_WRITER_QUEUE);
390 String persistentPath = conf.get(BUCKET_CACHE_PERSISTENT_PATH_KEY);
391 float combinedPercentage = conf.getFloat(
392 BUCKET_CACHE_COMBINED_PERCENTAGE_KEY,
393 DEFAULT_BUCKET_CACHE_COMBINED_PERCENTAGE);
394 if (combinedWithLru) {
395 lruCacheSize = (long) ((1 - combinedPercentage) * bucketCacheSize);
396 bucketCacheSize = (long) (combinedPercentage * bucketCacheSize);
397 }
398 try {
399 int ioErrorsTolerationDuration = conf.getInt(
400 "hbase.bucketcache.ioengine.errors.tolerated.duration",
401 BucketCache.DEFAULT_ERROR_TOLERATION_DURATION);
402 bucketCache = new BucketCache(bucketCacheIOEngineName,
403 bucketCacheSize, writerThreads, writerQueueLen, persistentPath,
404 ioErrorsTolerationDuration);
405 } catch (IOException ioex) {
406 LOG.error("Can't instantiate bucket cache", ioex);
407 throw new RuntimeException(ioex);
408 }
409 }
410 LOG.info("Allocating LruBlockCache with maximum size "
411 + StringUtils.humanReadableInt(lruCacheSize));
412 LruBlockCache lruCache = new LruBlockCache(lruCacheSize,
413 StoreFile.DEFAULT_BLOCKSIZE_SMALL);
414 lruCache.setVictimCache(bucketCache);
415 if (bucketCache != null && combinedWithLru) {
416 globalBlockCache = new CombinedBlockCache(lruCache, bucketCache);
417 } else {
418 globalBlockCache = lruCache;
419 }
420 } else {
421 globalBlockCache = new DoubleBlockCache(lruCacheSize, offHeapCacheSize,
422 StoreFile.DEFAULT_BLOCKSIZE_SMALL, blockSize, conf);
423 }
424 return globalBlockCache;
425 }
426 }