redis hash大key怎么优化?怎么查找大key
大key有两种情况,一种是hash结构key下面挂了很多的fileld和value,另一种是单纯的key很多
这种属于分散操作
第一种情况:
用key的fileId的哈希值对一个容量取模,得到一个0到容量的数,然后再加拼接上key,得到新的key,并以新key设置,获取时候同样要先用fileld的哈希值取模
newKey = key + hash(field) % 10000;
hset(newKey, field, value);
hget(newKey, field);
第二种情况:
这种属于聚合操作,需要找到key的相关行
1、这种情况首先看key有没有相关性,比如user_zhangsan_id = 5 user_zhangsan_name = 张三 ,这种key有关联性,可以把这个转成hash结构,[key] user.zhangshan [fileld]id, [value]5 name, 张三
2、如果没有相关性,可以和上面一样,对key的hash和容量取模,再拼接原key,得到新key,用hash结构存,用新key作为key,原key作为field
HTTPS过程
- 客户端向服务器端发起加密通信请求,请求内容包括,自己支持的加密协议版本(SSL安全套接字协议(Secure Socket Layer)是TCP层和应用层(一般指HTTP)之间的中间层协议、TLS-标准化的SSL)、(非对称加密)加密算法(RSA、DSA)
- 服务器端收到请求,选择合适的加密协议(如果没有合适的就关闭加密通信?)、选择合适的加密算法,随后把证书响应给客户端,证书里包含了加密公钥、证书颁发机构信息、过期时间等
- 客户端收到响应,用自己的根证书公钥验证证书的合法性,包括证书解密、签名算法验证签名(sha256、MD5) 验证通过,生成对称加密key(随机数),然后用服务器端公钥对其加密,并发送至服务端
- 服务端收到请求,对收到的加密key用服务端私钥解密,得到客户端的对称加密key,并用这个key加密要发送的数据发送给客户端
- 双方用对称加密key进行加解密通信
CAS SSO单点登陆
有两个系统,分别是www.javaA.com和www.javaB.com,一个SSO www.sso.com
1、客户请求系统A,系统A发现没有token,重定向到SSO认证中心,并将自己的地址作为参数。请求的地址如下:www.sso.com?service=www.java3y.com
2、SSO认证中心发现用户未登录,将用户引导至登录页面,用户进行输入用户名和密码进行登录,用户与认证中心建立全局会话(生成一份Token,写到Cookie中,保存在客户浏览器上,至此客户浏览器和SSO认证中心建立了cookie联系),随后,认证中心重定向回系统A,并把Token携带过去给系统A,重定向的地址如下:www.javaA.com?token=xxxxxxx
3、请求到了系统A,系统A发现有token,然后去SSO验证,验证通过,则系统A和用户建立局部会话(创建Session)并返回资源
4、请求系统B,系统B发现没有token,重定向到SSO认证中心,并将自己的地址作为参数。请求的地址如下:www.sso.com?service=www.javaB.com,此时因为之前客户浏览器已经建立了和SSO的cookie会话,所以本次请求SSO会带着token,SSO系统发现有token,他会重定向至系统B
5、请求到了系统B,系统B发现有token,然后去SSO验证,验证通过,则系统B和用户建立局部会话(创建Session)并返回资源
Spring IOC
-
资源定位
加载配置文件,封装成资源对象
-
装载
通过资源对象加载所有bean,封装成bean描述对象,Defination
-
注册
- 实例化
- 属性注入
- 初始化
IOC过程主要关注两点
- 后置处理器的5种实现,涵盖了整个IOC过程
- 循环依赖的处理
一、实例化前,首先通过一个后置处理器获取对象,相当于把实例化工作交给用户自定义,如果获取的到不走下面的逻辑,直接返回(返回之前遍历执行所有后置处理器的afterinit方法)
进入实例化过程…
实例化
二、通过后置处理器选择一个合适的构造函数,按访问修饰符(Public最大)、参数列表排序,获取匹配度最高的
获取到构造函数以后,通过反射实例化对象
三、通过后置处理器对@Autowired和@Value注解进行处理,根据修饰属性还是修饰方法,封装成InjectionMetadata(注入元数据),接下来的属性注入需要用到
四、为了解决循环依赖,需要提前暴露,暴露的条件是单例 当前bean正在创建 允许提前暴露,第三级缓存是一个函数接口,逻辑是通过后置处理器判断当前bean是否需要代理,如果需要代理则返回其代理对象,这个逻辑
是留给依赖他的Bean触发的,即从三级缓存获取时候singletonFactories.get(beanName) -> singletonFactory.getObject(),这里触发
进入属性填充过程…
属性填充
五、通过后置处理器并使用上一步获取的"注入元数据"对象进行属性填充
进入初始化过程…
初始化
激活Aware接口,即Bean要实现各种Aware接口,这里就会调用对应的接口方法
六、遍历后置处理器,调用before方法
调用init方法 <bean id=“myBean” class=“com.sf…” init-method=“init” />
七、遍历后置处理器,调用after方法(aop是在这里生成的代理对象)
最后
doCreateBean方法最后,进行一次循环依赖检查,看当前bean所依赖的bean是否还有正在创建的,正常情况bean创建完后他依赖的bean一定都创建完了,如果还存在没创建完的bean就认为有循环依赖报错
数据库隔离级别
- 读未提交 脏读
- 读已提交 不可重复读
- 可重复读 幻读
可重复读指的是,T1读取 T2修改 T1再读(结果相同),是通过MVCC(多版本并发控制)机制实现的
数据行会有隐藏的版本号列,修改、删除时候不是真的删,而是多加一个记录,版本号不同,在读取时候,只能读当前小于等于事务所对应版本号的记录,所以才能做到读取结果都是同一个
幻读,并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的select操作得到的结果所表征的数据状态无法支撑后续的业务操作
更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,无论读多少次,都是读不到冲突的那个数据的,此时就发生了幻读。
分区备份
exchange partition
mysql分区备份
https://blog.51cto.com/daisywei/1900331
分库分表方案
- 应用层依赖组件 sharding-jdbc
- 中间代理层组件 mycat
本质都是拦截并且改写sql
mycat要注意的问题
1、查询要带字段,不能select *(某些版本)
2、要带分片字段,否则会到所有库查询一遍,一个查询变成n多个
3、分页要显式排序,否则返回结果不对,哪个先响应就返回哪个,并且结果集可能也不对(字段、字段值不匹配),并且分页查询是比较慢的
4、根据id分片的话,id必须有值,这种情况id是不能自增长的
mycat入门
https://blog.csdn.net/er_vel/article/details/82810055
分布式事务
基于MQ事务消息分布式事务
要点一,利用两段式提交保证生产者消息一定成功进入MQ,要点二,利用MQ重试机制实现最终一致性
事务消息属于一种特殊类型的消息,有prepare状态,该状态下对消费者是不可见的
1:系统A先向MQ发送事务消息
2:MQ收到消息后响应系统A
3:系统A收到响应,开始执行本地事务
4:系统A根据本地事务执行情况向MQ提交二次确认,对应commit 或是 rollback(如果是rollback状态MQ将直接删除prepare消息订阅方将不会接受该消息)
5:MQ收到Commit状态则prepare消息变成可投递类型
6:系统B作为消费方,最终将收到该消息,并执行本地事务(事务的最终一致性靠MQ的重试来实现)
异常情况
1:第【3】步系统A由于网络原因没有收到MQ响应
系统A要提供回查接口,MQ将轮询prepare状态的消息并调用回查接口获取本地事务执行状态
TCC
Try 负责资源的检查和预留
Confirm 执行真正的业务
Cancel 异常情况下资源的释放和取消
每个服务都要实现一套TCC逻辑,并且需要用数据库来感知和同步事务执行状态
XA规范,两段式、三段式
有协调者、参与者两个角色
两段提交
协调者向所有参与者发起询问,参与者收到询问后执行本地事务(但不提交)并响应执行结果,协调者判断响应,只要存在失败就向所有参与者发送回滚
三段提交
增加超时机制、多了一次预处理
中间件形式,阿里的GTS、Fescar