1引言
1.1目的与范围
改造Sqoop,实现mysql与Phoenix的数据同步
1.2术语与缩写
无
1.3参考资料
Sqoop官方文档, http://sqoop.apache.org/docs/1.4.6/
Phoenix官方文档: http://phoenix.apache.org/
2项目概况
2.1需求概述
需要利用sqoop将mysql中的数据, 同步到phoenix.
但是, 由于sqoop并不支持将数据直接同步到phoenix中,
因此, 需要自定义开发.
3系统结构
无
3.1设计方法
Sqoop提供了直接将mysql中数据导入到hbase中的工具,
而phoenix是基于hbase的, 可以通过重写hbase的put转换类来实现.
3.2子系统规划
无
4 系统详细设计
4.1 Mysql, 同phoenix数据同步设计
4.1.1 数据同步设计
4.1.1.1 表示层设计
无
4.1.1.2 类设计
4.1.1.2.1 总体类图
自定义ToPhoenixPutTransformer类, 继承自PutTransformer类(sqoop中的类).
4.1.1.2.2 类说明ToPhoenixPutTransformer
概述
将mysql中的数据转换为phoenix类型的Put对象属性
属性 | 属性名 | 类型 | 说明 |
---|---|---|---|
LOG | 日志记录器 | Log | 记录日志 |
serializedFieldNames | 已经序列化属性 | Map | 保存已经处理的字段 |
- 方法
方法getFieldNameBytes - 说明:
获得属性名称的字节数组。 方法原型:
private byte[] getFieldNameBytes(String fieldName) ;
输入参数:
变量 | 变量名 | 类型 | 说明 |
---|---|---|---|
fieldName | 属性名 | String |
- 返回值:
类型 | 说明 |
---|---|
Byte[] | 返回字符串对应的字节数组 |
方法
getPutCommand说明:
将mysql中的数据转换为Put对象列表。- 方法原型:
public List getPutCommand(Map
4.1.1.3时序图
4.1.1.4详细代码
class ToPhoenixPutTransformer extends PutTransformer {
public static final Log LOG = LogFactory.getLog(ToBytesPutTransformer.class
.getName());
// A mapping from field name -> bytes for that field name.
// Used to cache serialization work done for fields names.
private Map<String, byte[]> serializedFieldNames;
public ToBytesPutTransformer() {
serializedFieldNames = new TreeMap<String, byte[]>();
}
/**
* Return the serialized bytes for a field name, using the cache if it's
* already in there.
*/
private byte[] getFieldNameBytes(String fieldName) {
byte[] cachedName = serializedFieldNames.get(fieldName);
if (null != cachedName) {
// Cache hit. We're done.
return cachedName;
}
// Do the serialization and memoize the result.
byte[] nameBytes = Bytes.toBytes(fieldName);
serializedFieldNames.put(fieldName, nameBytes);
return nameBytes;
}
@Override
/** {@inheritDoc} */
public List<Put> getPutCommand(Map<String, Object> fields)
throws IOException {
String rowKeyCol = getRowKeyColumn();
String colFamily = getColumnFamily().toUpperCase();
byte[] colFamilyBytes = Bytes.toBytes(colFamily);
// Multiple rowKey
String[] rowKeys = rowKeyCol.split(",");
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
for (String item : rowKeys) {
Object rowKey = fields.get(item);
if (null == rowKey) {
// If the row-key column is null, we don't insert this row.
LOG
.warn("Could not insert row with null value for row-key column: "
+ rowKeyCol);
return null;
}
outputStream.write(getBytes(rowKey));
}
// New put object
Put put = new Put(outputStream.toByteArray());
outputStream.close();
for (Map.Entry<String, Object> fieldEntry : fields.entrySet()) {
String colName = fieldEntry.getKey().toUpperCase();
if (!colName.equals(rowKeyCol.toUpperCase())) {
// This is a regular field, not the row key.
// Add it if it's not null.
Object val = fieldEntry.getValue();
if (null != val) {
put.add(colFamilyBytes, getFieldNameBytes(colName),
getBytes(val));
}
}
}
return Collections.singletonList(put);
}
public byte[] getBytes(Object obj) {
byte[] valBytes = null;
if (obj instanceof String) {
String s = (String) obj;
valBytes = PVarchar.INSTANCE.toBytes(s);
} else if (obj instanceof Boolean) {
Boolean b = ((Boolean) obj).booleanValue();
valBytes = PBoolean.INSTANCE.toBytes(b);
} else if (obj instanceof Byte) {
Byte b = ((Byte) obj).byteValue();
valBytes = PTinyint.INSTANCE.toBytes(b);
} else if (obj instanceof Short) {
Short s = ((Short) obj).shortValue();
valBytes = PSmallint.INSTANCE.toBytes(s);
} else if (obj instanceof Integer) {
Integer i = ((Integer) obj).intValue();
valBytes = PInteger.INSTANCE.toBytes(i);
} else if (obj instanceof Long) {
Long l = ((Long) obj).longValue();
valBytes = PLong.INSTANCE.toBytes(l);
} else if (obj instanceof Float) {
Float f = ((Float) obj).floatValue();
valBytes = PFloat.INSTANCE.toBytes(f);
} else if (obj instanceof Double) {
Double d = ((Double) obj).doubleValue();
valBytes = PDouble.INSTANCE.toBytes(d);
} else if (obj instanceof java.math.BigInteger) {
java.math.BigInteger b = (java.math.BigInteger) obj;
valBytes = PLong.INSTANCE.toBytes(b);
} else if (obj instanceof java.math.BigDecimal) {
java.math.BigDecimal b = (java.math.BigDecimal) obj;
valBytes = PDecimal.INSTANCE.toBytes(b);
} else if (obj instanceof java.sql.Date) {
java.sql.Date d = (java.sql.Date) obj;
valBytes = PDate.INSTANCE.toBytes(d);
} else if (obj instanceof java.sql.Time) {
java.sql.Time t = (java.sql.Time) obj;
valBytes = PTime.INSTANCE.toBytes(t);
} else if (obj instanceof java.sql.Timestamp) {
java.sql.Timestamp t = (java.sql.Timestamp) obj;
valBytes = PTimestamp.INSTANCE.toBytes(t);
}
return valBytes;
}
}