当前位置 : 主页 > 编程语言 > c++ >

表格存储 tablestore 创建表, 创建client,构造分区键主键(随机桶) 工具类

来源:互联网 收集:自由互联 发布时间:2021-07-03
创建表格存储 client,在接口代码中直接注入 即可使用 ( @Autowired @Qualifier("createClient") private SyncClient client;) package com.mimidai.common.utils.table;import com.alicloud.openservices.tablestore.ClientConfigurati
创建表格存储 client,在接口代码中直接注入 即可使用 ( @Autowired @Qualifier("createClient") private SyncClient client;)
package com.mimidai.common.utils.table;

import com.alicloud.openservices.tablestore.ClientConfiguration;
import com.alicloud.openservices.tablestore.SyncClient;
import com.alicloud.openservices.tablestore.model.AlwaysRetryStrategy;
import com.mimidai.common.utils.PropertiesUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 创建表格存储client Created by EVE on 2017-06-22.
 */
@Configuration
//@PropertySource("classpath:application-develop.properties")
public class TableClientConfig {
    private static Logger logger = LoggerFactory.getLogger("log.hbase.TableClientConfig");  
    //测试 环境 start
    //内网地址
     private String endPoint = "http://XXXXXX:80/";
    //外网地址  网段地址保留一个即可
    // private static final String endPoint = "http://XXXXXX.cn-beijing.ots.aliyuncs.com";
     private String accessId = "XXXXXX";
     private String accessKey = "XXXXXXXX";
     private String instanceName = "test";



    //测试  
    @Bean
    public SyncClient createClient() {
    		try{
    			logger.info("开始调用createClient方法");
			// ClientConfiguration提供了很多配置项,以下只列举部分。
			ClientConfiguration clientConfiguration = new ClientConfiguration();
			// 设置建立连接的超时时间。
			clientConfiguration.setConnectionTimeoutInMillisecond(5000);
			// 设置socket超时时间。
			clientConfiguration.setSocketTimeoutInMillisecond(5000);
			// 设置重试策略,若不设置,采用默认的重试策略。
			clientConfiguration.setRetryStrategy(new AlwaysRetryStrategy());
			logger.info("返回创建表格存储cleint");
			return new SyncClient(endPoint, accessId, accessKey, instanceName, clientConfiguration);
		} catch (Exception e) {
			logger.warn("----------------------表格存储client初始化失败");
		}
    		return null;
        
    }

}
创建表格存储表的工具类,可通过此创建带版本的表。(在官方客户端好像不可以创建版本,我是没发现)
package com.mimidai.common.utils.table;

import com.alicloud.openservices.tablestore.SyncClient;
import com.alicloud.openservices.tablestore.model.CapacityUnit;
import com.alicloud.openservices.tablestore.model.DeleteTableRequest;
import com.alicloud.openservices.tablestore.model.DescribeTableRequest;
import com.alicloud.openservices.tablestore.model.DescribeTableResponse;
import com.alicloud.openservices.tablestore.model.PrimaryKeySchema;
import com.alicloud.openservices.tablestore.model.PrimaryKeyType;
import com.alicloud.openservices.tablestore.model.ReservedThroughput;
import com.alicloud.openservices.tablestore.model.ReservedThroughputDetails;
import com.alicloud.openservices.tablestore.model.TableMeta;
import com.alicloud.openservices.tablestore.model.TableOptions;
import com.alicloud.openservices.tablestore.model.UpdateTableRequest;
import com.alicloud.openservices.tablestore.model.internal.CreateTableRequestEx;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by 孟庆艺 on 2017-08-03.
 */
@Service
public class OperateTableUtils {
    @Autowired
    @Qualifier("createClient")
    private SyncClient client;
    private static final Logger logger = LoggerFactory.getLogger("log.tableStore.OperateTableUtils");

    /**
     * 创建表
     *
     * @param createTableName 表名
     * @param timeToLive      数据过期时间 单位:秒 例如:一年 365*24*3600 -1表示永不过期
     * @param maxVersions     保存最大版本数 设置为3即代表每列最多保存 N 个最新的版本
     * @param primaryKey      可变参数类型 主键列名 可变参数最大为4
     */
    public void createTable(String createTableName, Integer timeToLive, Integer maxVersions, String... primaryKey) {
        if (primaryKey.length > 4) {
            logger.info("注意:表格存储主键最多可设置4个,可变参数个数最大为4");
            return;
        }
        TableMeta tableMeta = new TableMeta(createTableName);
        for (String PRIMARY_KEY : primaryKey) {
            tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema(PRIMARY_KEY, PrimaryKeyType.STRING));
        }
        TableOptions tableOptions = new TableOptions(timeToLive, maxVersions);
        CreateTableRequestEx request = new CreateTableRequestEx(tableMeta, tableOptions);
        //设置读写预留值 容量型示例 只能设置为0 高性能示例可以设置为非零值
        request.setReservedThroughput(new ReservedThroughput(new CapacityUnit(0, 0)));
        client.createTable(request);
    }

    /**
     * 创建表
     *
     * @param timeToLive  数据过期时间 单位:秒 例如:一年 365*24*3600 -1表示永不过期
     * @param maxVersions 保存最大版本数 设置为3即代表每列最多保存 N 个最新的版本
     */
    public void createTable(String createTableName, Integer timeToLive, Integer maxVersions,
            List
 
   primaryKey) {
        if (primaryKey.size() > 4) {
            logger.info("注意:表格存储主键最多可设置4个,可变参数个数最大为4");
            return;
        }
        TableMeta tableMeta = new TableMeta(createTableName);
        tableMeta.addPrimaryKeyColumns(primaryKey);
        TableOptions tableOptions = new TableOptions(timeToLive, maxVersions);
        CreateTableRequestEx request = new CreateTableRequestEx(tableMeta, tableOptions);
        //设置读写预留值 容量型示例 只能设置为0 高性能示例可以设置为非零值
        request.setReservedThroughput(new ReservedThroughput(new CapacityUnit(0, 0)));
        client.createTable(request);
    }


    /**
     * 构建list
     */
    private List
  
    primaryKeySchemaList(Object... primaryKey) { if (primaryKey.length > 4) { logger.info("注意:表格存储主键最多可设置4个,可变参数个数最大为4"); return null; } List
   
     primaryKeySchemaList = new ArrayList<>(); for (Object PRIMARYKEY : primaryKey) { if (PRIMARYKEY instanceof String) { String PRIMARY_KEY = (String) PRIMARYKEY; primaryKeySchemaList.add(new PrimaryKeySchema(PRIMARY_KEY, PrimaryKeyType.STRING)); } } return primaryKeySchemaList; } /** * 更新表 * * @param timeToLive 数据过期时间 单位:秒 例如:一年 365*24*3600 -1表示永不过期 * @param maxVersions 保存最大版本数 设置为3即代表每列最多保存 N 个最新的版本 * @param maxTimeDeviation 有效版本偏差 [数据写入时间-有效版本偏差,数据写入时间+有效版本偏差) */ public void updateTable(Integer timeToLive, Integer maxVersions, Long maxTimeDeviation, String TableName) { if (maxVersions == null || TableName == null) { return; } TableOptions tableOptions = new TableOptions(); if (maxVersions != null) { tableOptions = new TableOptions(maxVersions); } else if (timeToLive != null) { tableOptions = new TableOptions(timeToLive, maxVersions); } else if (maxTimeDeviation != null) { tableOptions = new TableOptions(timeToLive, maxVersions, maxTimeDeviation); } UpdateTableRequest updateTableRequest = new UpdateTableRequest(TableName); updateTableRequest.setTableOptionsForUpdate(tableOptions); client.updateTable(updateTableRequest); } /** * 获取表相关信息 */ public void describeTable(String TableName) { DescribeTableRequest describeStreamRequest = new DescribeTableRequest(TableName); DescribeTableResponse describeTableResponse = client.describeTable(describeStreamRequest); TableMeta tableMeta = describeTableResponse.getTableMeta(); List
    
      primaryKeySchemaList = tableMeta.getPrimaryKeyList(); for (PrimaryKeySchema primaryKeySchema : primaryKeySchemaList) { logger.info("表:{}主键:{}", TableName, primaryKeySchema); } TableOptions tableOptions = describeTableResponse.getTableOptions(); ReservedThroughputDetails reservedThroughputDetails = describeTableResponse.getReservedThroughputDetails(); logger.info("表:{},数据过期时间timeToLive:{},最大版本数maxVersions:{},预留读吞吐量:{},预留写吞吐量:{}", TableName, tableOptions .getTimeToLive(), reservedThroughputDetails.getCapacityUnit().getReadCapacityUnit(), reservedThroughputDetails.getCapacityUnit().getWriteCapacityUnit()); } /** * 删除表 */ public void deleteTable(String TableName) { DeleteTableRequest deleteTableRequest = new DeleteTableRequest(TableName); client.deleteTable(deleteTableRequest); } }
    
   
  
 
该方法将重点着眼于 分区键的创建,一个良好的表结构设计尤为重要,分区键关系到最大化的利用大数据量情况下表格存储,自动分区,数据均匀散列分布,有利于分布式的操作数据
package com.mimidai.common.utils.table;/**
 * Created by 孟庆艺 on 2017-08-31.
 */

import com.alicloud.openservices.tablestore.model.PrimaryKeyBuilder;
import com.alicloud.openservices.tablestore.model.PrimaryKeyValue;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import sun.misc.BASE64Encoder;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

import com.alicloud.openservices.tablestore.model.PrimaryKey;

/**
 * 表格存储生成构造主键方法
 *
 * @author mengqingyi
 * @create 2017-08-31 10:13
 **/
public class PrimaryKeyUtils {
    //日志
    private static final Logger logger = LoggerFactory.getLogger(PrimaryKey.class);

    /**
     * 使用md5算法加密算法 对字符串进行加密
     */
    private String EncodeByMd5(String string) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        //计算方法
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        BASE64Encoder base64Encoder = new BASE64Encoder();
        //加密后的字符串
        String newStr = base64Encoder.encode(messageDigest.digest(string.getBytes("UTF-8")));
        return newStr;
    }

    /**
     * 如有明确的分区键,则可以使用分区键+主键格式构造主键
     */
    public PrimaryKey createPrimaryKey(Integer partitionKey, String userId) {
        logger.debug("进入tableStore(core1)生成构造主键通用方法createPrimaryKey");
        // 首先对入参进行判断 若为空直接返回 不再查询
        if (StringUtils.isBlank(partitionKey + "") || StringUtils.isBlank(userId)) {
            logger.warn("表格存储短信详单主键为空,达不到构造主键要求,返回空值");
            return null;
        }
        // 构造主键
        PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
        primaryKeyBuilder.addPrimaryKeyColumn("partitionKey", PrimaryKeyValue.fromLong(partitionKey));
        primaryKeyBuilder.addPrimaryKeyColumn("userId", PrimaryKeyValue.fromString(userId));
        logger.info("tableStore(core1)生成构造主键通用方法createPrimaryKey:partitionKey={},userId={}", partitionKey, userId);
        return primaryKeyBuilder.build();
    }

    /**
     * 如无明确的分区键,方案1.由大小为5随机桶(实际就是随机数)作为分区键 以桶的随机数作为分片键(表格存储,hbase中也有类似方案,salted key)
     */
    public PrimaryKey createPrimaryKeyByRandomBucket(String userId) {
        logger.debug("进入tableStore(core1)生成构造主键通用方法createPrimaryKey");
        // 首先对入参进行判断 若为空直接返回 不再查询
        if (StringUtils.isBlank(userId)) {
            logger.warn("表格存储短信详单主键为空,达不到构造主键要求,返回空值");
            return null;
        }
        Integer partitionKey = new Random().nextInt(5);
        // 构造主键
        PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
        primaryKeyBuilder.addPrimaryKeyColumn("partitionKey", PrimaryKeyValue.fromLong(partitionKey));
        primaryKeyBuilder.addPrimaryKeyColumn("userId", PrimaryKeyValue.fromString(userId));
        logger.info("tableStore(core1)生成构造主键通用方法createPrimaryKey:partitionKey={},userId={}", partitionKey, userId);
        return primaryKeyBuilder.build();
    }

    /**
     * 如无明确的分区键,方案1.指定大小的随机桶(实际就是随机数)作为分区键 以桶的随机数作为分片键(表格存储,hbase中也有类似方案,salted key)
     */
    public PrimaryKey createPrimaryKeyByRandomBucket(String userId, Integer randomBucketSize) {
        logger.debug("进入tableStore(core1)生成构造主键通用方法createPrimaryKey");
        // 首先对入参进行判断 若为空直接返回 不再查询
        if (StringUtils.isBlank(userId)) {
            logger.warn("表格存储短信详单主键为空,达不到构造主键要求,返回空值");
            return null;
        }
        Integer partitionKey = new Random().nextInt(randomBucketSize);
        // 构造主键
        PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
        primaryKeyBuilder.addPrimaryKeyColumn("partitionKey", PrimaryKeyValue.fromLong(partitionKey));
        primaryKeyBuilder.addPrimaryKeyColumn("userId", PrimaryKeyValue.fromString(userId));
        logger.info("tableStore(core1)生成构造主键通用方法createPrimaryKey:partitionKey={},userId={}", partitionKey, userId);
        return primaryKeyBuilder.build();
    }

    /**
     * 无明确的分区键,取散裂化后的userId的前4位作为分区键
     */
    public PrimaryKey createPrimaryKeyByUserId(String userId) {
        logger.debug("进入tableStore(core1)生成构造主键通用方法createPrimaryKey");
        // 首先对入参进行判断 若为空直接返回 不再查询
        if (StringUtils.isBlank(userId)) {
            logger.warn("表格存储短信详单主键为空,达不到构造主键要求,返回空值");
            return null;
        }
        String partitionKey = null;
        try {
            partitionKey = EncodeByMd5(userId);
            logger.info("userId={},MD5之后的md5UserId={}", userId, partitionKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 构造主键
        PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
        primaryKeyBuilder.addPrimaryKeyColumn("partitionKey", PrimaryKeyValue.fromString(partitionKey));
        primaryKeyBuilder.addPrimaryKeyColumn("userId", PrimaryKeyValue.fromString(userId));
        logger.info("tableStore(core1)生成构造主键通用方法createPrimaryKey:partitionKey={},userId={}", partitionKey, userId);
        return primaryKeyBuilder.build();
    }


}
最后奉上 官方表格存储的最佳实践
https://yq.aliyun.com/articles/57102
网友评论