• 授权协议:-
  • 开发厂商:-
  • 软件语言:C/C++
  • 更新日期:2019-12-19
redis-aux

redis-aux 是基于 redisTemplate 的 redis 辅助工具包。目前有两个主要模块,基于注解的三种限流方式以及简单易用布隆过滤器。 用法: 这里用maven作为工具管理包演示...

redis-aux redis 辅助工具包 项目简介

【年终提升】2019尾声,来 OSC·年终盛典收割技术干货,get新技能!>>> redis-aux 是基于 redisTemplate 的 redis 辅助工具包。目前有两个主要模块,基于注解的三种限流方式以及简单易用布隆过滤器。用法:这里用maven作为工具管理包演示,添加jitpack源、添加下面的依赖<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>

<dependency>
<groupId>com.github.97lele</groupId>
<artifactId>redis-aux</artifactId>
<version>0.0.8.RELEASE</version>
</dependency>布隆过滤器演示:在启动类上添加启用工具包的注解@EnableRedisAux三个属性,分别为1.需要支持lambda表达式添加的实体路径2.是否开启支持@Trancational注解,需要和数据库事务配合使用3.是否开启限流功能配置好redisspring:
redis:
port: 6379
host: 127.0.0.1添加方法 若要调用SFunction为参数的方法需要在EnableRedisAux配置扫描路径主要是exceptedInsertions,fpp这里两个参数,分别为预计插入的个数,允许的错误率演示1.普通单个添加@Autowired
private RedisBloomFilter redisBloomFilter;


@Test
void addSingleTest() {
redisBloomFilter.add("news","user1","推送1",500L,0.001);
System.out.println(redisBloomFilter.mightContain("news", "user1", "推送1"));
System.out.println(redisBloomFilter.mightContain("news","user1","推送2"));
}结果多个添加@Test
void addMutileTest(){
String keyPrefix="news";
String key="user2";
redisBloomFilter.addAll(keyPrefix,key,1000L,0.03, Arrays.asList("1","2","3"));
System.out.println(redisBloomFilter.mightContains(keyPrefix,key,Arrays.asList("1","2","4")));
}结果lambda演示,需要实体类实现getter和序列化接口,并且添加上前缀名,否则默认为"bloom_filter",需要操作的属性上面添加BloomFilterProperty注解,该注解可填充属性有以下3个,key如果不填按字段名处理double fpp() default 0.03D;

long exceptionInsert() default 1000L;

String key() default "";基于lambda的测试代码单个添加@Test
void addSingleLambda(){
redisBloomFilter.add(UserTicket::getTicketId,"hello");
System.out.println(redisBloomFilter.mightContain(UserTicket::getTicketId,"hello"));
System.out.println(redisBloomFilter.mightContain(UserTicket::getTicketId,"hello2"));
}多个添加@Test
void addMutileLambda(){
redisBloomFilter.add(UserTicket::getUserId,Arrays.asList("1","2","3"));
System.out.println(redisBloomFilter.mightContains(UserTicket::getUserId,Arrays.asList("1","2","4")));

}结果都是一样,然后redis的格式为,由于单个成员删除会影响到布隆过滤器准确性,即不支持删除成员,所以删除是整个键删除开启支持事务清空redis的键service代码,一个有错,一个无错package com.example.demo.service;

import com.example.demo.dao.UserTicketMapper;
import com.example.demo.entity.UserTicket;
import com.trendy.util.redis.aux.bloomfilter.autoconfigure.RedisBloomFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
* @author: lele
* @date: 2020/1/4 下午11:51
*/
@Service
public class TestService {

@Autowired
private UserTicketMapper userTicketMapper;

@Autowired
private RedisBloomFilter redisBloomFilter;

@Transactional(rollbackFor = Exception.class)
public void wrong() {
redisBloomFilter.add("news", "user2", "推送1", 500L, 0.001);
userTicketMapper.insert(new UserTicket().setCreateTime(LocalDateTime.now()).setTicketId(1L).setUserId(2L));
int i = 1 / 0;

}

@Transactional(rollbackFor = Exception.class)
public void right() {
redisBloomFilter.add("news", "user1", "推送3", 500L, 0.001);
userTicketMapper.insert(new UserTicket().setCreateTime(LocalDateTime.now()).setTicketId(1L).setUserId(2L));

}
}访问两个接口查看redis、mysql的结果 确实只有一个成功的,即user1有值(enableRedisAux的事务默认不开启) 限流功能:目前支持三种限流模式——滑动窗口限流、漏斗限流、令牌桶限流使用方式在接口上添加注解,aop会进行拦截并做相应的处理,相关注解@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@LimiterType(mode = RateLimiter.FUNNEL_LIMITER)
public @interface FunnelLimiter {

/**
* 漏斗容量
* @return
*/
double capacity();
/**
*每秒漏出的速率
* @return
*/
double passRate();
/**
*时间单位
* @return
*/
TimeUnit timeUnit() default TimeUnit.SECONDS;
/**
*每次请求所需加的水量
* @return
*/
double addWater();

Class failStrategy() default FailStrategy.DefaultStrategy.class;

String msg() default "";



}@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@LimiterType(mode = RateLimiter.TOKEN_LIMITER)
public @interface TokenLimiter {

/**
* 令牌桶容量
* @return
*/
double capacity();

/**
* 令牌生成速率
* @return
*/
double rate();

/**
* 速率时间单位,默认秒
* @return
*/
TimeUnit rateUnit() default TimeUnit.SECONDS;

/**
* 每次请求所需要的令牌数
* @return
*/
double need();

/**
* 是否阻塞等待
* @return
*/
boolean isAbort() default false;

/**
* 阻塞超时时间
* @return
*/
int timeout() default -1;

/**
* 单位,默认毫秒
* @return
*/
TimeUnit timeoutUnit() default TimeUnit.MILLISECONDS;

Class failStrategy() default FailStrategy.DefaultStrategy.class;

String msg() default "";



}package com.trendy.util.redis.aux.limiter.annonations;

import com.trendy.util.redis.aux.limiter.core.FailStrategy;
import com.trendy.util.redis.aux.limiter.core.RateLimiter;

import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;

/**
* @author: lele
* @date: 2020/1/2 下午4:11
*/


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@LimiterType(mode = RateLimiter.WINDOW_LIMITER)
public @interface WindowLimiter {
/**
* 持续时间,窗口间隔
* @return
*/
int during();

TimeUnit timeUnit() default TimeUnit.SECONDS;

/**
* 通过的请求数
* @return
*/
long value();

Class failStrategy() default FailStrategy.DefaultStrategy.class;

String msg() default "";



}其中令牌桶限流通过sleep提供阻塞等待功能,但是超时会返回false,而failStrategy可以由用户自定义并指定返回的结果,这里默认返回"too much request",而msg则是会拼接到返回信息里面去,支持spel表达式,失败策略要声明为public,否则无法实例化导致报错demo:@RestController
public class TestController {

@GetMapping("ha")
@WindowLimiter(during = 10, value = 5)
public String test() {
return "hihi1";
}
@GetMapping("ha2/{userName}")
@FunnelLimiter(capacity = 5,passRate = 0.5,addWater = 1,msg = "#userName",failStrategy = TestStragy.class)
public Result<String> test2(@PathVariable("userName")String userName) {
return Result.success("ok");
}
@GetMapping("ha3")
@TokenLimiter(capacity = 5,rate = 0.5,need = 1)
public String test3() {
return "hihi3";
}
@GetMapping("ha4")
@TokenLimiter(capacity = 1,rate = 0.5,need = 1,isAbort = true,timeout = 2000)
public String test4() {
return "hihi4";
}
@GetMapping("ha5")
@TokenLimiter(capacity = 1,rate = 0.5,need = 1,isAbort = true)
public String test5() {
return "hihi5";
}



}public class TestStragy implements FailStrategy {

@Override
public Object handle(String msg) {
return Result.success(String.format("对不起:%s,挤不进去太多人了",msg));
}
}  

redis-aux redis 辅助工具包 评论内容