时间:2023-06-01 21:45:19 | 浏览:125
架构
前后端分离:
补充:
注:这个“仓库”应该就是本地安装maven的目录下的Repository的文件夹
分布式锁
线程锁:当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效,因为线程锁的实现在根本上是依靠线程之间共享内存实现的。如synchronized
进程锁:为了控制同一操作系统中多个进程访问某个共享资源。
分布式锁:当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。
分布式锁一般有三种实现方式:
乐观锁的实现:使用版本标识来确定读到的数据与提交时的数据是否一致。提交后修改版本标识,不一致时可以采取丢弃和再次尝试的策略。
分布式锁基于Redis的实现:(本系统锁才用的)
基本命令:
加锁方式:
这里的jedis是Java对Redis的集成
jedis.set(String key, String value, String nxxx, String expx, int time)
错误的加锁方式1:
如果程序在执行完setnx()之后突然崩溃,导致锁没有设置过期时间。那么将会发生死锁。
Long result = jedis.setnx(Key, value); if (result == 1) { // 若在这里程序突然崩溃,则无法设置过期时间,将发生死锁 jedis.expire(Key, expireTime); }
错误的加锁方式2:
分布式锁才用(Key,过期时间)的方式,如果锁存在,那么获取它的过期时间,如果锁的确已经过期了,那么获得锁,并且设置新的过期时间
错误分析:不同的客户端之间需要同步好时间。
long expires = System.currentTimeMillis() + expireTime; String expiresStr = String.valueOf(expires); // 如果当前锁不存在,返回加锁成功 if (jedis.setnx(lockKey, expiresStr) == 1) { return true; } // 如果锁存在,获取锁的过期时间 String currentValueStr = jedis.get(lockKey); if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) { // 锁已过期,获取上一个锁的过期时间,并设置现在锁的过期时间 String oldValueStr = jedis.getSet(lockKey, expiresStr); if (oldValueStr != null && oldValueStr.equals(currentValueStr)) { // 考虑多线程并发的情况,只有一个线程的设置值和当前值相同,它才有权利加锁 return true; } } // 其他情况,一律返回加锁失败 return false;
解锁:判断锁的拥有者后可以使用 jedis.del(lockKey) 来释放锁。
分布式锁基于Zookeeper的实现
Zookeeper简介:Zookeeper提供一个多层级的节点命名空间(节点称为znode),每个节点都用一个以斜杠(/)分隔的路径表示,而且每个节点都有父节点(根节点除外)。
例如,/foo/doo这个表示一个znode,它的父节点为/foo,父父节点为/,而/为根节点没有父节点。
client不论连接到哪个Server,展示给它都是同一个视图,这是zookeeper最重要的性能。
Zookeeper 的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务,实现中zxid是一个64位的数字。
Zookeeper的分布式锁原理
获取分布式锁的流程:
我的解释:
A在Locker下创建了Node_n —>循环 ( 每次获取Locker下的所有子节点 —> 对这些节点按节点自增号排序顺序 —> 判断自己创建的Node_n是否是第一个节点 —> 如果是则获得了分布式锁 —> 如果不是监听上一个节点Node_n-1 等它释放掉分布式锁。)
@ControllerAdvice处理全局异常
Mybatis注解方式的使用:
@insert 用注解方式写SQL语句
分布式系统的下的Session
1、分布式系统:多节点,节点发送数据交互,不共享主内存,但通过网络发送消息合作。
分布式:不同功能模块的节点
集群:相同功能的节点
2、Session 与token
服务端在HTTP头里设置SessionID而客户端将其保存在cookie
而使用Token时需要手动在HTTP头里设置,服务器收到请求后取出cookie进行验证。
都是一个用户一个标志
3、分布式系统中的Session问题:
高并发:通过设计保证系统能够同时并行处理很多请求。
当高并发量的请求到达服务端的时候通过负载均衡的方式分发到集群中的某个服务器,这样就有可能导致同一个用户的多次请求被分发到集群的不同服务器上,就会出现取不到session数据的情况。
根据访问不同的URL,负载到不同的服务器上去
三台机器,A1部署类目,A2部署商品,A3部署单服务
通用方案:用Redis保存Session信息,服务器需要时都去找Redis要。登录时保存好key-value,登出时让他失效
垂直扩展:IP哈希 IP的哈希值相同的访问同一台服务器
session的一致性:只要用户不重启浏览器,每次http短连接请求,理论上服务端都能定位到session,保持会话。
Redis作为分布式锁
高并发:通过设计保证系统能够同时并行处理很多请求。(系统学习并发知识,可以在Java知音公众号回复“多线程聚合”)
同步:Java中的同步指的是通过人为的控制和调度,保证共享资源的多线程访问成为线程安全。
线程的Block状态:
a.调用join()和sleep()方法,sleep()时间结束或被打断
b.wait(),使该线程处于等待池,直到notify()/notifyAll():不释放资源
此外,在runnable状态的线程是处于被调度的线程,Thread类中的yield方法可以让一个running状态的线程转入runnable。
Q:为什么wait,notify和notifyAll必须与synchronized一起使用?Obj.wait()、Obj.notify必须在synchronized(Obj){…}语句块内。
A:wait就是说线程在获取对象锁后,主动释放对象锁,同时本线程休眠。
Q:Synchronized:
A:Synchronized就是非公平锁,它无法保证等待的线程获取锁的顺序。
公平和非公平锁的队列都基于锁内部维护的一个双向链表,表结点Node的值就是每一个请求当前锁的线程。公平锁则在于每次都是依次从队首取值。
ReentrantLock重入性:
重入锁可以看这两篇文章,都比较简单
https://www.jianshu.com/p/587a4559442b
https://www.jianshu.com/p/1c52f17efaab
Spring + Redis缓存的两个重要注解:
对数据库加锁(乐观锁 与 悲观锁)
悲观锁依赖数据库实现:
select * from account where name=”Erica” for update
这条sql 语句锁定了account 表中所有符合检索条件(name=”Erica”)的记录,使该记录在修改期间其它线程不得占有。
代码层加锁:
String hql ="from TUser as user where user.name="Erica""; Query query = session.createQuery(hql); query.setLockMode("user",LockMode.UPGRADE); //加锁 List userList = query.list();//执行查询,获取数据
其它
@Data 类似于自动生成了Getter()、Setter()、ToString()等方法。
JAVA1.8的新特性StreamAPI:Collectors中提供了将流中的元素累积到汇聚结果的各种方式
List<Menu> menus=Menu.getMenus.stream().collect(Collectors.toList())
For - each 写法:
for each语句是java5新增,在遍历数组、集合的时候,for each拥有不错的性能。
public static void main(String[] args) { String[] names = {"beibei", "jingjing"}; for (String name : names) { System.out.println(name); } }
for each虽然能遍历数组或者集合,但是只能用来遍历,无法在遍历的过程中对数组或者集合进行修改。
BindingResult:一个@Valid的参数后必须紧挨着一个BindingResult 参数,否则spring会在校验不通过时直接抛出异常。
@Data public class OrderForm { @NotEmpty(message = "姓名必填") private String name; }
后台:
@RequestMapping("save") public String save( @Valid OrderForm order,BindingResult result) { // if(result.hasErrors()){ List<ObjectError> ls=result.getAllErrors(); for (int i = 0; i < ls.size(); i++) { log.error("参数不正确,OrderForm={}", order); throw new SellException( ………… , result.getFeildError.getDefaultMessage() ) System.out.println("error:"+ls.get(i)); } } return "adduser"; }
result.getFeildError.getDefaultMessage()可抛出“姓名必填” 的异常。
4、List转为Map
public class Apple { private Integer id; private String name; private BigDecimal money; private Integer num; /*构造函数*/ }
List<Apple> appleList = new ArrayList<>();//存放apple对象集合 Apple apple1 = new Apple(1,"苹果1",new BigDecimal("3.25"),10); Apple apple12 = new Apple(1,"苹果2",new BigDecimal("1.35"),20); Apple apple2 = new Apple(2,"香蕉",new BigDecimal("2.89"),30); Apple apple3 = new Apple(3,"荔枝",new BigDecimal("9.99"),40); appleList.add(apple1); appleList.add(apple12); appleList.add(apple2); appleList.add(apple3);
Map<Integer, Apple> appleMap = appleList.stream().collect(Collectors.toMap(Apple::getId, a -> a,(k1,k2)->k1));
5、Collection的子类:List、Set
List:ArrayList、LinkedList 、Vector
List:有序容器,允许null元素,允许重复元素
Set:元素是无序的,不允许元素
最流行的是基于 HashMap 实现的 HashSet,由hashCode()和equals()保证元素的唯一性。
可以用set帮助去掉List中的重复元素,set的构造方法的参数可以是List,构造后是一个去重的set。
HashMap的补充:它不是Collection下的
Map可以使用containsKey()/containsValue()来检查其中是否含有某个key/value。
HashMap会利用对象的hashCode来快速找到key。
插入过程:通过一个hash函数确定Entry的插入位置index=hash(key),但是数组的长度有限,可能会发生index冲突,当发生了冲突时,会使用头插法,即为新来的Entry指向旧的Entry,成为一个链表。
每次插入时依次遍历它的index下的单链表,如果存在Key一致的节点,那么直接替换,并且返回新的值。
但是单链表不会一直增加元素,当元素个数超过8个时,会尝试将单链表转化为红黑树存储。
为何加载因子默认为0.75?(0.75开始扩容)
答:通过源码里的javadoc注释看到,元素在哈希表中分布的桶频率服从参数为0.5的泊松分布。
源码地址:
https://github.com/923310233/wxOrder
架构前后端分离:补充:setting.xml 文件的作用:settings.xml是maven的全局配置文件。而pom.xml文件是所在项目的局部配置。Settings.xml中包含类似本地仓储位置、修改远程仓储服务器、认证信息等配置。ma
顾客不用排队等待,打开微信扫一扫二维码,就能通过微信点餐支付,对于大部分餐厅来说,都已经成为常见的现象,小程序彻底融入了我们的生活,小程序也已经成为餐饮行业必备的工具。那么,如何开发一款自己的餐饮小程序呢?开发一个点餐外卖小程序需要多少钱?
产品介绍三勾餐饮点餐小程序源码是一款基于微信开发的小程序,旨在提供用户快捷、便利的餐饮点餐服务。该小程序包含点餐、支付等功能,用户可以通过扫描店内二维码、搜索店铺名称等方式进入和使用。产品特点该小程序具有以下特点:快速入口:用户可以通过扫描
项目功能简介:该项目采用技术JSP、Servlet、jdbc、bootstrap、Tomcat服务器、MySQL数据库、目含有源码、论文、配套开发软件、软件安装教程、项目发布教程.点餐系统分为前台和后台前台功能介绍:1、项目运行展示首页,自
大家好啊,我是测评君,欢迎来到web测评。技术架构后端技术框架:springboot + shiro + layui前端技术框架:uni-app运行环境:IntelliJ IDEA 2022 + jdk1.8 + Mysql5.7.4 +
蛋糕店预约点餐系统是一种基于互联网技术的预订点餐服务,旨在为顾客与蛋糕店建立一种快捷、便捷、在线的交流方式。Java开发的蛋糕店预约点餐系统可为顾客提供在线预定、快捷支付、口碑评价等服务,为蛋糕店提供菜单管理、订单管理、店铺信息管理等服务。
经常听说,燕窝一定要购买带有溯源码的燕窝,带有溯源码的燕窝才是真燕窝。这种说法正确吗?有溯源码的燕窝一定代表是正品燕窝吗?先来了解一下什么是溯源码燕窝。溯源燕窝就是有燕窝原产地和中国质检局两国检疫审批的燕窝,溯源就是追本溯源,溯源和非溯源的
在手机下单点餐,热乎乎的饭菜便会送到病房。为保障院内医疗服务,降低住院患者取餐就餐时的聚集情况,近日,山医大一院推出床旁智慧点餐系统,借助“互联网+”订餐模式,实现患者点餐取餐无接触。 据了解,此次山医大一院床旁智慧点餐系统是在原有的
很多朋友都在问同城外卖点餐系统,哪种外卖系统更好?它曾经被使用过吗?,下面云快卖小编就为大家介绍一下。对于城市外卖跑腿的创业者来说,选择一款优质的外卖跑腿系统是一件非常重要的事情。低性价比的系统无法满足日常需求。同时,频繁的系统更换容易造成
摘 要计算机信息技术和互联网的发展,带动了整个的商业发展,方便了我们的生活。在餐饮业,从传统的就餐方式发展到如今的线上销售,客户通过订餐系统查看餐品信息,根据订购量和受欢迎程度来衡量餐品的好坏,不仅可以订购到优质的美食,也可以享受到快捷的送
产品特色会员积分系统:包含积分抵现、会员折扣等,沉淀老用户。价格不怕调:微信小程序点餐系统,后台操作,实时更新,不怕调菜品、调价格就餐不等待:后台对接小票打印系统,订单清晰明了,实时监控,避免错误更高的曝光率:小程序入口多、可分享好友,还可
据华夏经纬网引用台湾“联合新闻网”报道,台当局“数位发展部”日前发布该部门负责人唐凤吃面线的文章宣传线上点餐系统,被痛批后紧急再发声明,强调是在推广“台湾云市集”服务,但蓝绿民代都不埋单。图源台媒 民进党民代何志伟揶揄,“痒的不抓,不
智慧点餐是现在外出就餐的常见场景,通过座位处的二维码连接店里的点餐系统,可以直接下单并定位到相对应的餐桌号,这种风靡的点餐方式符合移动数字化的发展趋势,它可以让顾客更方便,也能减轻饭店人员服务负担。智慧点餐应用最多的就是点餐与结算,完整的智
1、通过预定点餐系统,可以帮助食堂老板提高管理效率,有效节省时间,避免了人工去登记和点餐的繁琐。同时还能减少人员流动性,降低了员工之间的矛盾。2、食堂可以进行预约排队管理,减少了排队等餐带来的效率低下问题。3、可以帮助食堂节省人力成本,提高
本文所研究的基于微信小程序的网上点餐系统商城主要是一个餐馆点餐的线上网上商城,结合市面上小型餐饮店铺的新零售化,实现线上销售模式,扩充其销售渠道。本文主要是基于微信开发者工具、后端设计语言即PHP语言以及微信开发者工具的界面实现技术(WXM