it_worker365

   ::  ::  ::  ::  :: 管理

读多写少,优化性能  application -> cache(快) -> DB(慢)

缓存命中率 = 命中的 / 总的

写入操作时,更新缓存(写入DB && 写入缓存 计算简单的时候,直接更新,增加一次命中率)/淘汰缓存(写

入DB,只淘汰数据,计算复杂时,比更新操作简单,但会增加一次不命中)

处理时应先写入缓存,再写入DB,如果DB失败,则缓存多一次失效。如果先DB后缓存,这时缓存失败了,则缓存数据和DB数据出现不一致

实现方案:中间加入服务层/写请求都到DB,都请求都到cache,异步工具来做db与缓存间的同步(这种太复杂了点吧)

服务化是向业务方屏蔽底层cache与db复杂性的一种通用解决方式

 

用户想查找自己的订单列表,分页,列表会变 (uid -> list<oid> ,uid的订单新增时,删除缓存)

频繁删除redis key会产生很多内存碎片,导致内存占用率越来越大,最后不得不重启释放内存

连接池每次取出一个连接后并发执行,想串行化这种操作,考虑在获取连接时按照业务ID取模

---------------------------------------------------------------------------------------------------------

例如订单表,业务上对用户和商家都有订单查询需求:

Order(oid, info_detail)

T(buyer_id, seller_id, oid)

如果用buyer_id来分库,seller_id的查询就需要扫描多库。

如果用seller_id来分库,buyer_id的查询就需要扫描多库。

这类需求,为了做到高吞吐量低延时的查询,往往使用“数据冗余”的方式来实现,就是文章标题里说的“冗余表”:

T1(buyer_id, seller_id, oid)

T2(seller_id, buyer_id, oid)

同一个数据,冗余两份,一份以buyer_id来分库,满足买家的查询需求;

一份以seller_id来分库,满足卖家的查询需求。

具体实现:

双写

异步消息投递

通过log接触耦合,线下异步写

 

谁先来?哪种对业务影响小哪种先来,一切为业务服务

以上文的订单生成业务为例,buyer和seller冗余表都需要插入数据:

T1(buyer_id, seller_id, oid)

T2(seller_id, buyer_id, oid)

用户下单时,如果“先插入buyer表T1,再插入seller冗余表T2”,当第一步成功、第二步失败时,出现的业务影

响是“买家能看到自己的订单,卖家看不到推送的订单”

相反,如果“先插入seller表T2,再插入buyer冗余表T1”,当第一步成功、第二步失败时,出现的业务影响是“卖家能看到推送的订单,卖家看不到自己的订单”

由于这个生成订单的动作是买家发起的,买家如果看不到订单,会觉得非常奇怪,并且无法支付以推动订单状态的流转,此时即使卖家看到有人下单也是没有意义的。

因此,在此例中,应该先插入buyer表T1,再插入seller表T2。

 

一致性保证:

线下离线扫描,对比两个表,不一致进行修补

写入表,写入log,线下增量扫描log,对比两个表,不一致进行修补canal

写入表,发送消息msg1,写入另一个表,发送消息msg2,检查两个消息的间隔,确定是否需要修补

 

posted on 2017-05-31 17:57  it_worker365  阅读(472)  评论(0编辑  收藏  举报