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(Configuration conf) {
351 if (globalBlockCache != null) return globalBlockCache;
352 if (blockCacheDisabled) return null;
353
354 float cachePercentage = conf.getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY,
355 HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT);
356 if (cachePercentage == 0L) {
357 blockCacheDisabled = true;
358 return null;
359 }
360 if (cachePercentage > 1.0) {
361 throw new IllegalArgumentException(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY +
362 " must be between 0.0 and 1.0, and not > 1.0");
363 }
364
365
366 MemoryUsage mu = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
367 long lruCacheSize = (long) (mu.getMax() * cachePercentage);
368 int blockSize = conf.getInt("hbase.offheapcache.minblocksize", HConstants.DEFAULT_BLOCKSIZE);
369 long offHeapCacheSize =
370 (long) (conf.getFloat("hbase.offheapcache.percentage", (float) 0) *
371 DirectMemoryUtils.getDirectMemorySize());
372 if (offHeapCacheSize <= 0) {
373 String bucketCacheIOEngineName = conf.get(BUCKET_CACHE_IOENGINE_KEY, null);
374 float bucketCachePercentage = conf.getFloat(BUCKET_CACHE_SIZE_KEY, 0F);
375
376 long bucketCacheSize = (long) (bucketCachePercentage < 1 ? mu.getMax()
377 * bucketCachePercentage : bucketCachePercentage * 1024 * 1024);
378
379 boolean combinedWithLru = conf.getBoolean(BUCKET_CACHE_COMBINED_KEY,
380 DEFAULT_BUCKET_CACHE_COMBINED);
381 BucketCache bucketCache = null;
382 if (bucketCacheIOEngineName != null && bucketCacheSize > 0) {
383 int writerThreads = conf.getInt(BUCKET_CACHE_WRITER_THREADS_KEY,
384 DEFAULT_BUCKET_CACHE_WRITER_THREADS);
385 int writerQueueLen = conf.getInt(BUCKET_CACHE_WRITER_QUEUE_KEY,
386 DEFAULT_BUCKET_CACHE_WRITER_QUEUE);
387 String persistentPath = conf.get(BUCKET_CACHE_PERSISTENT_PATH_KEY);
388 float combinedPercentage = conf.getFloat(
389 BUCKET_CACHE_COMBINED_PERCENTAGE_KEY,
390 DEFAULT_BUCKET_CACHE_COMBINED_PERCENTAGE);
391 if (combinedWithLru) {
392 lruCacheSize = (long) ((1 - combinedPercentage) * bucketCacheSize);
393 bucketCacheSize = (long) (combinedPercentage * bucketCacheSize);
394 }
395 try {
396 int ioErrorsTolerationDuration = conf.getInt(
397 "hbase.bucketcache.ioengine.errors.tolerated.duration",
398 BucketCache.DEFAULT_ERROR_TOLERATION_DURATION);
399 bucketCache = new BucketCache(bucketCacheIOEngineName,
400 bucketCacheSize, writerThreads, writerQueueLen, persistentPath,
401 ioErrorsTolerationDuration);
402 } catch (IOException ioex) {
403 LOG.error("Can't instantiate bucket cache", ioex);
404 throw new RuntimeException(ioex);
405 }
406 }
407 LOG.info("Allocating LruBlockCache with maximum size " +
408 StringUtils.humanReadableInt(lruCacheSize));
409 LruBlockCache lruCache = new LruBlockCache(lruCacheSize, StoreFile.DEFAULT_BLOCKSIZE_SMALL);
410 lruCache.setVictimCache(bucketCache);
411 if (bucketCache != null && combinedWithLru) {
412 globalBlockCache = new CombinedBlockCache(lruCache, bucketCache);
413 } else {
414 globalBlockCache = lruCache;
415 }
416 } else {
417 globalBlockCache = new DoubleBlockCache(lruCacheSize, offHeapCacheSize,
418 StoreFile.DEFAULT_BLOCKSIZE_SMALL, blockSize, conf);
419 }
420 return globalBlockCache;
421 }
422 }