redis缓存实现原理
Ⅰ redis缓存原理
1、Redis是一种内存高速cache,如果使用redis缓存,那经常被访问的内容会被缓存在内存中,需要使用的时候直接从内存调取,不知道比硬盘调取快了多少倍,并且支持复杂的数据结构,应用于许多高并发的场景中。
2、Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。zset是set的一个升级版本,他在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,zset会自动重新按新的值调整顺序。可以理解了有两列的mysql表,一列存value,一列存顺序。操作中key理解为zset的名字。
更多关于redis缓存原理,进入:https://www.abcgonglue.com/ask/66eab61616100681.html?zd查看更多内容
Ⅱ SpringBoot进阶之缓存中间件Redis
大家好,一直以来我都本着 用最通俗的话理解核心的知识点, 我认为所有的难点都离不开 “基础知识” 的铺垫
“大佬可以绕过 ~”
本节给大家讲讲 “java的SpringBoot框架” , 之前我们学习的都是java的基础知识和底层提供的一些能力,我们日常工作都是在写接口。在我们在产品开发中,一般我们都会选择比较稳定的框架来帮我们加速开发,不会自己去造轮子,而在java众多框架中,spring框架表现的非常好,大部分公司都会首选它作为开发框架,而至今,大部分企业都是以 springboot 来构建项目了,一个稳健的系统需要引入稳定的技术~
如果你是一路看过来的,很高兴你能够耐心看完。前几期都是带大家学习了 SpringBoot 的基础使用以及集成 mybatis 开发,这也是我们写业务的基础,如果你还不熟悉这些,请先看完它们。接下来的几期内容将会带大家进阶使用,会先讲解基础 中间件 的使用和一些场景的应用,或许这些技术你听说过,没看过也没关系,我会带大家一步一步的入门,耐心看完你一定会有 收获 ,本期将会给大家讲解最热门的缓存中间件技术 Redis ,同样的,我们集成到 Springboot 中。最近github可能会被墙,所以我把源码放到了国内gitee上,本节我们依然使用上期的代码
Redis 是由意大利人Salvatore Sanfilippo(网名:antirez)开发的一款内存高速缓存数据库。全称叫 Remote Dictionary Server(远程数据服务) 是由 C语言 编写的,Redis是一个 key-value 存储系统,它支持丰富的数据类型,如: string、list、set、zset(sorted set)、hash 。
它本质上是一种键值对数据库,我们之前学习的 mysql 它是持久层的关系型数据库,而 redis 它的存储主要存在 内存 中。我们都知道在 内存 中的数据读取是非常快的,就好比你把一个变量存到磁盘读取和直接放到代码中运行,肯定是在代码中拿到的速度快,因为运行时期,都是直接存到内存的。
给大家总结一下:
有了基本的概念之后,我们下面进行环境搭建,在学习阶段,安装 redis 很简单,生产环境一般我们也会选择云产品,一切为了服务保障,虽说它只是做缓存用,但也是系统的一把 保护伞
如果你是 mac 用户,你可以运行如下命令:
安装完成后会提示你运行命令,运行即可。
win 用户也很简单,直接下载 redis 软件,双击运行即可,运行之后它会有一个小方块的图案,和 locahost:6379 的log,说明运行成功了。初始阶段没有配置的 redis 默认 host 就是本地, port 就是 6379 , 而且是 没有密码 就可以访问的。
推荐一个客户端软件 Redis Desktop Manager ,它是 redis 的客户端界面软件,方便面我们学习的时候 清理缓存 使用,生产慎连。
我们不给大家讲它的基本命令使用,它也有语法,可以通过类似命令执行,如果想学习的小伙伴,可以自行搜索。本期重点内容是在 sprinboot 中的使用,我们平时开发不可能是去命令行里敲的,都是代码里执行,而目前市面上有很多封装好的库,我们可以直接调用它的方法,很方便的就可以操作它了,不用记一些繁琐的命令,下面我们就实际操作一下:
修改 pom.xml
修改 application.yml :
redis 默认是有 16 个库,不是 15 个啊,从 0 开始算的,我们随便连一个
通过代码很好理解, 首先需要引入 StringRedisTemplate ,然后需要设置一个 key ,那么思考一下,这个 key 允许重复吗
我们进客户端看一下,发现 key 还是只有一个,但是值变成了新的值了,所以可以得知 key 是唯一的,我们重新设置的时候相当于刷新了它。
在 redis 中删除缓存有两种方式,一种是自我消亡,也就是 过期 销毁,还有有一种是 主动 销毁,我们先看一下,过期时间如何设置
我们设置了 10s 后过期,过完10s后发现,这个```key data``消失了。我们在看看如何主动删除
我们可以利用 Redis 做一个计数器,实现自增功能,你可以用它做网站访问统计
通常做法,我们会把它封装一下,后续使用直接引入封装好的即可,把它直接交给 Springboot容器 管理
其实这个类,你还可以继续进一步封装,比如约束 key 的规范,约束过期时间,约束数据类型等等,这一切也都是为了规范和后期维护,防止滥用缓存
缓存的主要场景是用于解决热点数据问题,因为这些数据是访问频率比较高的,当大量的请求进来, mysql 可能压力很大,这样一来,数据查询效率就很慢,用户肯不高兴等了,这样用户体验很不好。所以我们一般做法,都是把这些热点数据放到缓存里,因为缓存读取速度很快。当有新数据的时候,我们再及时更新它,一般流程是先查询缓存,查到了直接返回缓存数据,查不到再走数据库,然后再刷回缓存。
但是并发足够大的时候,还是会暴露出很多问题,比如面试常问的一些高频问题 缓存雪崩、缓存穿透、缓存雪崩 ,这些问题后边会给大家专门讲,和如何去防范。所以总的来说,引入任何一门技术并不是万事大吉,还需我们不断的在实践中积累经验
本期到这里就结束了,总结一下,我们了解了什么是 redis ,以及在 springboot 中如何去使用它们,很简单,没什么复杂的东西。但这里想多说一点的是,缓存的设计却是很复杂的,因为工具是死的,人是活的,我们如何正确设计,需要我们在项目中不断的积累。
我们之前教大家查询列表数据,都是所有数据返回,还没有教大家如何去做分页,下期将带大家学习一下 mybatis 分页插件的使用 ,下期不见不散, 关注我,不迷路~
Ⅲ redis做mysql的缓存
redis缓存其实就是把经常访问的数据放到redis里面,用户查询的时候先去redis查询,没有查到就执行sql语句查询,同时把数据同步到redis里面。redis只做读操作,在内存中查询速度快。
使用redis做缓存必须解决两个问题,首先就是确定用何种数据结构存储来自mysql的数据;确定数据结构之后就是需要确定用什么标识来作为数据的key。
mysql是按照表存储数据的,这些表是由若干行组成。每一次执行select查询,mysql都会返回一个结果集,这个结果是由若干行组成的。redis有五种数据结构:列表list,哈希hash,字符串string,集合set,sorted set(有序集合),对比几种数据结构,string和hash是比较适合存储行的数据结构,可以把数据转成json字符串存入redis。
全量遍历键: keys pattern keys *
有人说 KEYS 相当于关系性数据的库的 select * ,在生产环境几乎是要禁用的
不管上面说的对不对, keys 肯定是有风险的。那我们就换一种方案,在存数据的时候。把数据的键存一下,也存到redis里面选hash类型,那么取的时候就可以直接通过这个hash获取所有的值,自我感觉非常好用!
Ⅳ 缓存-redis 三种模式搭建和运行原理
标签: redis 缓存 主从 哨兵 集群
本文简单的介绍redis三种模式在linux的安装部署和数据存储的总结,希望可以相互交流相互提升。
对于Centos7在安装redis之前需要进行一些常用工具的安装:
关闭防火墙
正式安装redis
在redis进行maketest时候会出现一系列的异常,有如下解决方案:
用redis-server启动一下redis,做一些实验没什么意义。
要把redis作为一个系统的daemon进程去运行的,每次系统启动,redis进程一起启动,操作不走如下:
RDB和AOF是redis的一种数据持久化的机制。 持久化 是为了避免系统在发生灾难性的系统故障时导致的系统数据丢失。我们一般会将数据存放在本地磁盘,还会定期的将数据上传到云服务器。
RDB 是redis的snapshotting,通过redis.conf中的save配置进行设置,如 save 60 1000:
AOF 是以appendonly方式进行数据的储存的,开启AOF模式后,所有存进redis内存的数据都会进入os cache中,然后默认1秒执行一次fsync写入追加到appendonly.aof文件中。一般我们配置redis.conf中的一下指令:
AOF和RDB模式我们一般在生产环境都会打开,一般而言,redis服务挂掉后进行重启会优先家在aof中的文件。
当启动一个slave node的时候,它会发送一个PSYNC命令给master node,如果这是slave node重新连接master node,那么master node仅仅会复制给slave部分缺少的数据;否则如果是slave node第一次连接master node,那么会触发一次full resynchronization;
开始full resynchronization的时候,master会启动一个后台线程,开始生成一份RDB快照文件,同时还会将从客户端收到的所有写命令缓存在内存中。RDB文件生成完毕之后,master会将这个RDB发送给slave,slave会先写入本地磁盘,然后再从本地磁盘加载到内存中。然后master会将内存中缓存的写命令发送给slave,slave也会同步这些数据。
slave node如果跟master node有网络故障,断开了连接,会自动重连。master如果发现有多个slave node都来重新连接,仅仅会启动一个rdb save操作,用一份数据服务所有slave node。
从redis 2.8开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份。
master node会在内存中常见一个backlog,master和slave都会保存一个replica offset还有一个master id,offset就是保存在backlog中的。如果master和slave网络连接断掉了,slave会让master从上次的replica offset开始继续复制,但是如果没有找到对应的offset,那么就会执行一次resynchronization。
master在内存中直接创建rdb,然后发送给slave,不会在自己本地落地磁盘了,可以有如下配置:
slave不会过期key,只会等待master过期key。如果master过期了一个key,或者通过LRU淘汰了一个key,那么会模拟一条del命令发送给slave。
在redis.conf配置文件中,上面的参数代表至少需要3个slaves节点与master节点进行连接,并且master和每个slave的数据同步延迟不能超过10秒。一旦上面的设定没有匹配上,则master不在提供相应的服务。
sdown达成的条件很简单,如果一个哨兵ping一个master,超过了 is-master-down-after-milliseconds 指定的毫秒数之后,就主观认为master宕机
sdown到odown转换的条件很简单,如果一个哨兵在指定时间内,收到了 quorum 指定数量的其他哨兵也认为那个master是sdown了,那么就认为是odown了,客观认为master宕机
如果一个slave跟master断开连接已经超过了down-after-milliseconds的10倍,外加master宕机的时长,那么slave就被认为不适合选举为master
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
每次一个哨兵要做主备切换,首先需要quorum数量的哨兵认为odown,然后选举出一个slave来做切换,这个slave还得得到majority哨兵的授权,才能正式执行切换;
(2)SENTINEL RESET *,在所有sentinal上执行,清理所有的master状态
(3)SENTINEL MASTER mastername,在所有sentinal上执行,查看所有sentinal对数量是否达成了一致
4.3.2 slave的永久下线
让master摘除某个已经下线的slave:SENTINEL RESET mastername,在所有的哨兵上面执行.
redis的集群模式为了解决系统的横向扩展以及海量数据的存储问题,如果你的数据量很大,那么就可以用redis cluster。
redis cluster可以支撑N个redis master,一个master上面可以挂载多个slave,一般情况我门挂载一个到两个slave,master在挂掉以后会主动切换到slave上面,或者当一个master上面的slave都挂掉后,集群会从其他master上面找到冗余的slave挂载到这个master上面,达到了系统的高可用性。
2.1 redis cluster的重要配置
2.2 在三台机器上启动6个redis实例
将上面的配置文件,在/etc/redis下放6个,分别为: 7001.conf,7002.conf,7003.conf,7004.conf,7005.conf,7006.conf
每个启动脚本内,都修改对应的端口号
2.3 创建集群
解决办法是 先安装rvm,再把ruby版本提升至2.3.3
使用redis-trib.rb命令创建集群
--replicas: 表示每个master有几个slave
redis-trib.rb check 192.168.31.187:7001 查看状体
3.1 加入新master
以上相同配置完成后,设置启动脚本进行启动;然后用如下命令进行node节点添加:
3.2 reshard一些数据过去
3.3 添加node作为slave
3.4 删除node
Ⅳ redis是怎么实现的
第一:Redis 是什么?
Redis是基于内存、可持久化的日志型、Key-Value数据库 高性能存储系统,并提供多种语言的API.
第二:出现背景
数据结构(Data Structure)需求越来越多, 但memcache中没有, 影响开发效率
性能需求, 随着读操作的量的上升需要解决,经历的过程有:
数据库读写分离(M/S)–>数据库使用多个Slave–>增加Cache (memcache)–>转到Redis解决写的问题:
水平拆分,对表的拆分,将有的用户放在这个表,有的用户放在另外一个表;可靠性需求
Cache的"雪崩"问题让人纠结
Cache面临着快速恢复的挑战开发成本需求
Cache和DB的一致性维护成本越来越高(先清理DB, 再清理缓存, 不行啊, 太慢了!)
开发需要跟上不断涌入的产品需求
硬件成本最贵的就是数据库层面的机器,基本上比前端的机器要贵几倍,主要是IO密集型,很耗硬件;维护性复杂
一致性维护成本越来越高;
BerkeleyDB使用B树,会一直写新的,内部不会有文件重新组织;这样会导致文件越来越大;大的时候需要进行文件归档,归档的操作要定期做;
这样,就需要有一定的down time;
基于以上考虑, 选择了Redis
第三:Redis 在新浪微博中的应用
Redis简介
1. 支持5种数据结构
支持strings, hashes, lists, sets, sorted sets
string是很好的存储方式,用来做计数存储。sets用于建立索引库非常棒;
2. K-V 存储 vs K-V 缓存
新浪微博目前使用的98%都是持久化的应用,2%的是缓存,用到了600+服务器
Redis中持久化的应用和非持久化的方式不会差别很大:
非持久化的为8-9万tps,那么持久化在7-8万tps左右;
当使用持久化时,需要考虑到持久化和写性能的配比,也就是要考虑redis使用的内存大小和硬盘写的速率的比例计算;
3. 社区活跃
Redis目前有3万多行代码, 代码写的精简,有很多巧妙的实现,作者有技术洁癖
Redis的社区活跃度很高,这是衡量开源软件质量的重要指标,开源软件的初期一般都没有商业技术服务支持,如果没有活跃社区做支撑,一旦发生问题都无处求救;
Redis基本原理
redis持久化(aof) append online file:
写log(aof), 到一定程度再和内存合并. 追加再追加, 顺序写磁盘, 对性能影响非常小
1. 单实例单进程
Redis使用的是单进程,所以在配置时,一个实例只会用到一个CPU;
在配置时,如果需要让CPU使用率最大化,可以配置Redis实例数对应CPU数, Redis实例数对应端口数(8核Cpu, 8个实例, 8个端口), 以提高并发:
单机测试时, 单条数据在200字节, 测试的结果为8~9万tps;
2. Replication
过程: 数据写到master–>master存储到slave的rdb中–>slave加载rdb到内存。
存储点(save point): 当网络中断了, 连上之后, 继续传.
Master-slave下第一次同步是全传,后面是增量同步;、
3. 数据一致性
长期运行后多个结点之间存在不一致的可能性;
开发两个工具程序:
1.对于数据量大的数据,会周期性的全量检查;
2.实时的检查增量数据,是否具有一致性;
对于主库未及时同步从库导致的不一致,称之为延时问题;
对于一致性要求不是那么严格的场景,我们只需要要保证最终一致性即可;
对于延时问题,需要根据业务场景特点分析,从应用层面增加策略来解决这个问题;
例如:
1.新注册的用户,必须先查询主库;
2.注册成功之后,需要等待3s之后跳转,后台此时就是在做数据同步。
第四:分布式缓存的架构设计
1.架构设计
由于redis是单点,项目中需要使用,必须自己实现分布式。基本架构图如下所示:
2.分布式实现
通过key做一致性哈希,实现key对应redis结点的分布。
一致性哈希的实现:
lhash值计算:通过支持MD5与MurmurHash两种计算方式,默认是采用MurmurHash,高效的hash计算.
l一致性的实现:通过java的TreeMap来模拟环状结构,实现均匀分布
3.client的选择
对于jedis修改的主要是分区模块的修改,使其支持了跟据BufferKey进行分区,跟据不同的redis结点信息,可以初始化不同的 ShardInfo,同时也修改了JedisPool的底层实现,使其连接pool池支持跟据key,value的构造方法,跟据不同 ShardInfos,创建不同的jedis连接客户端,达到分区的效果,供应用层调用
4.模块的说明
l脏数据处理模块,处理失败执行的缓存操作。
l屏蔽监控模块,对于jedis操作的异常监控,当某结点出现异常可控制redis结点的切除等操作。
整个分布式模块通过hornetq,来切除异常redis结点。对于新结点的增加,也可以通过reload方法实现增加。(此模块对于新增结点也可以很方便实现)
对于以上分布式架构的实现满足了项目的需求。另外使用中对于一些比较重要用途的缓存数据可以单独设置一些redis结点,设定特定的优先级。另外对 于缓存接口的设计,也可以跟据需求,实现基本接口与一些特殊逻辑接口。对于cas相关操作,以及一些事物操作可以通过其watch机制来实现。
声明:所有博客服务于分布式框架,作为框架的技术支持及说明,框架面向企业,是大型互联网分布式企业架构,后期会介绍linux上部署高可用集群项目。
Ⅵ 怎么实现redis的数据库的缓存(redis实现缓存的流程)
大致为两种措施:
一、脚本同步:
1、自己写脚本将数据库数据写入到redis/memcached。
2、这就涉及到实时数据变更的问题(mysqlrowbinlog的实时分析),binlog增量订阅Alibaba的canal,以及缓存层数据丢失/失效后的数据同步恢复问题。
二、纯贺业务层实现:
1、先读取nosql缓存层,没有数据再读取mysql层,并写入数据到nosql。
2、nosql层做好多节点分布式(一致性hash),以及节点失效后替代方案(多层hash寻找相邻替代节点),和数据震荡恢复了。
redis实现数据库缓存的分析:
对于变化频率非常快的数据来说,如果还选择传统的静态缓存方式(Memocached、FileSystem等)展示数据,可能在缓存的存取上会有很大的开销则裤差,并不能很好的满足需要,而Redis这样基于内存的NoSQL数据库,就非常适合担任实时数据的容器。
但是往往又有数据可靠性的需求,采用MySQL作为数据存储,不会因为内存问题而引起数据丢失,同时也可以利用关系数据库的特性实现很多功能。所以就会很自然的想到是否可以采用MySQL作为数据存孙皮储引擎,Redis则作为Cache。
MySQL到Redis数据复制方案,无论MySQL还是Redis,自身都带有数据同步的机制,比较常用的MySQL的Master/Slave模式,就是由Slave端分析Master的binlog来实现的,这样的数据复制其实还是一个异步过程,只不过当服务器都在同一内网时,异步的延迟几乎可以忽略。那么理论上也可用同样方式,分析MySQL的binlog文件并将数据插入Redis。
因此这里选择了一种开发成本更加低廉的方式,借用已经比较成熟的MySQLUDF,将MySQL数据首先放入Gearman中,然后通过一个自己编写的PHPGearmanWorker,将数据同步到Redis。比分析binlog的方式增加了不少流程,但是实现成本更低,更容易操作。
Ⅶ redis源码解读:单线程的redis是如何实现高速缓存的
redis可能是最近几年最火的缓存数据库方案了,在各个高并发领域都有应用。
这篇文章,我们将从源代码的角度来分析一下,为何如此一个高性能,高应用的缓存,会是单线程的方案,当然一个方案的高性能,高并发是多方面的综合因素,其它的因素我们将在后续解读。后续分析主要以LINUX操作系统为基础,这也是redis应用最广的平台。
单线程最大的受限是什么?就是CPU,现在服务器一般已经是多CPU,而单线程只能使用到其中的一个核。
redis作为一个网络内存缓存数据库,在实现高性能时,主要有4个点。
1.网络高并发,高流量的数据处理。
一个异步,高效,且对CPU要求不高的网络模型,这个模型主要是由OS来提供的,目前在LINUX最主流使用的是EPOLL,这个网上介绍很多,主要是基于事件驱动的一个异步模型。
2.程序内部的合理构架,调用逻辑,内存管理。
redis在采用纯C实现时,整体调用逻辑很短,但在内存方面,适当的合并了一些对象和对齐,比如sds等,在底层使用了内存池,在不同情况下使用的不太一样。
但整体处理上没有NGINX的内池设计巧妙,当然二者不太一样,NGINX是基于请求释放的逻辑来设计的,因此针对请求,可以一次申请大块,分量使用,再最后统一释放。
3.数据复制的代价,不管是读取数据或是写入数据,一般都是需要有数据复制的过程。
数据复制其实就是一次内存,真正的代价是在于存在大VALUE,当value值长度超过16KB时,性能会开始下降。因为单线程的原因,如果存在一个超大VALUE,比如20MB,则会因为这个请求卡住整个线程,导致后续的请求进不来,虽然后面的请求是能快速处理的小请求。
4.redis中数据结构中算法的代价,有些结构在大数据量时,代价是很高的。
很多时间,大家忽略了算法的运算代码,因为像memcached等这类是完全的KV缓存,不存在什么算法,除了一个KEY的查找定位HASH算法。
而redis不一样,提供了不少高阶的数据对象,这些对象具有上层的一些算法能力,而这些能力是需要比如GEO模块。