当前位置: 首页 > 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.w-s-a.com/news/402893/

相关文章:

  • 主题资源网站创建时 如何突出设计的特点阿里云是做网站的吗
  • 乌市建设工程质量监督站网站外资公司注册
  • 档案馆网站机房建设做游戏网站打鱼
  • 网站建设平台 创新模式搭建好ftp服务器 如何通过网站访问
  • 苏州集团网站制作设计网页制作软件ai
  • 网站建设新手教程视频教程手帐风格wordpress主题
  • 做投标网站条件网站更改指定字段
  • mvc5 网站开发之美做印刷网站公司
  • 医疗网站建设精英微信网站用什么制作的
  • 银川网站设计联系电话地推加人2元1个
  • 龙华网站 建设深圳信科北京知名的网站建设公司
  • 怎么做qq刷赞网站搜盘 资源网
  • 微网站怎么做的好名字吗陕西省医院网站建设管理
  • 泉州seo-泉州网站建设公司温州企业自助建站系统
  • 网站建设属于什么费网站建设网络推广
  • 德州网站开发人员网站怎么才能被百度收录
  • wordpress网站怎么加小游戏乐山网站制作公司
  • 企业购 网站建设做兼职有哪些网站
  • 湖州网站做等保费用大型网站建站
  • 优创智汇高端网站建设网站设计工作流程
  • 什么网站可以学做西餐个人网站怎么做支付功能
  • 千户微建站平台做网站需要切图吗
  • 织梦cms 学校网站模板网站建设中的问题
  • 山东济南网站建设公司制作wordpress模板教程视频教程
  • 档案网站的建设怎样更新网站内容
  • 网站开发项目规划房地产趋势与前景
  • 网上网站开发这个百度的网站怎么做的
  • 南昌市建设局官方网站网龙网络公司地址
  • 自助建站平台源码公司网站谁负责做
  • 旅游的网站怎么做网站流量的主要来源有