销售网站的销量统计怎么做在线免费看影视网站
2026/4/23 6:17:11 网站建设 项目流程
销售网站的销量统计怎么做,在线免费看影视网站,网站维护收费标准,安徽鑫华建设有限公司网站目录 雪花算法 百度UidGenerator 雪花实现创建ID 分布式ID在构建大规模分布式系统时扮演着至关重要的角色#xff0c;主要用于确保在分布式环境中数据的唯一性和一致性。 雪花算法 SnowFlake算法是Twitter开源的分布式ID生成算法。核心思想就是#xff1a;使用一个64 bit的…目录雪花算法百度UidGenerator雪花实现创建ID分布式ID在构建大规模分布式系统时扮演着至关重要的角色主要用于确保在分布式环境中数据的唯一性和一致性。雪花算法SnowFlake算法是Twitter开源的分布式ID生成算法。核心思想就是使用一个64 bit的 long 型的数字作为全局唯一ID。算法中还引入了时间戳基本上保证了自增特性。其特点是将64位的long型ID分为四个部分分别为时间戳、机器ID和序列号由于在 Java 中 64bit 的整数是 long 类型所以在 Java 中 SnowFlake 算法生成的 id 就是 long 来存储的。而对于每一个雪花算法服务需要先指定 10 位的机器码这个根据自身业务进行设定即可。例如机房号机器号机器号服务号或者是其他可区别标识的 10 位比特位的整数值都行。最终效果是Snowflake算法给出的唯一 ID生成器是一个支持多机房共1024个服务 实例规模、单个服务实例每秒可生成410万个long类型唯一 ID的分布式系统且此系统可以正常工作69年。优缺点高并发分布式环境下生成不重复 id每秒可生成百万个不重复 id。基于时间戳以及同一时间戳下序列号自增基本保证 id 有序递增。不依赖第三方库或者中间件。算法简单在内存中进行效率高。依赖服务器时间服务器时钟回拨时可能会生成重复 id。算法中可通过记录最后一个生成 id 时的时间戳来解决每次生成 id 之前比较当前服务器时钟是否被回拨避免生成重复 id。实现publicclassSnowFlake{/** * 起始的时间戳可设置当前时间之前的邻近时间 */privatefinalstaticlongSTART_STAMP1480166465631L;/** * 序列号占用的位数 */privatefinalstaticlongSEQUENCE_BIT12;/** * 机器标识占用的位数 */privatefinalstaticlongMACHINE_BIT5;/** * 数据中心占用的位数 */privatefinalstaticlongDATA_CENTER_BIT5;/** * 每一部分的最大值 */privatefinalstaticlongMAX_DATA_CENTER_NUM~(-1L DATA_CENTER_BIT);privatefinalstaticlongMAX_MACHINE_NUM~(-1L MACHINE_BIT);privatefinalstaticlongMAX_SEQUENCE~(-1L SEQUENCE_BIT);/** * 每一部分向左的位移 */privatefinalstaticlongMACHINE_LEFTSEQUENCE_BIT;privatefinalstaticlongDATA_CENTER_LEFTSEQUENCE_BIT MACHINE_BIT;privatefinalstaticlongTIMESTAMP_LEFTDATA_CENTER_LEFT DATA_CENTER_BIT;/** * 数据中心ID(0~31) */privatefinallongdataCenterId;/** * 工作机器ID(0~31) */privatefinallongmachineId;/** * 毫秒内序列(0~4095) */privatelongsequence0L;/** * 上次生成ID的时间截 */privatelonglastStamp-1L;publicSnowFlake(longdataCenterId,longmachineId){if(dataCenterId MAX_DATA_CENTER_NUM || dataCenterId 0) {thrownewIllegalArgumentException(dataCenterId cant be greater than MAX_DATA_CENTER_NUM or less than 0); }if(machineId MAX_MACHINE_NUM || machineId 0) {thrownewIllegalArgumentException(machineId cant be greater than MAX_MACHINE_NUM or less than 0); }this.dataCenterId dataCenterId;this.machineId machineId; }/** * 产生下一个ID */publicsynchronizedlongnextId(){longcurrStampgetNewStamp();if(currStamp lastStamp) {thrownewRuntimeException(Clock moved backwards. Refusing to generate id); }if(currStamp lastStamp) {//相同毫秒内序列号自增sequence (sequence 1) MAX_SEQUENCE;//同一毫秒的序列数已经达到最大if(sequence 0L) {//阻塞到下一个毫秒,获得新的时间戳currStamp getNextMill(); } }else{//不同毫秒内序列号置为0sequence 0L; } lastStamp currStamp;// 移位并通过或运算拼到一起组成64位的IDreturn(currStamp - START_STAMP) TIMESTAMP_LEFT//时间戳部分| dataCenterId DATA_CENTER_LEFT//数据中心部分| machineId MACHINE_LEFT//机器标识部分| sequence;//序列号部分}privatelonggetNextMill(){longmillgetNewStamp();while(mill lastStamp) { mill getNewStamp(); }returnmill; }privatelonggetNewStamp(){returnSystem.currentTimeMillis(); }publicstaticvoidmain(String[] args){SnowFlakesnowFlakenewSnowFlake(11,11);longstartSystem.currentTimeMillis();for(inti0; i 10; i) { System.out.println(snowFlake.nextId()); } System.out.println(System.currentTimeMillis() - start); } }博客地址分布式系列之ID生成器_分布式id生成器-CSDN博客https://blog.csdn.net/lonelymanontheway/article/details/104532828?ops_request_misc%257B%2522request%255Fid%2522%253A%25221e5d88ad71cd69252001b52b0da29ef4%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257Drequest_id1e5d88ad71cd69252001b52b0da29ef4biz_id0utm_mediumdistribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-104532828-null-null.142^v102^pc_search_result_base8utm_term%E5%88%86%E5%B8%83%E5%BC%8FId%E7%94%9F%E6%88%90%E5%99%A8spm1018.2226.3001.4187分布式唯一ID生成器 最详解-CSDN博客https://blog.csdn.net/2402_82958989/article/details/148616323?ops_request_miscrequest_idbiz_id102utm_term%E5%88%86%E5%B8%83%E5%BC%8FId%E7%94%9F%E6%88%90%E5%99%A8utm_mediumdistribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-148616323.142^v102^pc_search_result_base8spm1018.2226.3001.4187百度UidGeneratorUidGenerator 是Java实现的, 基于Snowflake算法的唯一ID生成器。UidGenerator 以组件形式工作在应用项目中, 支持自定义 workerId 位数和初始化策略, 从而适用于docker等虚拟化环境下实例自动重启、漂移等场景。在实现上UidGenerator 通过借用未来时间来解决 sequence 天然存在的并发限制采用 RingBuffer 来缓存已生成的 UID, 并行化 UID 的生产和消费, 同时对 CacheLine 补齐避免了由 RingBuffer 带来的硬件级「伪共享」问题. 最终单机 QPS 可达600万。项目地址分布式系列之ID生成器_分布式id生成器-CSDN博客https://blog.csdn.net/lonelymanontheway/article/details/104532828?ops_request_misc%257B%2522request%255Fid%2522%253A%25221e5d88ad71cd69252001b52b0da29ef4%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257Drequest_id1e5d88ad71cd69252001b52b0da29ef4biz_id0utm_mediumdistribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-104532828-null-null.142^v102^pc_search_result_base8utm_term%E5%88%86%E5%B8%83%E5%BC%8FId%E7%94%9F%E6%88%90%E5%99%A8spm1018.2226.3001.4187​Snowflake 算法描述指定机器 同一时刻 某一并发序列是唯一的。据此可生成一个 64 bits的唯一IDlong。默认采用上图字节分配方式sign(1bit)固定1bit符号标识即生成的UID为正数。delta seconds (28 bits)当前时间相对于时间基点2016-05-20的增量值单位秒最多可支持约8.7年worker id (22 bits)机器id最多可支持约420w次机器启动。内置实现为在启动时由数据库分配默认分配策略为用后即弃后续可提供复用策略。sequence (13 bits)每秒下的并发序列13 bits可支持每秒8192个并发。项目解析地址【分布式 ID】详解百度 uid-generator基础篇_uidgenerator-CSDN博客https://blog.csdn.net/laohuangaa/article/details/148881448雪花实现创建ID下面代码方案通过Spring 自动装配 Redis Lua在应用启动时全局唯一地分配workId / dataCenterId并将其注入到SnowflakeIdGenerator中作为单例使用。DatapublicclassWorkDataCenterId{/** * Snowflake 中的 workerId * 用来区分不同机器 / 实例 */privateLong workId;/** * Snowflake 中的 dataCenterId * 用来区分不同机房 / 集群 */privateLong dataCenterId; }publicclassIdGeneratorAutoConfig{/** * 将 WorkAndDataCenterIdHandler 注册为 Spring Bean * * 作用 * - 管理 Redis Lua 分配逻辑 * - 整个应用生命周期只需要一个实例 */BeanpublicWorkAndDataCenterIdHandlerworkAndDataCenterIdHandler( StringRedisTemplate stringRedisTemplate){returnnewWorkAndDataCenterIdHandler(stringRedisTemplate); }/** * 在 Spring 启动阶段就获取 workId / dataCenterId * * - 只在启动时执行一次 * - 不是每次生成 ID 都访问 Redis */BeanpublicWorkDataCenterIdworkDataCenterId( WorkAndDataCenterIdHandler workAndDataCenterIdHandler){returnworkAndDataCenterIdHandler.getWorkAndDataCenterId(); }/** * 创建 SnowflakeIdGenerator * * 依赖 * - WorkDataCenterId * * 最终效果 * - SnowflakeIdGenerator 是一个全局单例 * - workId / dataCenterId 固定 */BeanpublicSnowflakeIdGeneratorsnowflakeIdGenerator( WorkDataCenterId workDataCenterId){returnnewSnowflakeIdGenerator(workDataCenterId); } }publicclassIdGeneratorConstant{/** * 机器标识位数 */publicstaticfinallongWORKER_ID_BITS5L;publicstaticfinallongDATA_CENTER_ID_BITS5L;publicstaticfinallongMAX_WORKER_ID-1L^ (-1L WORKER_ID_BITS);publicstaticfinallongMAX_DATA_CENTER_ID-1L^ (-1L DATA_CENTER_ID_BITS); }Slf4j// Lombok 注解自动生成 private static final Logger logpublicclassWorkAndDataCenterIdHandler{/** * Redis 中用于记录 snowflake workerId 的 key * 本质是一个全局自增 / 分配标识 */privatefinalStringSNOWFLAKE_WORK_ID_KEYsnowflake_work_id;/** * Redis 中用于记录 snowflake dataCenterId 的 key */privatefinalStringSNOWFLAKE_DATA_CENTER_ID_keysnowflake_data_center_id;/** * Lua 脚本执行时使用的 KEYS 列表 * 对应 Lua 中的 * KEYS[1] - snowflake_work_id * KEYS[2] - snowflake_data_center_id */publicfinalListString keys Stream.of(SNOWFLAKE_WORK_ID_KEY, SNOWFLAKE_DATA_CENTER_ID_key) .collect(Collectors.toList());/** * Spring 提供的 Redis 操作模板 * 用来执行 Lua 脚本 */privateStringRedisTemplate stringRedisTemplate;/** * Redis Lua 脚本封装对象 * Spring 用它来执行 Lua 并解析返回值 */privateDefaultRedisScriptString redisScript;/** * 构造方法由 Spring 注入 StringRedisTemplate */publicWorkAndDataCenterIdHandler(StringRedisTemplate stringRedisTemplate){this.stringRedisTemplate stringRedisTemplate;try{// 创建 Lua 脚本执行对象redisScript newDefaultRedisScript();// 加载 classpath 下的 lua/workAndDataCenterId.luaredisScript.setScriptSource(newResourceScriptSource(newClassPathResource(lua/workAndDataCenterId.lua) ) );// 指定 Lua 返回值类型这里返回 JSON 字符串redisScript.setResultType(String.class); }catch(Exception e) {// Lua 脚本初始化失败直接记录错误log.error(redisScript init lua error, e); } }/** * 从 Redis 中获取或分配workId 和 dataCenterId * *returnWorkDataCenterId包含 workId 和 dataCenterId */publicWorkDataCenterIdgetWorkAndDataCenterId(){// 返回对象WorkDataCenterIdworkDataCenterIdnewWorkDataCenterId();try{/** * Lua 脚本的 ARGV 参数 */String[] data newString[2]; data[0] String.valueOf(IdGeneratorConstant.MAX_WORKER_ID); data[1] String.valueOf(IdGeneratorConstant.MAX_DATA_CENTER_ID);/** * 执行 Lua 脚本 */StringresultstringRedisTemplate.execute(redisScript, keys, data);/** * Lua 返回的是 JSON 字符串 * 例如 * {workId:3,dataCenterId:1} */workDataCenterId JSON.parseObject(result, WorkDataCenterId.class); }catch(Exception e) { log.error(getWorkAndDataCenterId error, e); }returnworkDataCenterId; } }WorkAndDataCenterIdHandler是执行lua脚本的执行器执行完脚本后获得了WorkDataCenterId的实体包好了workId和dataCenterIdWorkDataCenterId在注入到spring上下文的过程中就调用了WorkAndDataCenterIdHandler#getWorkAndDataCenterId方法在redis中加载workId和dataCenterId下面就来分析下加载获取workId和dataCenterId的详细过程① 保证workId / dataCenterId在 Redis 中存在初始化如果 Redis 里还没有那么第一次启动的第一个实例会把它们都初始化为0② 判断是不是“第一次初始化的实例”如果两个 key 都是本次脚本创建的说明这是整个集群里的第一个服务实例直接返回{ workId: 0, dataCenterId: 0 }③ 非第一次启动 → 开始“编号分配”后续实例进来读取当前workId 和 dataCenterId然后按一个双层计数器逻辑分配优先增长 workIdworkId 用完 → 推进 dataCenterId两者都用完 → 全部归零情况行为workId maxWorkerIdworkId 自增workId maxWorkerId 且 dataCenterId maxDataCenterIddataCenterId 自增workId max dataCenterId max两个都重置为 0④ 返回一个 JSON 给 Java{workId:3,dataCenterId:1}-- redis中work_id的keylocalsnowflake_work_id_key KEYS[1]-- redis中data_center_id的keylocalsnowflake_data_center_id_key KEYS[2]-- worker_id的最大阈值localmax_worker_id tonumber(ARGV[1])-- data_center_id的最大阈值localmax_data_center_id tonumber(ARGV[2])-- 返回的work_idlocalreturn_worker_id 0-- 返回的data_center_idlocalreturn_data_center_id 0-- work_id初始化flaglocalsnowflake_work_id_flag false-- data_center_id初始化flaglocalsnowflake_data_center_id_flag false-- 构建并返回JSON字符串localjson_result string.format({%s: %d, %s: %d},workId, return_worker_id,dataCenterId, return_data_center_id)-- 如果work_id不存在则将值初始化为0if(redis.call(exists, snowflake_work_id_key) 0)thenredis.call(set,snowflake_work_id_key,0) snowflake_work_id_flag trueend-- 如果data_center_id不存在则将值初始化为0if(redis.call(exists, snowflake_data_center_id_key) 0)thenredis.call(set,snowflake_data_center_id_key,0) snowflake_data_center_id_flag trueend-- 如果work_id和data_center_id都是初始化了那么执行返回初始化的值if(snowflake_work_id_flagandsnowflake_data_center_id_flag)thenreturnjson_resultend-- 获得work_id的值localsnowflake_work_id tonumber(redis.call(get,snowflake_work_id_key))-- 获得data_center_id的值localsnowflake_data_center_id tonumber(redis.call(get,snowflake_data_center_id_key))-- 如果work_id的值达到了最大阈值if(snowflake_work_id max_worker_id)then-- 如果data_center_id的值也达到了最大阈值if(snowflake_data_center_id max_data_center_id)then-- 将work_id的值初始化为0redis.call(set,snowflake_work_id_key,0)-- 将data_center_id的值初始化为0redis.call(set,snowflake_data_center_id_key,0)else-- 如果data_center_id的值没有达到最大值将进行自增并将自增的结果返回return_data_center_id redis.call(incr,snowflake_data_center_id_key)endelse-- 如果work_id的值没有达到最大值将进行自增并将自增的结果返回return_worker_id redis.call(incr,snowflake_work_id_key)endreturnstring.format({%s: %d, %s: %d},workId, return_worker_id,dataCenterId, return_data_center_id)​这样将得到了加载后的包含datacenterId和workerId的WorkDataCenterId对象当创建SnowflakeIdGenerator时将WorkDataCenterId注入进去注入datacenterId和workerId代码publicSnowflakeIdGenerator(WorkDataCenterId workDataCenterId){if(Objects.nonNull(workDataCenterId.getDataCenterId())) {this.workerId workDataCenterId.getWorkId();this.datacenterId workDataCenterId.getDataCenterId(); }else{this.datacenterId getDatacenterId(maxDatacenterId); workerId getMaxWorkerId(datacenterId, maxWorkerId); } }Slf4jpublicclassSnowflakeIdGenerator{/** * 时间起始标记点作为基准一般取系统的最近时间一旦确定不能变动 */privatestaticfinallongBASIS_TIME1288834974657L;/** * 机器标识位数 */privatefinallongworkerIdBits5L;privatefinallongdatacenterIdBits5L;privatefinallongmaxWorkerId-1L^ (-1L workerIdBits);privatefinallongmaxDatacenterId-1L^ (-1L datacenterIdBits);/** * 毫秒内自增位 */privatefinallongsequenceBits12L;privatefinallongworkerIdShiftsequenceBits;privatefinallongdatacenterIdShiftsequenceBits workerIdBits;/** * 时间戳左移动位 */privatefinallongtimestampLeftShiftsequenceBits workerIdBits datacenterIdBits;privatefinallongsequenceMask-1L^ (-1L sequenceBits);privatefinallongworkerId;/** * 数据标识 ID 部分 */privatefinallongdatacenterId;/** * 并发控制 */privatelongsequence0L;/** * 上次生产 ID 时间戳 */privatelonglastTimestamp-1L;/** * IP 地址 */privateInetAddress inetAddress;publicSnowflakeIdGenerator(WorkDataCenterId workDataCenterId){if(Objects.nonNull(workDataCenterId.getDataCenterId())) {this.workerId workDataCenterId.getWorkId();this.datacenterId workDataCenterId.getDataCenterId(); }else{this.datacenterId getDatacenterId(maxDatacenterId); workerId getMaxWorkerId(datacenterId, maxWorkerId); } }publicSnowflakeIdGenerator(InetAddress inetAddress){this.inetAddress inetAddress;this.datacenterId getDatacenterId(maxDatacenterId);this.workerId getMaxWorkerId(datacenterId, maxWorkerId); initLog(); }privatevoidinitLog(){if(log.isDebugEnabled()) { log.debug(Initialization SnowflakeIdGenerator datacenterId:this.datacenterId workerId:this.workerId); } }/** * 有参构造器 * *paramworkerId 工作机器 ID *paramdatacenterId 序列号 */publicSnowflakeIdGenerator(longworkerId,longdatacenterId){ Assert.isFalse(workerId maxWorkerId || workerId 0, String.format(worker Id cant be greater than %d or less than 0, maxWorkerId)); Assert.isFalse(datacenterId maxDatacenterId || datacenterId 0, String.format(datacenter Id cant be greater than %d or less than 0, maxDatacenterId));this.workerId workerId;this.datacenterId datacenterId; initLog(); }/** * 获取 maxWorkerId */protectedlonggetMaxWorkerId(longdatacenterId,longmaxWorkerId){StringBuildermpidnewStringBuilder(); mpid.append(datacenterId);StringnameManagementFactory.getRuntimeMXBean().getName();if(StringUtils.isNotBlank(name)) {/* * GET jvmPid */mpid.append(name.split()[0]); }/* * MAC PID 的 hashcode 获取16个低位 */return(mpid.toString().hashCode() 0xffff) % (maxWorkerId 1); }/** * 数据标识id部分 */protectedlonggetDatacenterId(longmaxDatacenterId){longid0L;try{if(nullthis.inetAddress) {this.inetAddress InetAddress.getLocalHost(); }NetworkInterfacenetworkNetworkInterface.getByInetAddress(this.inetAddress);if(null network) { id 1L; }else{byte[] mac network.getHardwareAddress();if(null! mac) { id ((0x000000FF (long) mac[mac.length -2]) | (0x0000FF00 (((long) mac[mac.length -1]) 8))) 6; id id % (maxDatacenterId 1); } } }catch(Exception e) { log.warn( getDatacenterId: e.getMessage()); }returnid; }publiclonggetBase(){intfive5;longtimestamptimeGen();//闰秒if(timestamp lastTimestamp) {longoffsetlastTimestamp - timestamp;if(offset five) {try{ wait(offset 1); timestamp timeGen();if(timestamp lastTimestamp) {thrownewRuntimeException(String.format(Clock moved backwards. Refusing to generate id for %d milliseconds, offset)); } }catch(Exception e) {thrownewRuntimeException(e); } }else{thrownewRuntimeException(String.format(Clock moved backwards. Refusing to generate id for %d milliseconds, offset)); } }if(lastTimestamp timestamp) {// 相同毫秒内序列号自增sequence (sequence 1) sequenceMask;if(sequence 0) {// 同一毫秒的序列数已经达到最大timestamp tilNextMillis(lastTimestamp); } }else{// 不同毫秒内序列号置为 1 - 2 随机数sequence ThreadLocalRandom.current().nextLong(1,3); } lastTimestamp timestamp;returntimestamp; }/** * 获取分布式id * *returnid */publicsynchronizedlongnextId(){longtimestampgetBase();// 时间戳部分 | 数据中心部分 | 机器标识部分 | 序列号部分return((timestamp - BASIS_TIME) timestampLeftShift) | (datacenterId datacenterIdShift) | (workerId workerIdShift) | sequence; }/** * 获取订单编号 * *returnorderNumber */publicsynchronizedlonggetOrderNumber(longuserId,longtableCount){longtimestampgetBase();longsequenceShiftlog2N(tableCount);// 时间戳部分 | 数据中心部分 | 机器标识部分 | 序列号部分 | 用户id基因return((timestamp - BASIS_TIME) timestampLeftShift) | (datacenterId datacenterIdShift) | (workerId workerIdShift) | (sequence sequenceShift) | (userId % tableCount); }protectedlongtilNextMillis(longlastTimestamp){longtimestamptimeGen();while(timestamp lastTimestamp) { timestamp timeGen(); }returntimestamp; }protectedlongtimeGen(){returnSystemClock.now(); }/** * 反解id的时间戳部分 */publicstaticlongparseIdTimestamp(longid){return(id22) BASIS_TIME; }/** * 求log2(N) * */publiclonglog2N(longcount){return(long)(Math.log(count)/ Math.log(2)); }publiclonggetMaxWorkerId(){returnmaxWorkerId; }publiclonggetMaxDatacenterId(){returnmaxDatacenterId; } }总结在构建SnowflakeIdGenerator时如果通过lua执行加载获取workDataCenterId失败则还采取Mybiats-plus的生成策略nextId方法就是获取分布式id的方法其内部getBase()是更新时间戳的部分由时间戳部分 | 数据中心部分 | 机器标识部分 | 序列号部分这四个部分组成getOrderNumber方法是生成订单编号使用了基因替换法来解决在分库分表情况下使用订单id和用户id查询订单时的全路由问题关于基因法的详细介绍可跳转到相关文档

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询