Reactor模式一、Web请求处理架构概述在处理Web请求时,主要存在两种体系结构:thread - based architecture(基于线程)和event - driven architecture(事件驱动)。
(一)Thread - based Architecture(基于线程)
基于线程的体系结构通常采用多线程方式来处理客户端请求。每当接收到一个请求,就会开启一个独立的线程进行处理。这种方式在直观上易于理解,但存在一定局限性。每个线程都需要占用一定的内存资源,并且操作系统在线程之间切换时会产生开销。当并发访问量不大时,这种开销可能不明显,但随着线程数量增多,会显著降低Web服务器的性能。此外,当线程处理I/O操作并处于等待输入状态时,线程处于空闲状态,这期间会造成CPU资源的浪费。以下是其典型设计流程:
客户端发起请求。
服务器接收请求后,在单独的线程中进行读取(read)操作。
对读取的数据进行解码(decode)。
调用相应的处理程序(handler)进行业务逻辑处理,如计算(Compute)。
对处理结果进行编码(encode)。
最后将响应发送(s ...
MySQL死锁产生原因所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的InnoDB。
死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。
那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。mysql如何避免死锁https://www.pianshen.com/article/7970964764/
11 、死锁的概念
是指两个或两个以上的事务在执行过程中,因争夺资源而造成的一种互相等待的现象。若无外力作用,事务都将无法推进下去,解决死锁的最简单问题是不要有等待,任何的等待都转换为回滚,并且事务重新开始,但在线上环境,这可能会导致并发性能下降,甚至任何一个事务都不能进行,而这所带来的问题远比死锁的问题更严重
解决死锁的问题最简单的一种方法是超时,当两个事务互相等待时,当一个等待时间超过设置的某一阈值时,其中一个事务回滚,另一个等待的事务就能继续运行了, ...
redis
未读Redis 主从在线切换记录
背景Redis master 所在实例主机需要下线维护. 如何切换主从对线上影响最小. 当前架构如下图
技术方案方案1引入 redis sentinel.
步骤:
部署redis sentinel
修改业务配置, 修改业务代码.
kill master.
check
建立新主从逻辑
优点:
切换简单, kill 主库即可, sentinel 可自动提升 slave -> master.
缺点:
需要部署 redis sentinel, 新的中间件.
需要改动业务代码.
方案2直接切换
步骤:
使从库可写, redis-cli -h redis-slave -p 6379 CONFIG set slave-read-only no
修改业务侧配置, redis 地址指向可写的 slave 实例, 重启业务应用
确保主从同步完成, 停止主从同步. redis-cli -h redis-slave -p 6379 slaveof no one
建立新主从逻辑.
优点:
符合直觉
没有代码改动
缺点:
如果切换过程中有问题, 需要及时回滚配置和业 ...
目录
从一个Spring Security的例子开始
创建不受保护的应用
加入spring security 保护应用
关闭security.basic ,使用form表单页面登录
角色-资源 访问控制
获取当前登录用户信息
小结
Spring Security 核心组件
SecurityContext
SecurityContextHolder
Authentication
UserDetails
UserDetailsService
AuthenticationManager
小结
Spring Security的一些工作原理
spring security 在web应用中是基于filter的
DelegatingFilterProxy
spring security入口——springSecurityFilterChain
FilterChainProxy 和SecurityFilterChain
小结
再说SecurityFilterChain
Spring Security 的一些实战
通过数据库查询,存储用户和角色实现安全认证
添加spring-data-jp ...
spring-cloud
未读Zuul是Netflix开源的微服务网关,可以和Eureka、Ribbon、Hystrix等组件配合使用,Spring Cloud对Zuul进行了整合与增强,Zuul默认使用的HTTP客户端是Apache HTTPClient,也可以使用RestClient或okhttp3.OkHttpClient。 Zuul的主要功能是路由转发和过滤器。路由功能是微服务的一部分,比如/demo/test转发到到demo服务。zuul默认和Ribbon结合实现了负载均衡的功能
本文介绍zuul的工作原理和如何搭建zuul服务以及介绍相关知识点一、工作原理zuul的核心是一系列的filters, 其作用类比Servlet框架的Filter,或者AOP。zuul把请求路由到用户处理逻辑的过程中,这些filter参与一些过滤处理,比如Authentication,Load Shedding等
Zuul使用一系列不同类型的过滤器,使我们能够快速灵活地将功能应用于我们的边缘服务。这些过滤器可帮助我们执行以下功能
身份验证和安全性 - 确定每个资源的身份验证要求并拒绝不满足这些要求的请求
洞察和监 ...
数据结构
未读这篇文章终于来到了实现持久化 List 的最后一步: 实现 Transient 和持久化的功能。
这篇文章是系列文章的一部分,如果还没有浏览过文章的其它部分请参考:
持久化数据结构简介
Vector Trie 的实现
Transient 及持久化(本文)
在之前的文章中,我们已经看到了如何实现一个 Vector Trie,也知道如何使用 Vector Trie 来实现共享数据结构的持久化 List: 在每次修改时,我们复制从根节点到被修改节点路径上的所有节点,并使用得到的新的 Root 节点构造一个新的 List 的 HEAD 数据结构。这样通过新的 HEAD 我们就可以访问到新的数据,通过旧的 HEAD 我们可以得到旧的数据。
按照这样的思路,我们需要更改 List 的接口,对于每一个会修改 List 元素的操作,我们都要返回一个新的 List 对象而不是在原来的对象上修改。比如说:
1234567type List interface { Get(n int) (interface{}, bool) Set(n int, ...
这篇文章是系列文章的一部分,如果还没有浏览过文章的其它部分请参考:
持久化数据结构简介
Vector Trie 的实现 (本文)
Transient 及持久化
首先我们来回顾一下 Vector Trie 的设计思路,为了代替 ArrayList 这种数据结构以及兼顾高性能的随机访问和内存使用, Vector Trie 主要采用了以下几种设计:
将 ArrayList 连续的地址空间切分成一段一段定长的数组
使用 Trie 树结构将这些分段组织起来
读取和写入的时候,利用 Trie 树检索的方法查找目标元素所在的位置
值得注意的是,Vector Trie 作为一种高效的 ArrayList 替代,并非一定要用来实现持久化操作, 在这篇文章当中,我们将会先完成一个不具备持久化能力的 Vector Trie 实现。将 Vector Trie 转变为不可变数据结构以及 Transient 的实现将会留作下一篇文章的内容。
List 的设计首先我们定义一些常数:
12345const ( SHIFT = 5 NODE_SIZE = (1 << SHIFT) ...
这篇文章是系列文章的一部分,如果还没有浏览过文章的其它部分请参考:
持久化数据结构简介(本文)
Vector Trie 的实现
Transient 及持久化
作为系列博客的第一篇,这篇博客将会先给出一些持久化数据结构的简介并以最简单的 List (列表)数据结构为例, 介绍一些常见的持久化数据结构实现方法。这一个系列的文章都主要参考了 Understanding Persistent Vector 这篇非常经典的文章,其中一些章节甚至可以看作是对它内容的翻译。建议有兴趣的读者浏览原文作为参考。
持久化数据结构简介持久化(Persistent)数据结构又叫不可变(Immutable)数据结构,顾名思义,这类数据结构的内容是不可变的。 也就是说,对于这类数据结构的修改操作,都会返回一个新的副本,而原来的数据结构保存的内容不会有任何改变。 这样的数据结构是有意义的,比方说我们现在所编写的所有程序,都可以看作是一个状态机, 也就是说在程序运行的过程的每一个时刻,程序本身可以被看作存在一个状态(State),我们的语句作用在当前状态上, 从而不断地产生出进一步的状态,由此循环往复。如果按照 ...
一、两种方案分库分表
一般业界,对订单数据的分库分表,笔者了解,有两类思路:按照订单号来切分、按照用户id来切分。
方案一、按照订单号来做hash分散订单数据
把订单号看作是一个字符串,做hash,分散到多个服务器去。
具体到哪个库、哪个表存储数据呢?订单号里面的数字来记录着。
现在的微信红包。它的订单分库分表,是对订单号进行hash计算。不是什么取模、取整数。这样数据是均匀分散的。
然后订单号的末尾3个数,里面是包含了库名称、表名称的。
如果要查询某用户的所有订单呢?
由于是根据订单号来分散数据的。他的订单分散在了多个库、多个表中。
总不能去所有的库,所有的表扫描吧。这样效率很低。
其实按照uid切分订单,一样会遇到查询的问题。比如要查询a订单的信息。分库分表的规则是按照uid,都不知道数据在哪个库,无从查。
后续说明解决思路。
一般使用方案二的比较多,一个用户的所有订单,都在一张表里面,那么做分页展示的时候,就容易。
方案二、按照用户id打散订单数据。
以uid来切分数据,有两种思路:
一种是,某个范围的uid订单到哪些库。0到2千万uid ...
问题背景广告主在广告投放平台勾选定向条件之后,当用户发起一个请求之后,需要广告引擎快速筛选出符合定向条件的广告。我们当然可以想到如下的代码结构:
1234Attributes = list<Attribute> // 用户的流量标签,例如:用户的年龄、性别...for (Ad ad : ads) { check attributes for each ad. // 对于每一个广告检查是不是符合流量标签,挑选广告.}
但是这样的问题是随着广告的数量增长而增长的,显然不能满足业务发展需要。无论是在品牌广告,还是竞价广告中,该问题都会遇到。很自然的,我们想到建索引,那么索引结构如何设计就成为问题的关键。
索引结构
两层索引结构
为了说明两层索引结构,我们定义如下术语:
Attribute。单个流量标签,包含两个信息:属性类别和属性取值。如:AGE: 5
Assignment。多个流量标签组成的用户画像。如:AGE: 5,GENDER: 1,NETWORK: 1
Conjunction。布尔表达式的合取范式。如:AGE ∈ (4,5,6) ∧ GEND ...

