美文网首页
java基础17-存储的一些事

java基础17-存储的一些事

作者: liwsh | 来源:发表于2021-08-16 16:16 被阅读0次

    1.订单创建和更新

    创建订单预先生成订单号,前端提交的时候带上订单号提交。订单号在数据库是唯一索引,保证前端重复提交只会生成一个订单
    订单更新的时候带版本号,每一条数据都有一个版本字段,更新一次加1。保证你更新的时候没有其他事务在更新,解决ABA问题。举例:事务A更新字段为666,事务B接着更新为888。事务A的前端超时了,重试更新为666。那数据会被错误的更新为666。

    2.商品详情页如何设计

    商品结构化的基本信息保存在mysql。商品参数和特征使用MongoDB,因为非格式化,酒,电子产品特征完全不一样。对象存储保存图片和视频。商品介绍静态化,nginx分发。

    3.购物车如何设计

    购物车数据保存在mysql或者redis,mysql主要考虑后续扩展和明细统计,redis主要考虑性能和对数据丢失的容忍程度

    4.账户余额设计

    修改账户余额与记录操作流水同一个事务。流水只能新增,不允许修改和删除,可以对冲

    5.跨系统数据一致性

    理论
    CAP:一致性,可用,分区容错
    BASE:基本可用,软状态,最终一致性
    强一致方案
    2pc:一阶段执行动作不提交,二阶段提交,RM一直没收到commit会阻塞。缺点:TM单点故障,提交过程RM没收到请求造成数据不一致,同步阻塞
    3pc:与二阶段相比,引入了超时机制 canCommit preCommit doCommit。如果第三阶段参与者没有收到协调者的请求,默认提交。这个时候也会导致数据不一致,因为可能第三阶段协调者是发回滚命令,而不是commit命令。
    基于base的柔性方案

    TCC:try:预锁资源,confirm:确认扣减资源,cancel:预锁资源没有全部成功,取消预锁。优点:无锁,缺点:业务改造成本高
    异常处理:
    「在try阶段」发生错误/异常/超时了需要进行cancel回滚,在这里需要考虑两种特殊情况:
    【被调用方收到了cancel,没有收到try】:这个时候被调用方由于没有进行try,所以不需要做任何处理,也就是「空回滚」
    【被调用方收到了cancel,之后又收到了try】:这个时候被调用方需要对前面的cancel进行空回滚,并对后面的try进行识别,识别出已经进行过cancel处理,故不再处理该次try调用,这也就是所谓的「防悬挂控制」;
    空回滚和防悬挂控制通常也可以采用引入事务控制表来进行实现;
    【在confirm、cancel阶段】的异常则需要重试或者需要人工介入处理;

    Saga:没有confirm的TCC,直接扣减,如果某一步异常,逆序补偿


    image.png

    与TCC区别,TCC是数据隔离的,在补偿期间,不会影响用户读数据。sage补偿期间影响用户读数据,读到的是脏数据,因为事务还没有最终提交,正在回滚中。
    最大努力通知:异步通知下游,最多通知N次。适用场景:对最终一致性时间敏感度低的服务,下游处理不影响上游业务
    可靠消息最终一致


    image.png
    image.png

    6.mysql主从同步

    image.png

    复制策略:
    异步复制:主库提交事务后,异步把日志复制到所有从节点,性能最好。主库宕机容易丢数据
    半同步复制,主库等待操作日志最少同步到N个从库后,再提交事务。这是在性能和数据安全中的一种折中

    7.数据越来越多如何处理

    1.归档。历史数据归档到另外的表中
    2.分库分表,原则能不拆就不拆,能少拆就少拆。数据量大分表,并发高分库。是否考虑二次扩容,尽量不要引入太复杂的设计,可以不考虑

    1. 分库分表键如何选择,订单号揉合很多其他信息(userId,分区等)。尽量不按时间分区,因为热点分片

    8.redis集群实践

    1.小规模集群可以使用官方的redis cluster,因为采取去中心化设计,redis每个节点都保存了所有槽和节点的映射关系,客户端可以访问任何一个节点,然后通过重定向找到数据。映射表如何更新,采用去中心化的流言协议,集群越大传播越慢
    2.代理集群模式,优点:客户端透明,就像访问单节点的redis一样。缺点:引入了代理层,性能,稳定性受到挑战,也引入了复杂度
    3.客户端定制方案,路由信息保存在客户端,通过zookeeper通知客户端更新路由信息。

    9.mysql同步redis

    流量非常大的系统,都是直接访问redis,不访问数据库。如何保证redis和mysql数据实时同步

    1. 业务代码发mq消息,启动一个服务消费mq更新redis。这个对业务有侵入性
    2. 消费mysql binlog日志,同步到redis。这个无业务侵入性,没有mq的收发引起的一致性问题。

    10.跨系统实时同步数据

    image.png

    11.点击流数据存储

    点击,监控,日志都是海量数据,互联网公司一般是先存储后计算。
    kafka:读写性能好,单节点吞吐量更高。存储不是无限容量
    hdfs:无限存储,查询更友好,吞吐量和读写性能较差
    有无集合kafka和hdfs优点的系统:
    1.分布式流数据存储pravega apache bookKeeper
    2.时序数据库:influxDB和openTSDB,主要用于存储监控数据

    12.newSql

    no sql具有高性能,可无限扩展
    sql:支持sql ACID,事务
    new sql:完美具备nosql 和 sql的优点 比如:CockroachDB

    13.rocksDB

    1.高性能的kv存储,越来越多的新生代数据库都是要它作为存储引擎
    2.与redis区别,性能较高20W,redis50w。支持持久化,不丢数据
    3.为什么依赖磁盘,rocksDB性能还如此高,采用顺序写。LSM-tree,适用写多读相对较少的场景
    4.LSM-Tree 全称是 Log Structured Merge Tree,是一种分层、有序、面向磁盘的数据结构,其核心思想是充分利用磁盘的顺序写性能要远高于随机写性能这一特性,将批量的随机写转化为一次性的顺序写

    相关文章

      网友评论

          本文标题:java基础17-存储的一些事

          本文链接:https://www.haomeiwen.com/subject/gfpfbltx.html