Hive UDTF 接受参数及Redis连接问题

hive-exec-2.7.3版本中最通用的方法,所有的类型都可以接收。

ObjectInspector[] inputIOS;
public StructObjectInspector initialize(ObjectInspector[] args) {
    this.inputIOS = args;
}
public void process(Object[] o) {
    Object obj = ((PrimitiveObjectInspector)inputIOs[i]).getPrimitiveJavaObject(o[i]);
    String input = obj.toString();
    // 然后将input转换正任何想要的类型
}

 

 

1、UDTF中process方法会被执行多次,是串行执行的,close方法只会执行一次。

2、可以定义实例范围的局部变量,不需要考虑线程安全问题。但是由于运行中UDTF会多次实例化,所以就会有很多个连接。实测100万数据大概会有100个实例,也就会有100个连接,process执行10s以内,整个函数运行46s。

3、如果想要降低连接数,就要使用类范围的全部静态变量,所以需要加锁,无论如何,肯定会影响性能。

(1)JedisPool,整体耗时增加至256s。

(2)单例加锁,整体耗时大约也要300s左右。

(3)自定义队列,长度100,初始化10,整体耗时54s。

4、代码
 

public class MyUDTF extends GenericUDTF {
    @Override
    public StructObjectInspector initialize(ObjectInspector[] argOIs)
        throws UDFArgumentException {
    
    }
    @Override
    public void process(Object[] args) throws HiveException {
    /******************************方法1*******************************/
        getJedis().get("key");
    /******************************方法2*******************************/
        Jedis jedis = getJedis();
        jedis.get("key");
        returnJedis(jedis);
    /******************************方法3*******************************/
        Jedis jedis = getJedis();
        jedis.get("key");
        returnJedis(jedis);
    }

    @Override
    public void close() throws HiveException {
    /******************************方法1*******************************/
        returnJedis(jedis);
    /******************************方法2*******************************/
        // do nothing:无法在close时释放资源,在后续实例化中仍然需要使用。
    /******************************方法3*******************************/
        // do nothing:无法在close时释放资源,在后续实例化中仍然需要使用。
    }
    /******************************方法1*******************************/
    private Jedis jedis = null;
    private Jedis getJedis() {
        if(null == Jedis) {
            jedis = new Jedis("127.0.0.1", 6379);
        }
        return jedis;
    }
    private static void returnJedis(Jedis jedis) {
        if(null != jedis) {
            jedis.close();
        }
    }
    /******************************方法2*******************************/
    private static final JedisPool pool;
    static {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(10);
        config.setMinIdle(0);
        config.setTestOnBorrow(false);
        config.setTestOnCreate(false);
        config.setTestOnReturn(false);
        pool = new JedisPool(config, "127.0.0.1", 6379);
    }
    private static Jedis getJedis() {
        return pool.getResource();
    }
    private static void returnJedis(Jedis jedis) {
        if(null != jedis) {
            jedis.close();
        }
    }
    /******************************方法3*******************************/
    private static final LinkedBlockingQueue<Jedis> queue;
    static {
        int n = 10;
        queue = new LinkedBlockingQueue<>(10 * n);
        Jedis jedis;
        for(int i = 0; i < n; i++) {
            jedis = createJedis();
            returnJedis(jedis);
        }
    }
    private static Jedis getJedis() {
        Jedis jedis = null;
        try {
            jedis = queue.poll(1, TimeUnit.MICROSECONDS);
        } catch(Exception e) {
            // log
        }
        if (null == jedis) {
            jedis = createJedis();
        }
        return jedis;
    }
    private static void returnJedis(Jedis jedis) {
        if(!queue.offer(jedis)) {
            // log
        }
    }
    private static void createJedis(Jedis jedis) {
        jedis = new Jedis("127.0.0.1", 6379);
        return jedis;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章