`

Redis实战9-全局唯一ID

 
阅读更多

发布优惠券的时候,每个店铺都可以发布优惠券,当用户抢购的时候,优惠券表中的id如果使用数据库的自增长ID会存在以下问题:

1:id的规律太明显,容易被刷

2:当数据量很大的时候,会受到单表数据的限制

缺点场景分析:

id规律场景:如果我们的id具有太明显的规则,用户或者说商业对手很容易猜测出来我们的一些敏感信息,比如商城在一天时间内,卖出了多少单,这明显不合适。

单表限制:随着我们商城规模越来越大,mysql的单表的容量不宜超过500W,数据量过大之后,我们要进行拆库拆表,但拆分表了之后,他们从逻辑上讲他们是同一张表,所以他们的id是不能一样的, 于是乎我们需要保证id的唯一性。

全局ID生成器

全局ID生成器,是一种在分布式系统下用来生成全局唯一的ID工具,一般需要瞒住下列特性:

唯一性、高可用、递增性、安全性、高性能

71ed2335099c6f90fd97e5b7aa9b2e81.png

全局唯一ID生成策略:

UUID、Redis自增长、雪花算法、数据库自增

Redis自增ID策略:

1:每天一个key,方便统计订单量;

2:ID都在是时间戳+计数器

实战:基于Redis拼接其他信息来实现全局唯一ID

d1eda313100802c0e06709274b2a0632.png

全局唯一ID使用long类型的,其中时间戳是基于某一个时间点开始的。比如我们从2022.11.26 23:00:00开始,可以使用69年。

思考1:获取当前时间的秒:

3f7e603ec908f8c2febd76a5d53ea9ad.png

思考2:时间戳,怎么计算的?

使用当前时间的秒-初始时间的秒

思考3:序列号怎么设置?

使用Redis的setnx命令,最好加上当前年月日

7c56056dbdba82c428ecb1c96ea7d280.png

思考4:怎么拼接?

因为我们需要返回的是long类型的,如果使用string拼接后,还要转换。还要知道,使用string拼接,当并发量很大的时候,也会有性能问题。那么我们应该怎么处理的?

注意:我们再来看看全局唯一ID的格式。如上图,我们可以看出,共64位,其中符号位是1个,时间戳是31位。序列号是32位,发现什么了吗?如果我们把时间戳向左移动32位(因为序列号是32位。向左移动位置,空出给序列号使用),是不是就是符号位+时间戳的了?

1:我们也知道计算机中左移动最快是x<<位数。

2:我们还需要知道,在计算机中 | 或计算:按位或运算“|”

f4f158cc14263b984ab3ccfe990d6e2b.png

根据上面,我们可以知道位运算序号后,就是序列号的值。序列号是多少,就是多少。

所以,我们可以知道拼接代码如下:timeStamp << 32 |no;

最终代码:

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;
 
/**
 * @author 凯哥Java
 * @description  基于Redis实现62位的全局唯一ID
 * @company
 *  */
@Component
public class RedisIdWorker {
 
    private static final long BEGIN_TIMESTAMP = 1669503600L;
 
 
    private final StringRedisTemplate stringRedisTemplate;
 
    /**
     * 序列号的位数
     */
    private static final int COUNT_BITS = 32;
 
    public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }
 
    /**
     * 获取id
     * @param kyePrefix
     * @return
     */
    public long nextId(String kyePrefix){
        //1:生成时间戳 = 当前时间戳-开始时间戳
        LocalDateTime now = LocalDateTime.now();
        long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
        long timeStamp = nowSecond - BEGIN_TIMESTAMP;
 
        //2:生成序列号.使用sexNx.其中加上当前年月日
        //获取当前时间的你那月日
        String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
        //开始32位序列号
        long  no = stringRedisTemplate.opsForValue().increment("icr:"+kyePrefix+":"+date);
        //3:拼接返回
        return timeStamp << COUNT_BITS |no;
 
    }
    /**
     * 获取到指定时间的毫秒
     * @param args
     */
    public static void main(String[] args) {
        LocalDateTime time = LocalDateTime.of(2022,11,26,23,00,00);
        long second = time.toEpochSecond(ZoneOffset.UTC);
        System.out.println(second);
 
    }
}
 
测试:使用多线程及countdownlatch
private ExecutorService executorService = Executors.newFixedThreadPool(500);
 
    @Resource
    private RedisIdWorker redisIdWorker;
 
    @Test
    public void RedisIdWorkerTest() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(300);
        Runnable task = ()->{
            for(int i = 0;i<100;i++){
                long id = redisIdWorker.nextId("myorder");
                System.out.println(id);
            }
            latch.countDown();
        };
 
        long begin = System.currentTimeMillis();
        for(int i = 0;i< 300;i++){
            executorService.submit(task);
        }
        latch.await();
        long endTime = System.currentTimeMillis();
        System.out.println("耗时:"+(endTime-begin));
    }

 

 

 

 

分享到:
评论

相关推荐

    Redis教程实战篇 点评项目,用于学习Redis实战,实战篇代码已完-hm-dianping.zip

    **Redis实战教程——基于点评项目的应用** 在本教程中,我们将深入探讨如何使用Redis这个高性能的键值存储系统来实现一个点评项目的实际应用场景。Redis以其出色的数据结构支持、高速读写性能以及丰富的功能,被...

    Redis面试题深度解析:技术要点与实战应用.zip

    - 分布式ID生成:利用Redis自增操作生成全局唯一ID。 - 任务队列:使用Redis的List作为消息队列。 通过以上内容,我们可以看到Redis不仅是一个简单的键值存储,还具备强大的功能和广泛的应用场景。在面试中,深入...

    java抢红包源码-agan-redis-open:agan-redis-open

    java抢红包源码 一:redis分布式缓存(String专题) redis安装部署 ...淘宝商品分布式全局id 1. 为什么分布式系统需要全局唯一id ? 2. 全局唯一id必须具备什么特点 ? 3. 剖析淘宝商品id的特点 4. 基于Redis

    Windows环境下java对Redis的各项操作及实例

    - 分布式ID生成:使用有序集合生成全局唯一ID。 - 用户会话管理:存储用户会话信息,实现跨服务器的会话共享。 通过以上内容,你将能够理解如何在Windows环境中安装和配置Redis,并使用Java进行各种操作。在实际...

    redis的使用实战教程

    此外,Redisson 是一个Java客户端库,它提供了对Redis的全面支持,包括分布式锁、分布式ID生成器等高级功能。 Redis 的内存管理策略包括LRU(Least Recently Used)和LFU(Least Frequently Used)等,可以根据实际...

    Redis开发电商网站.rar

    11. **分布式ID生成**:Snowflake算法结合Redis可以生成全局唯一的订单ID,保证订单数据的一致性和可追踪性。 12. **数据预热**:在大促活动前,预先加载高流量数据到Redis,避免活动开始时因大量请求导致的延迟。 ...

    Java分布式实战指南.pdf

    另外,通过雪花算法生成高并发下的分布式全局ID,保证了ID的唯一性。Redis也被用于实现分布式Session,解决用户会话在不同服务器间共享的问题。Sleuth与ZipKin结合,提供了服务追踪与调用链,帮助开发者理解微服务间...

    黑马点评项目个人笔记+项目优化调整

    - **分布式ID生成**:项目中使用Redis生成全局唯一ID,这是一种常见的应用场景,通常采用递增的方式来实现。 - **分布式锁**:尽管本文档未提及自研分布式锁的内容,但理解其实现原理(如使用SETNX指令或RedLock...

    spring cloud实战项目

    分布式实战涉及到的内容更广泛,包括分布式事务(Seata、TCC等)、分布式ID(Snowflake、UUID等)、分布式锁(Redis、Zookeeper等)、分布式日志追踪(Zipkin、Sleuth)等。这些技术的合理应用能够提高系统的稳定性...

    Java面试专属视频

    面试必考之HashMap源码分析与实现 ,微服务架构之Spring Cloud Eureka 场景...锁、分布式锁、无锁实战全局性IDSpringMvc深入理解源码分析 Nosql Redis Jedis常用命令 JAVA并发编程之多线程并发同步业务场景与解决方案

    Python+MySQL分表分库实战

    接着,我们会详细探讨创建新表结构的步骤,并讲解如何使用Snowflake全局ID生成器来解决分布式系统中ID生成的问题。同时,本教程还将指导读者如何进行数据迁移和查询操作,确保在分表分库后依然能够高效地对数据进行...

    架构师培训教程 大数据高并发服务器实战 第2.4篇-LNMP部分-Nginx部分-基本配置 共30页.pptx

    此外,Nginx还能与其他技术如Java(Tomcat)、Memcached和Redis集成,实现更复杂的业务需求。在后续的课程中,还会涉及Nginx的虚拟主机配置、反向代理和负载均衡,以及Rewrite功能,这些都是构建高效网络服务的重要...

    Java思维导图xmind文件+导出图片

    分布式全局ID生成方案 session跨域共享及企业级单点登录解决方案实战 分布式事务解决方案实战 高并发下的服务降级、限流实战 基于分布式架构下分布式锁的解决方案实战 分布式架构实现分布式定时调度 分布式...

    微服务架构专题-SpringBoot.pptx

    - **统一ID生成服务**:设计和实现一个能够为整个分布式系统提供全局ID的服务。 - **分布式配置服务**:例如Spring Cloud Config,它可以作为一个集中式配置中心,使得配置管理变得更加简单。 6. **Spring Cloud...

    第二代微服务电商项目实战笔记

    6. **雪花算法**: 生成全局唯一ID,适用于分布式系统中的主键生成。 7. **Spring-Session**: 分布式Session管理,解决了单体应用拆分成微服务后Session共享的问题。 8. **ZipKin**: 分布式服务追踪系统,用于构建...

    B站 (锋迷商城) 学习资料

    分布式数据库中间件Mycat/Sharding-jdbc、分布式事务Seata、分布式全局ID、接口幂等性、SpringCloud之Eureka服务治理、SpringCloud之Ribbon和Feign、SpringCloud之Hystrix和Config、SpringCloud之ZUUL(Gateway)和...

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    锁、分布式锁、无锁实战全局性ID-悟空.mp4 │ │ │ ├─4.SpringMvc深入理解源码分析 │ │ 4.SpringMvc深入理解源码分析-悟空.mp4 │ │ │ ├─5.Nosql Redis Jedis常用命令 │ │ 5.Nosql Redis Jedis常用命令...

    零声学院 第9代 Linux CC++后台架构开发 成长体系课程 - v1.21

    另外,还涉及了Redis缓存系统,包括其全局唯一ID保存机制、消息队列、事务、安全性能以及备份恢复。Nginx作为反向代理服务器,其配置与负载均衡、自定义协议开发也是该专题的重要内容。 **源码分析专题**深入探讨了...

    2019java亲生经历面试题答案解析准备.zip

    14.分库分表之后分布式下如何保证ID全局唯一性 10道腾讯的Java面试题.txt Dubbo面试题锦集.txt 阿里巴巴高级Java面试题(首发,70道).doc 春节跳槽最新Java面试题及答案整理.txt 分享18道Java基础面试笔试题(面试...

Global site tag (gtag.js) - Google Analytics