HBase基础几个关键点——你能答出多少?

本文探讨了HBase中Region与Scan的rowkey范围特性,并分析了HTablePool的线程安全性。此外,还提供了HBase数据读取及批量写入的具体实现方式,并针对存在的问题进行了深入讨论。

1. Region的rowkey范围是开区间还是闭区间?描述一下

2. Scan的rowkey范围是开区间还是闭区间?描述一下

3. HTablePool线程安全么?如果线程安全,为什么?如果线程不安全,有什么影响?

4. 下面的代码有没有问题

public List<Message> getData(Date start, Dateend, Long to)

throws IOException {

HTableInterfacetable = tablePool.getTable(tableName);

List<Message>ret = null;

byte[] bytesTo = Bytes.toBytes(to);

byte[] startRow = Bytes.add(bytesTo,Bytes.toBytes(start.getTime()));

byte[] endRow = Bytes.add(bytesTo, Bytes.toBytes(end.getTime()));

byte[] family = "f".getBytes();

Scanscan = new Scan();

scan.setStartRow(startRow);

scan.setStopRow(endRow);

scan.setCaching(200);

scan.addFamily(family);

ResultScannerrs = null;

try {

rs= table.getScanner(scan);

Resultresult = rs.next();

while (result != null) {

if (ret == null) {

ret= new ArrayList<Message>();

}

Messagemsg = new Message();

msg.setTo(to);

long id = Bytes.toLong(result.getValue(family,"id".getBytes()));

long from = Bytes.toLong(result.getValue(family, "from".getBytes()));

Stringmessage = Bytes.toString(result.getValue(family,

"msg".getBytes()));

long time = Bytes.toLong(Arrays.copyOfRange(result.getRow(),8,

16));

msg.setId(id);

msg.setFrom(from);

msg.setMessage(message);

msg.setTime(new Date(time));

ret.add(msg);

result.close();

result= rs.next();

}

}finally {

table.close(); // important

}

return ret;

}

5. 请优化:

publicList<Put> getPut(String row, String… values) {

List<Put> puts = new ArrayList<Put>(values.length);

for(String value : values) {

Put put = new Put(row.getBytes());

put.add("family".getBytes(),"from".getBytes(), Bytes.toBytes(value));

puts.add(put);

}

return puts;

}

6. scan.setBatch(1)和scan.setCaching(2)的区别

7. 判断

a)put(List<Put> puts)比put(Put put)效率高。

b)HBase的底层是HDFS,有多副本,所以HBase不会丢失数据。

c)写数据一定将自动flush设置为true以提高性能。

d)如果我要存30天的数据,但列都一样,那我可以用30个version来保存。

e)为了提升处理能力,我们应该把一批Put,分成多线程put到HBase集群

f)变长字段组合成rowkey的时候,将字段之间用#隔开就可以了。

g)一个Put对应于一个KeyValue。

h)HBase中建两张表不如建两个family。

i)假设pool是HTablePool对象,可以HTable table=(HTable) pool.get(“table”)。

j)使用HTablePool缓存的table(HTableInterface对象),将autoFlush设置为false的时候,用table.close就会自动flushCommits()。

k)一批Put最多需要当前表的region个数个RPC请求

l)HTablePool实现了网络连接的复用。

<think>嗯,用户这次的问题聚焦在Redis和HBase的缓存一致性设计上,看来是在构建大数据平台时遇到了具体的技术选型问题。从用户引用的资料来看,ta已经做了不少功课,对双删、canal等方案都有了解,但需要更落地的架构设计。 用户可能正在面临这样的困境:HBase作为海量存储响应慢,引入Redis缓存后又担心数据不一致。尤其在大数据场景下,写入频率高、数据量大,简单的双删策略可能不够用。ta真正需要的是能平衡性能与一致性的工业级方案。 从技术角度看,这个问题可以拆解为几个层面: 首先是策略选择,用户引用中提到的"先更新数据库再删缓存"是基础,但需要强化异常处理;其次是同步机制,canal监听HBase日志是个优雅方案,但用户可能担心延迟;最后是工程细节,比如如何避免大Key、网络分区时的处理等。 特别要注意用户提到的PB级数据场景,这意味着方案必须考虑内存成本。在回复中需要强调冷热分离——只有高频访问的数据才进Redis,避免全量同步。另外HBase本身有版本控制特性,这点可以巧妙利用,通过时间戳解决并发冲突。 用户引用的资料[^2]提到canal适合最终一致性场景,这点很关键。如果ta的业务需要强一致(比如金融交易),就必须引入分布式锁,但会牺牲性能。这个权衡点需要明确告知用户。 最后准备用架构图展示数据流向,这样更直观。典型方案是:HBase写操作 → canal捕获变更 → Redis删除/更新。对于高并发场景,加入消息队列做缓冲会更稳健。</think>设计 Redis 与 HBase 的缓存一致性同步机制需根据业务场景在**性能**和**一致性强度**间平衡。以下是分层策略方案: --- ### 一、核心同步策略(按一致性强度排序) #### 1. **最终一致性方案(推荐通用场景)** ```mermaid graph LR A[写请求] --> B[更新 HBase 数据] B --> C{同步策略} C -->|策略1| D[发送变更事件到 Kafka] C -->|策略2| E[通过 Canal 监听 HBase WAL] D/E --> F[消费者删除 Redis 对应 Key] F --> G[后续读请求回填新数据] ``` - **技术组合**: - **Canal 监听 HBase WAL**:实时捕获 HBase 数据变更,推送至 Kafka[^2] - **异步删除缓存**:消费者消费 Kafka 消息,执行 `DEL key` - **优势**: - 对业务代码零侵入 - 支持批量变更合并(减少 Redis 压力) - **时延**:百毫秒级(满足 99% 场景)[^2] #### 2. **强一致性方案(金融/交易场景)** ```mermaid graph TD A[写请求] --> B[获取分布式锁] B --> C[更新 HBase 数据] C --> D[删除 Redis 缓存] D --> E[释放锁] F[读请求] -->|缓存不存在| G[获取锁后查HBase并回填] ``` - **关键技术**: - **RedLock 分布式锁**:确保更新与删缓存原子性 - **双重检查**:回填缓存前二次验证 - **代价**:性能下降 30%-50%(锁竞争开销)[^1] #### 3. **折中方案:延时双删** ```python def update_hbase_with_delay_delete(key, data): # 第一次删除(快速失效旧缓存) redis.delete(key) # 更新数据库 hbase.put(key, data) # 异步延时二次删除 threading.Timer(1.0, lambda: redis.delete(key)).start() # 延迟1秒 ``` - **适用场景**: 高并发写且无法引入分布式锁时 - **关键参数**: - 延迟时间 = 主从复制延迟 + 业务处理耗时(通常 0.5-2秒)[^4] --- ### 二、异常场景处理机制 | 风险 | 解决方案 | |---------------------|--------------------------------------------------------------------------| | **删除缓存失败** | 消息重试 + 死信队列告警,最终回滚 HBase 事务[^1] | | **缓存穿透** | 空值缓存:`SET key_null "" EX 60` | | **缓存雪崩** | 差异化 TTL:`TTL = base_time + random(0, 300)` | | **并发回填旧数据** | 写锁 + 版本号校验(HBase 的 `timestamp` 作为版本写入 Redis) | --- ### 三、推荐技术栈组合 | 场景 | 技术组合 | 一致性级别 | |-----------------------|--------------------------------------------------------------------------|---------------| | **实时数仓** | HBase + Canal → Kafka → Spark Streaming → Redis | 秒级最终一致 | | **用户画像查询** | HBase + Redisson 分布式锁 | 强一致 | | **高并发日志分析** | HBase + 延时双删 + 布隆过滤器(防穿透) | 毫秒级最终一致 | --- ### 四、性能优化技巧 1. **批量处理** Canal 聚合 10ms 内的 HBase 变更,批量删除 Redis Key(减少网络开销) 2. **冷热分离** ```sql -- HBase 设计:热数据列族存 Redis 地址 CREATE 'user_profile', {NAME => 'hot_data', VERSIONS => 1}, {NAME => 'cold_data'} ``` 3. **内存控制** - Redis 仅缓存热点数据(通过 `LFU` 淘汰策略) - 大 Value 拆分:HBase 的 RowKey 拆解为 Redis Hash 字段 > **黄金法则**: > - 读多写少 → **最终一致性**(Canal+Kafka 方案) > - 写密集且需强一致 → **分布式锁**(性能损失换安全) > - 超高并发写入 → **延时双删 + 版本号**(平衡点方案)[^3][^4] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值