redis缓存一致性

本地缓存是指程序级别的缓存组件,它的特点是本地缓存和应用程序会运行在同一个进程中,所以本地缓存的操作会非常快,因为在同一个进程内也意味着不会有网络上的延迟和开销。

本地缓存适用于单节点非集群的应用场景,它的优点是快,缺点是多程序无法共享缓存,比如分布式用户 Session 会话信息保存,由于每次用户访问的服务器可能是不同的,
如果不能共享缓存,那么就意味着每次的请求操作都有可能被系统阻止,因为会话信息只保存在某一个服务器上,当请求没有被转发到这台存储了用户信息的服务器时,就会被认为是非登录的违规操作。
除此之外,无法共享缓存可能会造成系统资源的浪费,这是因为每个系统都单独维护了一份属于自己的缓存,而同一份缓存有可能被多个系统单独进行存储,从而浪费了系统资源。

分布式缓存是指将应用系统和缓存组件进行分离的缓存机制,这样多个应用系统就可以共享一套缓存数据了,它的特点是共享缓存服务和可集群部署,为缓存系统提供了高可用的运行环境,
以及缓存共享的程序运行机制。

分布式缓存可以使用 Redis 或 Memcached 来实现。由于 Redis 本身就是独立的缓存系统,因此可以作为第三方来提供共享的数据缓存,而 Redis 的分布式支持主从、哨兵和集群的模式,
所以它就可以支持分布式的缓存,而 Memcached 的情况也是类似的。


本地缓存的问题:
本地缓存速度一开始高于分布式缓存,但是随着其缓存数量的增加,所占内存越来越大,系统运行内存越来越小,最后系统会被拖慢(这一点与第二点联系起来)
本地缓存存于本机,其缓存数量与大小受本机内存大小限制
本地缓存存于本机,其他机器的访问不到这样的缓存

解决方案:分布式缓存
Jboss cache:缓存还存于本机,但是会同步更新到其他机器(解决了第三个问题,解决不了第一和第二个问题),如果缓存机器数量很多,同步更新很耗时
memcached:缓存存于其他机器,理论上缓存数量与大小无限(因为集群可伸缩),且不需要同步,所以即使缓存机器数量很多,也无所谓,但是这样就会造成单点故障问题,
最简单易行的解决方案是缓存备份,即缓存至少存两份。


Redis可以存储复杂的数据结构(5种)
strings-->即简单的key-value,就是memcached可以存储的唯一的一种形式,接下来的四种是memcached不能直接存储的四种格式(当然理论上可以先将下面
的一些数据结构中的东西封装成对象,然后存入memcached,但是不推荐将大对象存入memcached,因为memcached的单一value的最大存储为1M,可能即使采用了压缩算法也不够,
即使够,可能存取的效率也不高,而redis的value最大为1G)
有两种方式可以对缓存数据进行持久化RDB,AOF。就我个人而言,如果需要使用分布式缓存,那么首先redis是必选的,因为在实际开发中,我们会缓存各种各样的数据类型,
在使用了redis的同时,memcached就完全可以舍弃了,但是现在还有很多公司在同时使用memcached和redis两种缓存。


如果对数据库和缓存具有强一致性要求时,不要利用缓存了,因此根据CAP理论,只要涉及到双写就一定存在一致性问题。我们今天讨论的前提是对于缓存与数据库没有强一致要求。
如果可以容忍暂时的不一致,通常的做法给缓存设置一个过期时间,所有的写操作都以数据库为准,缓存过期后从数据库中取值,保存了数据最终一致性,尽可能得降低数据库和缓存之间的不一致。

缓存与数据库一致性,讨论的前提是业务场景不要求缓存与数据之间的强一致性。比如订单支付问题不建议使用缓存,
如果有人面试中不分青红皂白的说如何保证缓存与数据库的强一致性,大家可以让他gun了。

redis 作为 mysql 缓存
通常的开发模式中,都会使用 mysql 作为存储,而 redis 作为缓存,加速和保护 mysql。但是,当 mysql 数据更新之后,redis 怎么保持同步呢。
强一致性同步成本太高,如果追求强一致,那么没必要用缓存了,直接用 mysql 即可。通常考虑的,都是最终一致性。一般先数据先写数据库,在写到缓存,缓存是方便下次访问。
一般最好让用户访问同一台机器,这样可以减少访问数据库的次数,提高缓存命中率。缓存只做失效不做更新(是一种方案,但不一定)。

当前大多数的互联网系统都使用了服务器集群技术,集群即将相同服务部署在多台服务器上构成一个集群整体对外提供服务,
这些集群可以是Web应用服务器集群,也可以是数据库服务器集群,还可以是分布式缓存服务器集群等。

Redis3.0版本允许单点故障,它没有中心节点,各个节点地位一样,扩展性很好,节点间的采用二进制通信,节点与客户端采用ascII协议通信。
多个redis的client同时set key引起的并发问题。其实redis自身就是单线程操作,多个client并发操作,先到的先执行,其余的阻塞。
另外的解决方案是把redis.set操作放在队列中使其串行化,必须的一个一个执行。

posted @ 2016-05-09 20:14  南哥的天下  阅读(4317)  评论(1编辑  收藏  举报