当前位置: 首页 > news >正文

网站用户界面设计重庆邮电大学官网网站

网站用户界面设计,重庆邮电大学官网网站,南昌网页制作公司,找个可以直接观看的网站目录 一、前言二、如何通过Redis设计一个分布式全局唯一ID生成工具2.1、使用 Redis 计数器实现2.2、使用 Redis Hash结构实现 三、通过代码实现分布式全局唯一ID工具3.1、编写获取工具3.2、测试获取工具 四、总结 一、前言 在很多项目中生成类似订单编号、用户编号等有唯一性数… 目录 一、前言二、如何通过Redis设计一个分布式全局唯一ID生成工具2.1、使用 Redis 计数器实现2.2、使用 Redis Hash结构实现 三、通过代码实现分布式全局唯一ID工具3.1、编写获取工具3.2、测试获取工具 四、总结 一、前言 在很多项目中生成类似订单编号、用户编号等有唯一性数据时还用的UUID工具或者自己根据时间戳随机字符串等组合来生成在并发小的时候很少出问题当并发上来时就很可能出现重复编号的问题了单体项目和分布式项目都是如此要想解决这个问题也有很多种方法可以自己写一个唯一ID生成规则也可以通过数据库来实现全局ID生成这个和使用Redis实现其实类似还可以使用比较成熟的雪花算法工具实现每种方法都有各自的优缺点这里不展开说明这里详细说明如何使用Redis实现生成分布式全局唯一ID。        还有一个问题为什么不能直接使用数据库的自增ID而是需要单独生成一个分布式全局唯一ID类似订单IDON202311090001在数据库中有自增ID对于当前业务来说就是唯一的为什么不能用还要去生成一个独立的订单ID对于这个问题要从几个方面分析        1、数据库自增ID是有序增长的很容易就被人猜到比如我现在下一单看到的订单ID为999那么就知道你的系统里最多只有999单还有如果接口设计不合理比如取消订单接口只校验了用户是否登录没有校验订单是否属于该用户接收一个订单ID就能将订单取消那么这样很容易就被人抓住漏洞类似的情况有很多也很多人写接口是不会注意这个问题。        2、这种自增ID没有意义而且不同业务的自增ID是重合的对于信息区分度很低而且考虑到多业务交互和用户端展示也都是不合适的想想看要是你在某宝下单订单ID是999或者在对接别人订单系统时给你的订单ID是999是不是很奇怪。        3、分库分表时自增ID会重复 需要集成文章可以查看 SpringBoot集成Lettuce客户端操作Redishttps://blog.csdn.net/weixin_44606481/article/details/133907103 二、如何通过Redis设计一个分布式全局唯一ID生成工具 用户下单调用下单逻辑先进行业务逻辑处理然后携带订单ID标识通过分布式全局唯一ID工具获取一个唯一的订单ID这个订单ID标识就是用于区分业务的获取到订单ID后将数据组装入库分布式全局唯一ID工具可以做成一个内嵌的utils也可以封装成一个独立的jar还可以做成一个分布式全局唯一ID生成服务供其它业务服务调用。 2.1、使用 Redis 计数器实现 Redis的String结构提供了计数器自增功能类似Java中的原子类还要优于Java的原子类因为Redis是单线程执行的缓存读写本身就是线程安全的也不用进行原子类的乐观锁操作每一次获取分布式全局唯一ID时就将自增序列加1。 # 给key为GENERATEID:NO的value自增1如果这key不存在则会添加到Redis中并且设置value为1 ## GENERATEIDkey前缀 ## NO订单ID标识 127.0.0.1:6379 incr GENERATEID:NO (integer) 12.2、使用 Redis Hash结构实现 Redis Hash结构中的每一个field也可以进行自增操作可以用一个Hash结构存储所有的标识信息和自增序列方便管理比较适合并发不高的小项目所有服务都是用的一个Redis如果并发较高就不合适了毕竟Redis操作普通String结构肯定比操作Hash结构快。 # 给key为GENERATEIDfield为no的value自增1如果这key不存在则会添加到Redis中并且设置value为1 ## GENERATEID分布式全局唯一ID Hash key ## NOHash结构中的field 127.0.0.1:6379 hincrby GENERATEID NO 1 (integer) 1三、通过代码实现分布式全局唯一ID工具 这里使用Redis 计数器实现自增序列以天为单位存储在实际业务中比如生成订单编号组成规则都类似NO1699631999000-1业务标识key当前时间戳自增序列这个规则可以自己定义保证最终生成的订单编号不重复即可不建议直接一个自增序列干到底订单编号这类型的数据都是有长度限制的或者是要求生成20字符的订单编号如果增长的过长反而不好处理。 3.1、编写获取工具 import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.time.LocalDate; import java.util.concurrent.TimeUnit;Component public class RedisGenerateIDUtils {Autowiredprivate RedisTemplateString, Object redisTemplate;// key前缀private String PREFIX GENERATEID:;/*** 获取全局唯一ID* param key 业务标识key*/public String generateId(String key) {// 获取对应业务自增序列Long incr getIncr(key);// 组装最后的结果这里可以根据需要自己定义这里是按照业务标识key当前时间戳自增序列进行组装String resultID key System.currentTimeMillis() - incr;return resultID;}/*** 获取对应业务自增序列*/private Long getIncr(String key) {String cacheKey getCacheKey(key);Long increment 0L;// 判断Redis中是否存在这个自增序列如果不存在添加一个序列并且设置一个过期时间if (!redisTemplate.hasKey(cacheKey)) {// 这里存在线程安全问题需要加分布式锁这里做简单实现String lockKey cacheKey _LOCK;// 设置分布式锁boolean lock redisTemplate.opsForValue().setIfAbsent(lockKey, 1, 30, TimeUnit.SECONDS);if (!lock) {// 如果没有拿到锁进行自旋return getIncr(key);}increment redisTemplate.opsForValue().increment(cacheKey);// 我这里设置24小时可以根据实际情况设置当前时间到当天结束时间的插值redisTemplate.expire(cacheKey, 24, TimeUnit.HOURS);// 释放锁redisTemplate.delete(lockKey);} else {increment redisTemplate.opsForValue().increment(cacheKey);}return increment;}/*** 组装缓存key*/private String getCacheKey(String key) {return PREFIX key : getYYYYMMDD();}/*** 获取当前YYYYMMDD格式年月日*/private String getYYYYMMDD() {LocalDate currentDate LocalDate.now();int year currentDate.getYear();int month currentDate.getMonthValue();int day currentDate.getDayOfMonth();return year month day;} }3.2、测试获取工具 import com.redisscene.utils.RedisGenerateIDUtils; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.concurrent.*;RunWith(SpringRunner.class) SpringBootTest(classes RedisSceneApplication.class) public class RedisGenerateIDTest {Autowiredprivate RedisGenerateIDUtils redisGenerateIDUtils;Testpublic void t1() throws InterruptedException {// 定义一个线程池 设置核心线程数和最大线程数都为100队列根据需要设置ThreadPoolExecutor executor new ThreadPoolExecutor(100, 100, 10, TimeUnit.SECONDS, new LinkedBlockingQueue(10000));CountDownLatch countDownLatch new CountDownLatch(10000);long beginTime System.currentTimeMillis();// 获取10000个全局唯一ID 看看是否有重复CopyOnWriteArraySetString ids new CopyOnWriteArraySet();for (int i 0; i 10000; i) {executor.execute(() - {// 获取全局唯一IDlong beginTime02 System.currentTimeMillis();String orderNo redisGenerateIDUtils.generateId(NO);System.out.println(获取单个ID耗时 time (System.currentTimeMillis() - beginTime02));if (ids.contains(orderNo)) {System.out.println(重复ID orderNo);} else {ids.add(orderNo);}countDownLatch.countDown();});}countDownLatch.await();// 打印获取到的全局唯一ID集合数量System.out.println(获取到全局唯一ID count ids.size());System.out.println(耗时毫秒 time (System.currentTimeMillis() - beginTime));} }四、总结 通过测试可以看到100并发生成全局唯一ID是没问题的而且获取单个ID耗时在10-20毫秒左右一般的业务已经完全够用这个耗时也要看Redis性能和项目配置决定的如果对于这种唯一ID生成并发量非常高的业务可以提前生成一个唯一ID池存储在本地内存中业务要获取唯一ID先去池中获取如果获取不到再去Redis获取自增序列一次性增加多个然后将这个区间的值存储在本地缓存即可。
http://www.sadfv.cn/news/107318/

相关文章:

  • 工程建设国家标准网站网络架构方案规划设计和实施
  • 网站做seo必要的结构深圳专业极速网站建设
  • 有哪些做分析图用的网站深圳效果好的免费网站建设
  • 西安建筑网站建设wordpress电影资源
  • 网站被墙 做301跳转那个网站ppt做的比较好
  • 上海网站托管龙华做网站怎么样
  • 林州网站建设哪家便宜显示WordPress页面打开时长
  • 浙江省建设职业注册中心网站张家港江阴网站设计
  • 襄汾县住房和建设局网站wordpress自定义首页布局
  • 网站开发的策划书thinkphp网站开发实例教程
  • 网站空间150m临沂做网站首选
  • 高端的扬中网站建设东莞市专注网站建设怎么样
  • 长沙有哪些做网站的公司云课堂哪个网站做的好
  • 怎么做简易手机网站什么是网站流量
  • 企业做网站有用么自学网站
  • 镇江做网站要多少钱公司信息管理系统
  • 怀化订水网站网页都有哪些
  • 学编程要什么电脑网站太卡怎么优化
  • 营销智库网站安徽建站管理系统价格
  • 华西医院网站开发网站模版自适应
  • 网站开发 百度网盘做网站的分析报告案例
  • 广东建设继续教育网站首页长沙大型公司
  • 网站在线访谈栏目建设wordpress 头像本地化
  • 网站后台管理系统怎么进wordpress 资源下载主题
  • 开平市网站建设东莞长安做网站
  • 免费搭建网站怎么免费给网站做收录
  • 网站分哪些类型定制型网站制作明细报价表
  • 如何做与别人的网站一样的湘潭网站建设 诚信磐石网络
  • 家庭宽带做网站服务器吗织梦网站怎么重新安装教程
  • 能免费用服务器的网站wordpress游戏代练主题