背景介绍:我们系统使用的缓存服务是付费版的阿里云的redis集群服务,配置是4核,16G。redis的集群结构如下:分为四个节点DB0,DB1,DB2,DB3

之前的存储方案是存储的商品促销数据,结构是:
KEY FIELD VALUE来存储。其中KEY是一个固定的字符串"zy:prom:wx",FIELD则是商品sku,VALUE是商品促销的具体信息。这种方式导致我们存入缓存服务器的数据一直集中在DB0节点上,在访问量过大时,该节点会在短时间内受到到的访问压力很大,DB0的cpu瞬间达到100%以上,造成服务卡顿甚至不可用。而相比之下DB1,DB2,DB3的节点cpu压力却很小,可以忽略不计。这是为什么?最后询问了阿里的技术,他们说我们的数据存储的方法有误,具体是我们的key设置有误。与阿里的技术对话如下:


总结:从上面对话中可以看出,阿里的redis集群数据存储的原理是根据key的hash值来做离散的。当一个数据key相同时,他和对应的数据都会被存入同一个节点机器上,这样也就造成了key"zy:prom:wx"对应的所有商品促销数据就会被存储到一个节点DB0上。而访问时也就只对DB0这台存储服务器造成压力,也就失去了集群原来的设计初衷。所以要想让数据分散存储到DB0-DB3四个节点上,需要把原本固定的"zy:prom:wx"这个key,让他不在固定。
所以我们后来改造了方案把key的组成变程了"prom:wx:sku",这样key就会根据sku的不同而不同,增大了key的离散度,这样key通过hash算出来的值,就会不同,使得所有的数据不再存放到同一台节点上,完美解决问题。
修改后的存储分布情况如下图:DB0、DB1、DB2、DB3四个节点数据均匀分布。

对修改前后两天同一时间区间的缓存服务器的cpu压力情况对比:

网友评论