登陆

极彩彩票平台登录网址-Spring Boot 微信点餐开源体系

admin 2019-08-23 125人围观 ,发现0个评论
  • 架构
  • 散布式锁
  • 散布式锁依据Redis的完成:(本体系锁才用的)
  • 散布式锁依据Zookeeper的完成
  • Zookeeper的散布式锁原理
  • 散布式体系的下的Session
  • Redis作为散布式锁
  • 其它

架构

前后端别离:

Nginx与Tomcat的联系在这篇文章,几分钟能够快速了解:

https://www.jianshu.com/p/22dcb7ef9172

弥补:

  • setting.xml 文件的效果:settings.xml是maven的大局装备文件。而pom.xml文件是地点项目的部分装备。Settings.xml中包括相似本地仓储方位、修正长途仓储服务器、认证信息等装备。
  • maven的效果:凭借Maven,可将jar包只是保存在“库房”中,有需求该文件时,就引证该文件接口,不需求仿制文件过来占用空间

注:这个“库房”应该便是本地装置maven的目录下的Repository的文件夹

散布式锁

线程锁:当某个办法或代码运用锁,在同一时刻仅有一个线程履行该办法或该代码段。线程锁只在同一JVM中有用,由于线程锁的完成在根本上是依托线程之间同享内存完成的。如synchronized

进程锁:为了操控同一操作体系中多个进程拜访某个同享资源。

散布式锁:当多个进程不在同一个体系中,用散布式锁操控多个进程对资源的拜访。

散布式锁一般有三种完成办法:

  1. 数据库达观锁;
  2. 依据Redis的散布式锁;
  3. 依据ZooKeeper的散布式锁。

达观锁的完成:运用版别标识来确认读到的数据与提交时的数据是否共同。提交后修正版别标识,不共一同能够采纳丢掉和再次测验的战略。

CAS:能够阅览这篇文章:

https://www.jianshu.com/p/456bb1ea9627

散布式锁依据Redis的完成:(本体系锁才用的)

根本指令:

  • SETNX(SET if Not exist):当且仅当 key 不存在,将 key 的值设为 value ,并回来1;若给定的 key 现已存在,则 SETNX 不做任何动作,并回来0。
  • GETSET:将给定 key 的值设为 value ,并回来 key 的旧值。先依据key获取到旧的value,再set新的value。
  • EXPIRE 为给定 key 设置生计时刻,当 key 过期时,它会被主动删去。

加锁办法:

这儿的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的散布式锁原理

获取散布式锁的流程:

  1. 在获取散布式锁的时分在locker节点(locker节点是Zookeeper的指定节点)下创立暂时次序节点,开释锁的时分删去该暂时节点。
  2. 客户端调用createNode办法在locker下创立暂时次序节点,然后调用getChildren(“locker”)来获取locker下面的一切子节点,留意此刻不必设置任何Watcher。
  3. 客户端获取到一切的子节点path之后,假如发现自己创立的子节点序号最小,那么就以为该客户端获取到了锁。
  4. 假如发现自己创立的节点并非locker一切子节点中最小的,阐明自己还没有获取到锁,此刻客户端需求找到比自己小的那个节点,然后对其调用exist()办法,一同对其注册事情监听器。
  5. 之后,让这个被重视的节点删去,则客户端的Watcher会收到相应告诉,此刻再次判别自己创立的节点是否是locker子节点中序号最小的,假如是则获取到了锁,假如不是则重复以上进程持续获取到比自己小的一个节点并注册监听。

我的解说:

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问题:

高并发:经过规划确保体系能够一同并行处理许多恳求。

当高并发量的恳求抵达服务端的时分经过负载均衡的办法分发到集群中的某个服务器,这样就有或许导致同一个用户的极彩彩票平台登录网址-Spring Boot 微信点餐开源体系屡次恳求被分发到集群的不同服务器上,就会呈现取不到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缓存的两个重要注解:

  • @cacheable 只会履行一次,当标记在一个办法上时表明该办法是支撑缓存的,Spring会在其被调用后将其回来值缓存起来,以确保下次运用相同的参数来履行该办法时能够直接从缓存中获取成果。
  • @cacheput:与@Cacheable不同的是运用@CachePut标示的办法在履行前不会去查看缓存中是否存在之前履行过的成果,而是每次都会履行该办法,并将履行成果以键值对的方式存入指定的缓存中。

对数据库加锁(达观锁 与 失望锁)

失望锁依靠数据库完成:

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);
q极彩彩票平台登录网址-Spring Boot 微信点餐开源体系uery.setLockMode("user",LockMode.UPGRADE); //加锁
List userList = query.list();//履行查询,获取数据

其它

@Data 相似于主动生成了Getter()、Setter()、ToString()等办法。

JAVA1.8的新特性StreamAPI:Collectors中供给了将流中的元素累积到会聚成果的各种办法

List 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 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;
极彩彩票平台登录网址-Spring Boot 微信点餐开源体系private Integer num;
/*结构函数*/
}
List 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 appleMa极彩彩票平台登录网址-Spring Boot 微信点餐开源体系p =
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的泊松散布。

源码地址:

回复【餐饮】到大众号后台,取得 Github 库房地址。

来历:http://rrd.me/ehmE2


:-D 查找微信号(ID:芋道源码),能够取得各种 Java 源码解析、原理解说、面试题、学习指南。

:-D 而且,回复【书本】后,能够收取笔者引荐的各种 Java 从入门到架构的 100 本书本。

:-D 而且,回复【技能群】后,能够参加专门评论 Java、后端、架构的技能群。

来吧,骚年~


请关注微信公众号
微信二维码
不容错过
Powered By Z-BlogPHP