基於Redis-bitmaps自動重命名工具類

github鏈接:https://github.com/striner/javaCode/blob/master/WRedisHelper

 

import com.bj58.bic.pan.scf.constants.CfgConstant;
import com.bj58.bic.pan.scf.exception.WRedisException;
import com.bj58.spat.wredis.client.builder.ClientBuilder;
import com.bj58.spat.wredis.client.config.ClientConfig;
import com.bj58.spat.wredis.client.wjedis.WJedis;
import com.bj58.spat.wredis.client.wjedis.WJedisSentinelPool;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.bj58.bic.pan.scf.enums.StatusEnum.Result.*;


public class WRedisHelper {

    private static Logger logger = LogManager.getLogger(WRedisHelper.class);

    private static final String SET_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_EXPIRE_SECONDS = "EX";

    private static WJedisSentinelPool redisSentinelPool;

    private static final String APP_NAME = "aaa";

    private static final int COUNT = 20;
    private static final Pattern pattern = Pattern.compile("\\(\\d+\\)$"); //判斷是否以帶數字的括號結尾

    static {
        ClientConfig.init(CfgConstant.WREDIS_CONFIG_PATH);
        redisSentinelPool = ClientBuilder.redisSentinel(APP_NAME).build();
    }


    private static WJedis getJedis() {
        return redisSentinelPool.getResource();
    }


    private static void releaseJedis(final WJedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }



    /**
     * 重名處理-獲取name
     * @author : mulin
     * @date : 2019/8/23
     */
    public static synchronized String setName(String name, Long pid, int type) throws Exception{
        logger.info("setName -- name={}, pid={}, type={}", name, pid, type);
        WJedis jedis = getJedis();
        try {
            String key = pid + "_" + name.hashCode() + "_" + type;
            long offset = 0L;

            //判斷name是否以帶數字的括號結尾
            Matcher matcher = pattern.matcher(name);
            if (matcher.find()) {  //name後帶有括號
                GetShortName getShortName = new GetShortName(name, matcher).invoke();
                long shortIndex = getShortName.getOffset();
                String shortKey = pid + "_" + getShortName.getName().hashCode() + "_" + type;

                //判斷名字是否重複
                if(jedis.getbit(key, offset) || jedis.getbit(shortKey, shortIndex)) {

                    offset = jedis.bitpos(key, false);
                    String newKey= pid + "_" + (name + "("+offset+")").hashCode() + "_" + type;

                    while(jedis.getbit(newKey, 0)) {
                        jedis.setbit(key, offset, true);
                        offset++;
                        newKey = pid + "_" + (name + "("+offset+")").hashCode() + "_" + type;
                    }
                    jedis.setbit(newKey, 0, true);
                    jedis.setbit(key, offset, true);
                    String newName = name + "("+offset+")";

                    logger.info("setName -- newName={}", newName);
                    return newName;
                }
                jedis.setbit(key, offset, true);
                jedis.setbit(shortKey, shortIndex, true);
                logger.info("setName -- name={}", name);
                return name;
            }

            //如果名字不重複,則直接setbit
            if(!jedis.getbit(key, offset)) {
                jedis.setbit(key, offset, true);
                return name;
            }
            logger.info("setName -- offset={}", offset);

            offset = jedis.bitpos(key, false); //第一個爲false的bit
            jedis.setbit(key, offset, true);
            String newName = name+"(" + offset + ")";
            jedis.setbit((pid + "_" + newName.hashCode() + "_" + type), 0, true);
            logger.info("setName -- newName={}", newName);
            return newName;

        } catch (Exception e) {
            logger.error("setName -- name處理失敗 name={}, pid={}, type={}", name, pid, type, e);
            e.printStackTrace();
            throw new WRedisException();
        } finally {
            releaseJedis(jedis);
        }
    }

    /**
     * 重名處理-刪除name
     * @author : mulin
     * @date : 2019/8/23
     */
    public static synchronized boolean delName(String name, Long pid, int type) {
        logger.info("delName -- name={}, pid={}, type={}", name, pid, type);
        WJedis jedis = getJedis();
        try {
            //獲取name後括號中的數字
            Matcher matcher = pattern.matcher(name);

            long offset = 0L;
            if (matcher.find()) {
                logger.info("delName -- name={} end by '(number)'", name);
                GetShortName getShortName = new GetShortName(name, matcher).invoke();
                String shortName = getShortName.getName();
                long shortIndex = getShortName.getOffset();
                String shortKey = pid + "_" + shortName.hashCode() + "_" + type;
                logger.info("delName -- shortName={}, index={}", shortName, shortIndex);
                jedis.setbit(shortKey, shortIndex, false);
            }

            String key = pid + "_" + name.hashCode() + "_" + type;
            logger.info("delName -- name={}, index={}", name, offset);
            jedis.setbit(key, offset, false);

            return true;
        } catch (Exception e) {
            logger.error("delName -- name處理失敗 name={}, pid={}, type={}", name, pid, type, e);
            return false;
        } finally {
            releaseJedis(jedis);
        }
    }

    /**
     * 重名處理-判斷該name是否重複
     * @author : mulin
     * @date : 2019/8/26
     */
    public static synchronized boolean checkIsExist(String name, Long pid, int type) throws Exception {
        logger.info("checkIsExist -- name={}, pid={}, type={}", name, pid, type);
        WJedis jedis = getJedis();
        try {
            String key = pid + "_" + name.hashCode() + "_" + type;
            return jedis.bitcount(key) > 0;
        } catch (Exception e) {
            logger.error("checkIsExist -- name處理失敗 name={}, pid={}, type={}", name, pid, type, e);
            throw new WRedisException(serverError);
        } finally {
            releaseJedis(jedis);
        }
    }

    /**
     * 批量刪除該pid下的所有目錄和文件
     * @author : mulin
     * @date : 2019/9/9
     */
    public static Long delDirsAndDocsUnderPid(Long pid) throws Exception {
        logger.info("delDirsAndDocsUnderPid -- pid={}", pid);
        WJedis jedis = getJedis();
        try {

            String pattern = pid + "_*";
            List<String> keys = new ArrayList<>();

            String cursor = ScanParams.SCAN_POINTER_START;
            ScanParams scanParams = new ScanParams();
            scanParams.count(COUNT);
            scanParams.match(pattern);
            logger.info("delDirsAndDocsUnderPid -- pid={}, pattern={}", pid, pattern);

            do {
                ScanResult<String> scanResult = jedis.scan(cursor, scanParams);
                keys.addAll(scanResult.getResult());
                cursor = scanResult.getStringCursor();
            }while(!"0".equals(cursor));

            logger.info("delDirsAndDocsUnderPid -- keys={}", keys);
            Iterator<String> key = keys.iterator();
            Long del = 0L;
            while(key.hasNext()) {
                String keyStr = key.next();
                logger.info("delDirsAndDocsUnderPid delKey -- key={}", keyStr);
                del += jedis.del(keyStr);
            }

            return del;
        } catch (Exception e) {
            logger.error("delDirsAndDocsUnderPid -- 數據刪除失敗 pid={}", pid);
            throw new WRedisException(serverError);
        } finally {
            releaseJedis(jedis);
        }
    }



    /**
     * 文件/目錄移動
     *
     * @param sourceName    源name
     * @param sourcePid     源pid
     * @param type          數據類型 文件/目錄
     * @param targetPid     目標pid
     * @author : mulin
     * @date : 2019/9/10
     */
    public static synchronized void moveDocsAndDirs(String sourceName, Long sourcePid, int type, Long targetPid) throws Exception {
        logger.info("moveDocsAndDirs -- sourceName={}, sourcePid={}, type={}, targetPid={}",sourceName, sourcePid, type, targetPid);
        WJedis jedis = getJedis();
        String name = null;
        try {
            name = setName(sourceName, targetPid, type);
            delName(sourceName, sourcePid, type);
        } catch (Exception e) {
            logger.error("moveDocsAndDirs 操作失敗 -- sourceName={}, sourcePid={}, type={}, targetPid={}",sourceName, sourcePid, type, targetPid);
            //回滾
            if(StringUtils.isNotEmpty(name)) {
                delName(name, targetPid, type);
            }
            throw new WRedisException(serverError);
        } finally {
            releaseJedis(jedis);
        }
    }





    private static class GetShortName {
        private String name;
        private Matcher matcher;
        private long offset;

        GetShortName(String name, Matcher matcher) {
            this.name = name;
            this.matcher = matcher;
        }

        private String getName() {
            return name;
        }

        private long getOffset() {
            return offset;
        }

        private GetShortName invoke() {
            String index = matcher.group(0);
            index = index.substring(1, index.length()-1);
            offset = Long.valueOf(index);
            //name去掉括號和數字,獲取key
            name = name.substring(0, name.length()-index.length()-2);
            return this;
        }
    }
}

 

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