我想在服务器上保存一个冗长的表单输入。但我不认为对每个自动保存操作进行db调用是最好的方法。
解决这个问题的好方法是什么?
另一个问题是我有3个app服务器。所以在内存中缓存不会起作用。
我在考虑将数据保存在redis中并在每次调用时更新它,最后更新数据库。但由于我有3台服务器,我如何确保呼叫在队列中?
任何人都可以帮助建筑吗?
答案 0 :(得分:7)
但我不认为对每个自动保存操作进行db调用是最好的方法。
这是真正的问题,让我们从那开始吧。你为什么那么想? 你想要自动保存,对吧?这是保存用户工作的唯一方法。
您列出的所有其他选项(memcached / redis,进程内缓存) - 不仅不会保存用户工作,而且还会记录定时炸弹。想想那些可能在那里失败的事情:redis死亡,网络分裂,整个数据中心被雷击。
为什么在你可以......保存时创造所有的复杂性?您可能会发现它并不那么慢(如果这是您的担忧)。
答案 1 :(得分:2)
这是扩展体系结构时遇到的一个非常经典的问题,但是后来我们开始扩展,因为基本上您的初始应用程序需要多次调用数据库级别才能优先进行优化。
由于你没有给你的iops提供任何细节,我将在下面描述解决它的方法,按照递增的顺序,所有方法都是级联性的,这是最后一种方法实际建立在以前的所有方法上解决方案:
直接数据库方法{db调用每次自动保存操作}:
客户 - >应用层 - >数据库(直接在这里保存数据)
基本上在任何数据更新中,我们直接将其传播到数据库级别。此架构中的主要块是数据库 这种方法需要注意的事项:
对于最常用的关系数据库,如Mysql:
但是在任何中型应用程序中,单个表单修改需要30-40个请求,更新查询将阻止您的数据库资源。
因此,请保留一个附录类型的架构,例如可能维护一个二级密钥,如状态,跟踪用户填写表单的级别,但继续为每次更新插入数据。并且始终根据插入的最新状态进行阅读。
为了进一步优化,应该使用诸如外键约束之类的索引
当此步骤失败时,下一步是数据库本身,优化的下一步是,您正在处理的数据类型,您可以选择无模式数据库,如mongo,dynamodb等非交易数据
使用无模式数据库对于大量非事务性数据非常有用,因为它们允许附录方法处理同一行数据。
涉及应用层方法{应用层缓存}:
客户 - >应用层(在此处保存一些数据,然后再传播) - >数据库(最后保存在这里)
重新发明轮子:自定义级别应用程序层缓存+数据库缓存+数据库优化
客户 - >应用层(在此处保存一些数据) - > {添加数据库缓存} - >数据库(最后保存数据)
这是我们使用redis / Dynamodb / mongo设计我们自己的东西来充当主数据库的缓存的地方。 (请注意,如果首先使用非事务性数据库,请使用附录方法 - 这非常适合通过添加非事务性数据库的包装来扩展事务性数据库)
同样,express会话以相同的方式工作,实际上是通过在应用层上的redis上缓存数据,总是尝试尽可能减少对db的调用次数。
因此,如果你有一个功能齐全的应用程序层缓存和优化的数据库,那么就采用这种方法,因为它需要经验丰富的开发人员并且是资源密集型的,并且通常用于非常大规模的应用程序,例如我有一层redis快速会话后缓存一个平均每秒300k reqs的应用程序
此处的方法是将数据保存在用户会话中,将惰性写回应用于缓存。 Maritain缓存分类帐然后写入您的主数据库。对于这种大规模系统中的排队方法,我编写了一个完整的单独的微服务,它在后台工作,将数据从会话传输到redis到mysql,关注如何维护队列,更多地了解优先级队列和后台工作者。我使用了Kue is a priority job queue backed by redis, built for node.js.
答案 2 :(得分:1)
该解决方案成功应用于全行业。 配置3节点redis群集,负责数据复制。 写入仅发生在主节点上。
redis(master) - 应用服务器1, redis(slave1) - 应用服务器2, redis(slave2) - app server 3
使用slaveof:port命令添加slave很简单。 复制是通过线路完成的(不是临时磁盘存储) 链接 - https://redis.io/topics/replication