在逛各大电商网站的时候,总会有将商品加入购物车,然后合并付款,这个大大的提高了用户的体验,某东更是任性,在未登录的情况下都可以将商品加入购物车,但是任性总是有代价的,后面我会说一下这个小bug。可能不算是个bug,但是体验上也有不爽的地方。
还是谈谈购物车是如何实现的吧,购物车首先标识要唯一,因为每个账号要对应一个购物车,在登录状态下,我们可以直接将数据保存到数据库中,使用用户的id表示自己购买的商品,但是如果在未登录状态下呢,或者对购车访问量大的时候,这个就存在弊端,因为这样高速的读写数据库,会对数据库的压力比较大,在这里我们就看看如何用Redis和RabbitMQ解决这个问题。
第一章:登录状态下添加商品到购物车
此时购物车是对应一个用户,很简单,就是将商品的数据插入数据库中即可,但是如果读写频繁的时候,就存在压力问题,此时我们可以使用Redis担任读的部分功能。
在向数据库中插入数据的时候,使用RabbitMQ发送消息,然后有一个消息系统监听消息,将RabbitMQ中消息内容(插入数据库中的商品数据)保存到Redis中,但是此时Redis中我们该用什么存储结构,在Redis中存储结构有很多种,这里我们使用hash结构,看下面的图,分析一下hash结构:
从上面的图我们可以看的出来,这个图有两个键,一个是外部键,一个是内部键,这个就体现了购物车的好处,这里外部键可以标记一个唯一的购物车,内部键就可以标记购物车上的一个商品,一个外部键可以对应多个内部键,这个和一个购物车里有多个商品是相符合的,在用户查询自己的购物车数据的时候,就不要到数据库中查询,而是直接从redis中将数据拿出来即可,这样数据库的读压力就被Redis分担出去了。
就这样把登录状态下购物车问题解决了。
第二章:未登录下加入购物车,登录下合并购物车
在未登录状态下,没有指定的用户,此时购物车应该怎么分配,数据把偶才能在什么位置,这个其实也不难,我们可以将数据临时保存到Redis中,并不插入数据库中,因为此时没有对应的用户,Redis生成一个唯一的outerKey,保存到cookie中,每次添加商品,带上这个cookie,这样就保证每次加入同一个购物车,这个数据会被保存一段时间,当用户登录的时候,我们该如何将未登录状态下的购车和登录状态下的购车数据合并呢。这个就需要使用到消息了,我们可以发送一个消息给后台系统,将未登录状态下的outerKey传递给后台系统,后台系统到Redis中查询到未登录状态下的购物车,将购物车中的数据插入到数据库中,和之前登录状态下的购车数据合并,重新缓存到Redis中,此时缓存到Redis中的购物车是和未登录状态不同的,因为这个缓存的购物车是有主人的,未登录状态下缓存的临时购物车是没有主人的。
小小bug的解析:
在开头我们曾说到未登录状态下加入临时购物车,登录后合并到登录用户的购物车中,接下来我看一下这个场景。
小王用小李的电脑逛商城,没有登录,将看中的商品加入到了临时的购物车中,小王还没有来得及登录自己的账号结算购物车,因有事出去了一下,此时小李回来了,他想到之前自己的购物车里还有商品需要付款,他就毫不犹豫的登录了自己的账号,这时候问题来了,小王之前临时购物车中的商品都会合并到小李的账户下,小李的购物车凭空出现自己未加入购物车的商品。过了一会小王回来了,发现自己临时购物车中的数据都没有了。这样是不是就存在用户体验的问题,俗称灵异事件,呵呵,开个玩笑。这种情况就导致了用户的体验不好了。
上面的问题我也想过解决方案,但是无果,求各路大神共同解决。
疑问解决:
1、Redis担任读的问题,当像双11这种大量访问的情况下,Redis会不会崩溃?
这个问题我也想过,这个我们可以考虑使用Redis的集群,这样就可以解决大部分的问题。
2、数据库也可以做读写分离,为什么要使用Redis担任读呢,直接使用读写分离不就可以了吗?
数据库的读写分离的确可以解决问题,但是像Redis这种非关系型数据库比较明显的优点就是数据处理效率高,读写分离和Redis的效率相比较来说,个人感觉还是使用Redis可靠。
3、在文章中提到RabbitMQ消息机制,这个到底怎么用?
这个吗,说来话长,在接下来的博文中我会慢慢的道来RabbitMQ的基本使用和RabbitMQ与spring的整合。
如果还存在什么疑问,很欢迎你回复本帖,大家一起讨论。
转至:http://blog.csdn.net/millery22/article/details/49756667