honey-redis

honey-redis project for Spring Boot

License

License

Categories

Categories

Redis Data Databases
GroupId

GroupId

red.honey
ArtifactId

ArtifactId

honey-redis
Last Version

Last Version

1.1.0
Release Date

Release Date

Type

Type

jar
Description

Description

honey-redis
honey-redis project for Spring Boot
Project URL

Project URL

https://github.com/JavaYZJ/honey-redis
Source Code Management

Source Code Management

https://github.com/JavaYZJ/honey-redis.git

Download honey-redis

How to add to project

<!-- https://jarcasting.com/artifacts/red.honey/honey-redis/ -->
<dependency>
    <groupId>red.honey</groupId>
    <artifactId>honey-redis</artifactId>
    <version>1.1.0</version>
</dependency>
// https://jarcasting.com/artifacts/red.honey/honey-redis/
implementation 'red.honey:honey-redis:1.1.0'
// https://jarcasting.com/artifacts/red.honey/honey-redis/
implementation ("red.honey:honey-redis:1.1.0")
'red.honey:honey-redis:jar:1.1.0'
<dependency org="red.honey" name="honey-redis" rev="1.1.0">
  <artifact name="honey-redis" type="jar" />
</dependency>
@Grapes(
@Grab(group='red.honey', module='honey-redis', version='1.1.0')
)
libraryDependencies += "red.honey" % "honey-redis" % "1.1.0"
[red.honey/honey-redis "1.1.0"]

Dependencies

compile (9)

Group / Artifact Type Version
org.springframework.boot : spring-boot-starter jar
org.springframework.boot : spring-boot-configuration-processor Optional jar
org.springframework.boot : spring-boot-autoconfigure jar
org.springframework.boot : spring-boot-starter-data-redis jar
org.springframework.boot : spring-boot-starter-integration jar
org.springframework.integration : spring-integration-redis jar
com.alibaba : fastjson jar 1.2.72
com.fasterxml.jackson.core : jackson-databind jar 2.9.10.5
org.projectlombok : lombok Optional jar

test (1)

Group / Artifact Type Version
org.springframework.boot : spring-boot-starter-test jar

Project Modules

There are no modules declared in this project.

Honey-Redis

简介

####honey-redis 是基于Redis二次封装的一个中间件。目前里面封装实现了 Redis 五种基本数据类型的常用api、Redis全局唯一ID、Redis分布式、Redis Geo地理空间 等模块功能。

优缺点

####优点:基于springboot start 思想封装,开箱即用 ####缺点:。。。

迭代信息

版本号 更新信息
v1.0.0 Redis 五种基本数据类型的常用api、Redis全局唯一ID、Redis分布式锁三模块
v1.1.0 新增Redis Geo 模块以及接口幂等性(请求重复判断)

###1、引入依赖

    <!-- honey-redis-->
    <dependency>
        <groupId>red.honey</groupId>
        <artifactId>honey-redis</artifactId>
        <version>1.1.0</version>
    </dependency>

###2、在您的启动类上打上注解@EnableHoneyRedis

  @EnableHoneyRedis
  public class DemoApplication {
      public static void main(String[] args) {
          SpringApplication.run(DemoApplication.class, args);
      }
  }

###3、HoneyRedis封装实现了五种基本类型的api.借助IOC依赖注入即可使用.具体读者可自行阅读api

    @Autowired
    private HoneyRedis honeyRedis; 

####3.1、HoneyRedis新特性--重复请求/并发请求处理。封装在HoneyRedis组件中

    public boolean isReqDuplicate(String userId, String method, String deDuplicateParam)
  
    public boolean isReqDuplicate(String key)

###4、HoneyRedisId 封装实现了全局唯一ID,支持高并发、自定义业务前缀生成分布式唯一Id

   @SpringBootTest
   @RunWith(SpringRunner.class)
   @Slf4j
   public class HoneyRedisTest {
       // 请求总数
       public static int clientTotal = 50000;
       // 同时并发执行的线程数
       public static int threadTotal = 50000;
       @Autowired
       private HoneyRedisId honeyRedisId;
      
       @Test
       public void test() throws InterruptedException {
           ExecutorService executorService = Executors.newCachedThreadPool();
           // 信号量,此处用于控制并发的线程数
           final Semaphore semaphore = new Semaphore(threadTotal);
           // 闭锁,可实现计数器递减
           final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
           final List<String> rs = new LinkedList<>();
           for (int i = 0; i < clientTotal; i++) {
               executorService.execute(() -> {
                   try {
                       // 执行此方法用于获取执行许可,当总计未释放的许可数不超过规定threadTotal时,
                       // 允许通行,否则线程阻塞等待,直到获取到许可。
                       semaphore.acquire();
                       String id = honeyRedisId.getGloballyUniqueId("honeyRedis");
                       // 此处可替代为插入数据库,uid建立唯一索引
                       xxxService.insert(id);
                       log.info(id);
                       rs.add(id);
                       // 释放许可
                       semaphore.release();
                   } catch (Exception e) {
                       log.warn(e.getMessage());
                   }
                   // 闭锁减一
                   countDownLatch.countDown();
               });
           }
           //线程阻塞,直到闭锁值为0时,阻塞才释放,继续往下执行
           countDownLatch.await();
           executorService.shutdown();
           // 如果你不想建立数据表来验证的话,可以考虑下面这个来测试是否会
           // 生成重复的id哦
           log.info("去重前个数:{}", rs.size());
           Map<String, Long> map = rs.stream().collect(Collectors.groupingBy(p -> p, Collectors.counting()));
           List<String> repeat = new ArrayList<>();
           map.keySet().forEach(key -> {
               if (map.get(key) > 1) {
                   repeat.add(key);
               }
           });
           log.info("重复个数:{}", repeat.size());
           log.info(JSON.toJSONString(repeat));
           log.info("去重后个数:{}", rs.size() - repeat.size());
       }
   }

###5、HoneyRedisLock 这是基于Spring Boot 实现 Redis 分布式锁,是可重入的.用法与Java的lock 基本一样.

 @RestController
 @RequestMapping("/honeyRedis")
 @Slf4j
 public class HoneyRedisController {
     @Autowired
     private HoneyRedisLock honeyRedisLock;
     @GetMapping("/lock")
     @AuthSkip
     public String lock(@RequestParam("key") String key) {
         ExecutorService executorService = Executors.newCachedThreadPool();
         for (int i = 0; i < 10; i++) {
             executorService.execute(() -> {
                 boolean lock = honeyRedisLock.tryLock(key,4);
                 if (lock) {
                     try {
                         // 模拟处理业业务
                         log.info("我拿到锁了,进来执行业务处理");
                         Thread.sleep(1000L);
                     } catch (InterruptedException e) {
                         log.warn(e.getMessage());
                     }
                     log.info(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                     honeyRedisLock.unlock(key);
                 } else {
                     log.info("我拿不到锁,还等了4秒,还是拿不到锁,老子不干了");
                 }
             });
         }
         executorService.shutdown();
         return "SUCCESS";
     }
 }

###6、HoneyGeo 空间地理位置。新增空间位置出入库、空间位置坐标信息查询、空间位置距离计算、指定位置的附近空间位置查询等功能特性. ####6.1 空间位置入库.支持集合型批量加入。

public void addGeoBean(String key, List positionInfos)

参数 类型 描述
key java.lang.String redis key
PositionInfo red.honey.redis.entiy.PositionInfo 位置信息(含位置名、经纬度)
    @Before
    public void init() {

        positionInfos = new ArrayList<>();
        positionInfos.add(new PositionInfo("合肥", 117.17, 31.52));
        positionInfos.add(new PositionInfo("安庆", 117.02, 30.31));
        positionInfos.add(new PositionInfo("淮北", 116.47, 33.57));
        positionInfos.add(new PositionInfo("宿州", 116.58, 33.38));
        positionInfos.add(new PositionInfo("阜阳", 115.48, 32.54));
        positionInfos.add(new PositionInfo("蚌埠", 117.21, 32.56));
        positionInfos.add(new PositionInfo("黄山", 118.18, 29.43));
    }

    @Test
    public void testAddGeo() {
        honeyGeo.addGeoBean("HB_GEO_KEY", positionInfos);
    }

####6.2 空间位置删除 public void removeGeoBean(String key, Object... member)

参数 类型 描述
key java.lang.String redis key
member java.lang.Object 位置名
    @Test
    public void testAddGeo() {
        honeyGeo.addGeoBean("HB_GEO_KEY", positionInfos);
    }

####6.3 根据位置名获取空间坐标 public List getPosition(String key, String... member)

参数 类型 描述
key java.lang.String redis key
member java.lang.Object 位置名
    @Test
    public void testGet() {
        List<Point> position = honeyGeo.getPosition("HB_GEO_KEY", "合肥");
        System.out.println(JSON.toJSONString(position));
    }

####6.4 计算两个空间地点的距离 public Distance distance(String key, String source, String dest, Metric metric)

参数 类型 描述
key java.lang.String redis key
source java.lang.String 始发点
dest java.lang.String 目的点
metric org.springframework.data.geo.Metric 单位(默认是千米),可不传
    @Test
    public void testDistance() {
        Distance distance = honeyGeo.distance("HB_GEO_KEY", "合肥", "黄山", Metrics.KILOMETERS);
        System.out.println(JSON.toJSONString(distance));
    }

####6.5 以给定的经纬度为中心, 返回与中心的距离不超过给定最大距离的所有位置元素。 public GeoResults<RedisGeoCommands.GeoLocation> near(String key, double longitude, double latitude, long radius, Metric metric,long limit)

这个特性最为有用,可以做“附件的xxx”功能,像共享单车的附近的车、美团的附近的餐馆等等

参数 类型 描述
key java.lang.String redis key
longitude double 经度
dest double 纬度
radius long 半径(最大距离)
metric org.springframework.data.geo.Metric 单位(默认是千米),可不传
limit long 返回个数
    @Test
    public void testNear(){
        GeoResults<RedisGeoCommands.GeoLocation<Object>> results = honeyGeo.near("HB_GEO_KEY", 118.18, 29.43, 5, 5);
        System.out.println(JSON.toJSONString(results));
    }

####6.6 以给定的位置为中心, 返回与中心的距离不超过给定最大距离的所有位置元素。 public GeoResults<RedisGeoCommands.GeoLocation> nearByPlace(String key, String member, long radius, Metric metric, long limit)

参数 类型 描述
key java.lang.String redis key
member java.lang.String 位置名
radius long 半径(最大距离)
metric org.springframework.data.geo.Metric 单位(默认是千米),可不传
limit long 返回个数
    @Test
    public void testNearPlace(){
        GeoResults<RedisGeoCommands.GeoLocation<Object>> results = honeyGeo.nearByPlace("HB_GEO_KEY", "合肥", 200, 5);
        System.out.println(JSON.toJSONString(results));
    }

####6.7 计算位置的hash public List geoHash(String key, String... members)

参数 类型 描述
key java.lang.String redis key
member java.lang.String 位置名
    @Test
    public void testHash(){
        List<String> list = honeyGeo.geoHash("HB_GEO_KEY", "黄山");
        System.out.println(JSON.toJSONString(list));
    }

####未完待续, thanks!

Versions

Version
1.1.0
1.0.0