diff --git a/READ.md b/READ.md index 05b296f163b07026dab7ca1d7bb63f00ac56d6b7..3dee3982d3cc49b0d4478e76336ca5536d7602fa 100644 --- a/READ.md +++ b/READ.md @@ -33,6 +33,8 @@ - 乱码问题 WebMvcConfigurationSupport - 批处理 + +- redis 全局唯一id ## 三.链接 diff --git a/src/main/java/com/kwan/springbootkwan/utils/GoodsRankService.java b/src/main/java/com/kwan/springbootkwan/utils/GoodsRankService.java new file mode 100644 index 0000000000000000000000000000000000000000..b96dd359db5ed1c0ba7c18d04762f0eca0ea5bc8 --- /dev/null +++ b/src/main/java/com/kwan/springbootkwan/utils/GoodsRankService.java @@ -0,0 +1,90 @@ +package com.kwan.springbootkwan.utils; + +import redis.clients.jedis.Jedis; +import redis.clients.jedis.Tuple; + +import java.util.Set; + +/** + * 商品排序 + * + * @author : qinyingjie + * @version : 2.2.0 + * @date : 2022/12/22 10:01 + */ +public class GoodsRankService { + + private static Jedis jedis; + + static { + jedis = new Jedis("120.79.36.53", 6379); + } + + /** + * 排序的Key + */ + private static String KEY = "goods"; + + public static void removeOne() { + /** + * zrem——移除某个商品 + * 命令格式:***zrem 排行榜名称 商品标识*** 时间复杂度:O(log(N)) + */ + Long aLong = jedis.zrem(KEY, "god-10"); + } + + public static void addScore() { + /** + * zincrby——增减商品分数 + * 命令格式:***zincrby 排行榜名称 分数增量 商品标识*** 时间复杂度:O(log(N)) + * 有的排行榜是在变更时重新设置商品的分数,而还有的排行榜则是以增量方式修改商品分数,增量可正可负。如果执行zincrby时商品尚不在排行榜中,则认为其原始分数为0,相当于执行zdd。 + */ + Double zincrby = jedis.zincrby(KEY, 1, "god-10"); + System.out.println(zincrby); + } + + public static void getNum() { + /** + * zrevrank——查看商品的排名 + * 命令格式:***zrevrank 排行榜名称 商品标识*** 时间复杂度:O(log(N)) + * 与zrevrange类似,zrevrank是以分数由高到低的排序返回商品排名(实际返回的是以0开始的索引),对应的zrank则是以分数由低到高的排序返回排名。 + */ + Long aLong = jedis.zrevrank(KEY, "god-10"); + System.out.println(aLong); + Long aLong2 = jedis.zrevrank(KEY, "god-1000"); + System.out.println(aLong2); + } + + public static void getRange() { + /** + * zrevrange——按名次查看排行榜 + * 命令格式:***zrevrange 排行榜名称 起始位置 结束位置 [withscores]*** 时间复杂度:O(log(N)+M) + * 由于排行榜一般是按照分数由高到低排序的,所以我们使用zrevrange,而命令zrange是按照分数由低到高排序。 + * 起始位置和结束位置都是以0开始的索引,且都包含在内。如果结束位置为-1则查看范围为整个排行榜。 + * 带上withscores则会返回商品分数。 + */ + Set zrevrange = jedis.zrevrange(KEY, 2, 5); + zrevrange.forEach(System.out::println); + Set set = jedis.zrangeWithScores(KEY, 2, 5); + set.forEach(System.out::println); + } + + public static void getData() { + /** + * zscore——查看商品分数 + * 命令格式:***zscore 排行榜名称 商品标识*** 时间复杂度:O(1) + */ + Double zscore = jedis.zscore(KEY, "go-20"); + System.out.println(zscore); + } + + public static void setData() { + for (int i = 0; i < 100; i++) { + /** + * zadd——设置商品分数 + * 命令格式:***zadd 排行榜名称 分数 商品名字 时间复杂度:O(log(N)) + */ + jedis.zadd(KEY, i, "go-" + i); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/kwan/springbootkwan/utils/RedisIdWorker.java b/src/main/java/com/kwan/springbootkwan/utils/RedisIdWorker.java new file mode 100644 index 0000000000000000000000000000000000000000..227e538e2f281ba77af160d83a3aca2d908de693 --- /dev/null +++ b/src/main/java/com/kwan/springbootkwan/utils/RedisIdWorker.java @@ -0,0 +1,49 @@ +package com.kwan.springbootkwan.utils; + +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; + +/** + * 全局唯一id + * + * @author : qinyingjie + * @version : 2.2.0 + * @date : 2022/12/21 17:12 + */ +@Component +public class RedisIdWorker { + /** + * 开始时间戳 + */ + private static final long BEGIN_TIMESTAMP = 1640995200L; + /** + * 序列号的位数 + */ + private static final int COUNT_BITS = 32; + + private final StringRedisTemplate stringRedisTemplate; + + public RedisIdWorker(StringRedisTemplate stringRedisTemplate) { + this.stringRedisTemplate = stringRedisTemplate; + } + + public long nextId(String keyPrefix) { + // 1.生成时间戳 + LocalDateTime now = LocalDateTime.now(); + long nowSecond = now.toEpochSecond(ZoneOffset.UTC); + long timestamp = nowSecond - BEGIN_TIMESTAMP; + + // 2.生成序列号 + // 2.1.获取当前日期,精确到天 + String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd")); + // 2.2.自增长 + long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date); + + // 3.拼接并返回 + return timestamp << COUNT_BITS | count; + } +} diff --git a/src/test/java/com/kwan/springbootkwan/UserServiceImplTest.java b/src/test/java/com/kwan/springbootkwan/UserServiceImplTest.java index fc07814460dcd34a2c060a9cfed3cad11baa72b7..b721ae18423f3ac25291a597ba964be757d9e83c 100644 --- a/src/test/java/com/kwan/springbootkwan/UserServiceImplTest.java +++ b/src/test/java/com/kwan/springbootkwan/UserServiceImplTest.java @@ -4,6 +4,7 @@ import com.kwan.springbootkwan.entity.MailInfo; import com.kwan.springbootkwan.entity.User; import com.kwan.springbootkwan.mapper.UserMapper; import com.kwan.springbootkwan.service.ISendMsgHandle; +import com.kwan.springbootkwan.utils.RedisIdWorker; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -11,6 +12,9 @@ import org.springframework.boot.test.context.SpringBootTest; import java.util.Date; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; @SpringBootTest @@ -101,4 +105,32 @@ public class UserServiceImplTest { mailBean.setImageMap(image); emailSendMsgHandle.sendEnclosureEmail(mailBean); } + + @Autowired + private RedisIdWorker redisIdWorker; + + private ExecutorService es = Executors.newFixedThreadPool(500); + + + @Test + public void testWorkerId() throws InterruptedException { + CountDownLatch latch = new CountDownLatch(300); + Runnable task = () -> { + for (int i = 0; i < 100; i++) { + long id = redisIdWorker.nextId("order"); + System.out.println("id = " + id); + } + latch.countDown(); + }; + + long begin = System.currentTimeMillis(); + for (int i = 0; i < 300; i++) { + es.submit(task); + } + latch.await(); + long end = System.currentTimeMillis(); + System.out.println("times = " + (end- begin)); + + } + } \ No newline at end of file