Commit a15e1afb authored by 江洋洋's avatar 江洋洋

dsp初次请求v2.0

parent 1aee4f3b
...@@ -38,7 +38,7 @@ allprojects { ...@@ -38,7 +38,7 @@ allprojects {
} }
group = "cn.com.duiba.boot" group = "cn.com.duiba.boot"
version = "0.0.31" version = "0.0.32"
} }
subprojects { subprojects {
......
package cn.com.duiba.spring.boot.starter.dsp.enums;
/**
* @author jiangyangyang
* @version 1.0
* @description: redis8分片解决均匀分布key枚举类, 主要是先尝试获取所有节点的key,然后根据hash tag实现均匀分布
* @date 2022/1/6 上午10:28
*/
public enum RedisBalance8KeyEnum {
KEY01(0, "3"),
KEY02(1, "58"),
KEY03(2, "2"),
KEY04(3, "59"),
KEY05(4, "1"),
KEY06(5, "56"),
KEY07(6, "0"),
KEY08(7, "57");
public int order;
public String hashTag;
RedisBalance8KeyEnum(int order, String hashTag) {
this.order = order;
this.hashTag = hashTag;
}
}
package cn.com.duiba.spring.boot.starter.dsp.util;
/**
* hash 算法类 Created by lizhihui on 2017-08-15 11:05.
*/
public class HashAlgorithm {
private HashAlgorithm() {
}
public static int bkdrHash(String str) {
int seed = 131; // 31 131 1313 13131 131313 etc..
int hash = 0;
for (int i = 0; i < str.length(); i++) {
hash = (hash * seed) + str.charAt(i);
}
return (hash & 0x7FFFFFFF);
}
public static int sdbmHash(String str) {
int hash = 0;
for (int i = 0; i < str.length(); i++) {
hash = str.charAt(i) + (hash << 6) + (hash << 16) - hash;
}
return (hash & 0x7FFFFFFF);
}
public static int djbHash(String str) {
int hash = 5381;
for (int i = 0; i < str.length(); i++) {
hash = ((hash << 5) + hash) + str.charAt(i);
}
return (hash & 0x7FFFFFFF);
}
public static int dekHash(String str) {
int hash = str.length();
for (int i = 0; i < str.length(); i++) {
hash = ((hash << 5) ^ (hash >> 27)) ^ str.charAt(i);
}
return (hash & 0x7FFFFFFF);
}
public static int apHash(String str) {
int hash = 0;
for (int i = 0; i < str.length(); i++) {
hash ^= ((i & 1) == 0) ? ((hash << 7) ^ str.charAt(i)
^ (hash >> 3)) : (~((hash << 11) ^ str.charAt(i) ^ (hash >> 5)));
}
return hash;
}
public static int oneByOneHash(String key) {
int hash;
int i;
for (hash = 0, i = 0; i < key.length(); ++i) {
hash += key.charAt(i);
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
}
package cn.com.duiba.spring.boot.starter.dsp.util;
import cn.com.duiba.spring.boot.starter.dsp.enums.RedisBalance8KeyEnum;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @author jiangyangyang
* @version 1.0
* @description: 根据分片个数生成redis均匀的key
* @date 2022/1/6 上午10:36
*/
public class RedisBalanceKeyUtil {
private static final String START = "{";
private static final String END = "}";
/**
* 根据前缀生成8分片的redis key
*
* @param prefix 前缀
* @return redis key集合
*/
public static List<String> createRedisBalance8key(String prefix) {
RedisBalance8KeyEnum[] values = RedisBalance8KeyEnum.values();
List<String> list = new ArrayList<>(values.length);
for (RedisBalance8KeyEnum keyEnum : values) {
String key = keyEnum.hashTag;
String redisKey = StringUtils.join(prefix, "_", keyEnum.order, START, key, END);
list.add(redisKey);
}
return list;
}
/**
* 通过hash 然后取模获取指定的redis key
*
* @param targetStr 目标字符串
* @return 返回指定节点对应的rediskey
*/
public static String getRedisBalance8key(String prefix, String targetStr) {
String HashStr = DigestUtils.md5Hex(targetStr);
int targetHashValue = HashAlgorithm.dekHash(HashStr);
RedisBalance8KeyEnum[] values = RedisBalance8KeyEnum.values();
int mold = targetHashValue % (values.length);
for (RedisBalance8KeyEnum keyEnum : values) {
if (Objects.equals(keyEnum.order, mold)) {
String key = keyEnum.hashTag;
return StringUtils.join(prefix, "_", keyEnum.order, START, key, END);
}
}
return null;
}
}
package cn.com.duiba.spring.boot.starter.dsp.util; package cn.com.duiba.spring.boot.starter.dsp.util;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import cn.com.duiba.wolf.utils.NumberUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component; import org.springframework.scripting.support.StaticScriptSource;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Collections;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
...@@ -25,7 +26,7 @@ public class RedisBloomHandler<K, V> { ...@@ -25,7 +26,7 @@ public class RedisBloomHandler<K, V> {
private static final String EXISTS = "BF.EXISTS"; private static final String EXISTS = "BF.EXISTS";
private static final String MEXISTS = "BF.MEXISTS"; private static final String MEXISTS = "BF.MEXISTS";
@Resource(name = "redisBloomRedisTemplate") @Resource(name = "redisBloomStringRedisTemplate")
private RedisTemplate redisTemplate; private RedisTemplate redisTemplate;
RedisSerializer keySerializer() { RedisSerializer keySerializer() {
...@@ -166,4 +167,72 @@ public class RedisBloomHandler<K, V> { ...@@ -166,4 +167,72 @@ public class RedisBloomHandler<K, V> {
return rawArgs; return rawArgs;
} }
/**
* 保存数据到布隆过滤器
*
* @param key redis key
* @param value 值
* @param levelCount 过滤总层次
* @return
*/
public Integer saveBloom(String key, String value, Integer levelCount) {
String luaText = "local a = "+(levelCount+1)+"\n" +
"for i = 1, #(ARGV)+1 do\n" +
" if(redis.call('BF.ADD', KEYS[1], (ARGV[1] .. '_' .. i)) == 1) then\n" +
" a = i;\n" +
" break;\n" +
" end\n" +
"end\n" +
"return a;";
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
redisScript.setScriptSource(new StaticScriptSource(luaText));
redisScript.setResultType(Long.class);
Object execute = redisTemplate.execute(redisScript, Collections.singletonList(key), value, String.valueOf(levelCount));
if (NumberUtils.isNumeric(execute + "")) {
return Integer.valueOf(execute + "");
}
return null;
}
/**
* 判断创建redis 布隆过滤器
*
* @param keys
* @param errorRate
* @param initCapacity
* @param expireAt
*/
public void createFiltersWithExpireAt(List<K> keys, double errorRate, long initCapacity, long expireAt) {
byte[] rawErrorRate = rawString(String.valueOf(errorRate));
byte[] rawInitCapacity = rawString(String.valueOf(initCapacity));
Object execute = redisTemplate.execute(connection -> {
keys.forEach(key -> {
byte[] rawKey = rawKey(key);
connection.execute(RESERVE, rawKey, rawErrorRate, rawInitCapacity);
connection.expireAt(rawKey, expireAt);
});
return null;
}, true);
}
/**
* 根据key判断redis key是否设置过期时间
*
* @param key key
* @return
*/
public Long getExpire(String key) {
return redisTemplate.getExpire(key);
}
/**
* 设置redis过去时间
*
* @param key key
* @param delta 过期时间点
* @return
*/
public Boolean expireAt(String key, Date delta) {
return redisTemplate.expireAt(key, delta);
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment