暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

记一次分布式系统本地缓存设计方案

小度do 2021-09-12
666

一、背景

  1. 项目部署架构

    2. 业务背景

    电商系统用户访问商品详情页时,对商品SKU进行白名单校验,白名单在管理系统由业务人员维护。如果当前商品SKU在白名单中,则在商品详情页露出指定入口;反之则不露出指定入口。

    3. 实现目标

    由于商品详情页访问量很高,为了保证接口的访问性能,校验过程需要在本地缓存完成,所以需要将数据库的白名单在本地缓存维护一份。

二、方案设计

  1. 方案核心设计思路

    采用redis来完成本地缓存的增量维护设计。先说管理系统端的设计,当业务人员对某个SKU执行写操作时,将本次操作的SKU保存到redis的一个set集合中,待C端服务器中的定时任务拉取更新到本地缓存。这里需要考虑几个问题,一是C端的服务器何时去拉取redis中存储的变更SKU;二是如何确定变更的SKU需要添加还是删除本地缓存;三是当更新完变更的SKU到本地缓存后,如何处理更新后的SKU。

    1.1 C端的服务器何时去拉取redis中存储的变更SKU。这里采用定时任务轮巡的方式拉取变更SKU的集合,但不是每次拉取都要更新,这里我们在redis远程缓存中维护一个业务人员操作SKU变更的版本号,本地缓存也维护一个版本号。当业务人员操作一次管理端变更SKU时,版本号递增一次。本地缓存维护的版本号最初先到远程缓存拉取,如果有则存入本地缓存;如果远程没有,则初始化为0存入本地缓存,其实远程缓存没有这个版本号只会发生在项目刚刚上线,没有业务人员操作SKU前,以后就都会有这个版本号了。这样设计的目的在于,当本地缓存定时任务执行时,先拉取远程版本号跟本地的版本号进行对比,如果版本发生变更,则代表远程缓存有变更的SKU需要维护到本地缓存,执行维护操作,维护完毕后对本地缓存的版本号置为远程的最新版本号;否则不执行更新本地缓存操作。

    1.2 二是如何确定变更的SKU需要添加还是删除本地缓存。这个操作只需要将拿到的变更的SKU与数据库执行一次数据对齐即可,数据库存在则向本地缓存执行一次添加; 数据库不存在,则从本地缓存删除。这里会存在ABA问题的场景,不过这个不影响本地缓存的维护。

    1.3 当更新完变更的SKU到本地缓存后,如何处理更新后的SKU。这个问题如果放在单机部署的系统环境处理起来就非常容易了,完成一次本地缓存更新后,就删除本次更新的SKU即可。但是在分布式系统环境下,由于每一个节点都要维护一个本地缓存,所以如果手动去删除,会存在有的节点更新不到,即版本丢失的情况。所以这里我们采用redis本身定时清除,那么此时对于变更SKU的集合就不能只维护一份了,要针对于每一次的变更单独维护一份远程的SKU变更集合,同时设置一个定时过期,过期时间只要能保证每个版本的变更SKU集合都能被集群的每个节点维护完成即可。这里的核心是变更集合key的设计,上面说到我们在redis中会维护一个变更SKU的总版本号,那么现在我们还要对每一次变更SKU的集合的key在维护一个版本号的后缀,这样当C端服务器拉取到总版本号后,再去拉取比本地缓存维护版本大的所有远程SKU变更的集合,直到版本号等于本次拉取到的远程的总版本号,然后执行本地缓存维护操作。

  1. 分析考虑方案设计的优缺点

    这是一种典型的空间换时间的设计思想,本方案的设计实现了本地缓存的增量维护,但需要占用redis的存储空间,同时本地缓存也是一笔不小的开销。总的来说对接口的性能有保证,而且对于SKU的变更基本等于实时的同步到集群的每一个节点的本地缓存。当然这里采用zookeeper设计也是很好的方案,但如果系统中没有使用到zookeeper,而仅仅为了实现本地缓存的维护引入他,对于成本上也是一笔不小的开销。

三、结语

    分布式系统环境复杂,需要考虑的因素也多。在分布式系统环境下考虑任何的设计方案时,都要考虑到跨进程操作,这点很重要。


文章转载自小度do,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论