网站建设免费网站,做网站上凡科,商业门户网站怎么运营,浙江网站关注wx#xff1a;CodingTechWork
Redis介绍
概述
Redis是NoSQL#xff0c;是key-value分布式内存数据库。
缓存
缓存是将数据从慢的介质换到快的介质上#xff0c;提高读写效率和性能#xff0c;并降低数据库的读写成本。内存的速度一般都远远大于硬盘的速度#xf…
关注wxCodingTechWork
Redis介绍
概述
Redis是NoSQL是key-value分布式内存数据库。
缓存
缓存是将数据从慢的介质换到快的介质上提高读写效率和性能并降低数据库的读写成本。内存的速度一般都远远大于硬盘的速度大量请求数据库或远程应用时会导致大量的时间消耗在调用上从而降低系统应用调用效率若使用缓存则可以充分利用资源提高系统调用效率。
特点
Redis支持数据的持久化Redis运行在内存中但可以持久化到磁盘。将内存中的数据保存到磁盘中重启时可以再次加载进行使用。Redis提供多种数据结构类型存储如list、set、zset、hash。Redis支持数据的备份即主从master-slave模式的数据备份。Redis支持发布-订阅通知key过期等特性。Redis性能高读的速度是11万次/s写的速度是8万次/s。Redis支持原子性即要么全部执行成功要么全部不执行。单个操作是原子的多个操作也支持原子性事务通过MULTI和EXEC指令包装。
热点数据和冷点数据
热数据
需要被计算节点频繁访问的在线类数据如某导航信息缓存后会被读取很多次新建的通告信息缓存后也会被读取很多次。
冷数据
对于理想类不经常访问的数据如企业备份数据、业务与操作日志数据、话单与统计数据。大部分数据可能还未再次访问就已被挤出内存不仅占用内存且价值不大。
Memcached和Redis区别
存储方式Memcached存储在内存中断电挂掉丢失数据不能超过内存大小redis有部分存在硬盘上也可以持久化数据到数据库中。数据支持类型Memcached所有的值均为简单的字符串只是keyt-value类型数据redis可提供list、set、zset、hash等数据结构存储。底层实现方式redis直接构建自己的虚拟机机制value值大小Memcached1MBredis最大达1GB速度redis速度快于Memcached因为redis内存操作、单线程操作、采用非阻塞I/O多路复用机制灾难恢复Memcached挂掉后数据不可恢复redis数据丢失后可通过AOF恢复。备份redis支持数据备份即master-slave模式的数据备份。
Redis缓存问题
缓存雪崩
介绍
原有缓存失效新缓存未到期。缓存中采用相同过期时间同一时刻出现大面积缓存过期原本访问Redis缓存的请求都直接去查询数据库对数据库cpu和内存造成巨大压力严重时造成数据库宕机从而形成一系列连锁反应造成整个系统崩溃。与缓存击穿区别是雪崩是很多key采用相同过期时间同时多个key失效。击穿是某一个key缓存失效。
解决方案
考虑加锁、或者队列的方式保证不会有大量的线程对数据库一次性读写避免失效时大量的并发请求落到底层存储系统上。缓存失效时间随机化给每个key的失效时间加个随机值保证数据不会在同一时间大面积失效。设置热点数据永不过期有更新操作直接更新缓存。如系统首页有新产品展示直接刷缓存无需设置过期时间。
缓存穿透
介绍
查询一个不存在的数据缓存和数据库中都没有数据用户不断发起请求在缓存中找不到每次去数据库中再查一遍两次无用查询然后返回空。缓存穿透一般出现在攻击场景下攻击者知道请求路径的规则后传递一些不存在的id进行查询数据。
解决方案
采用布隆过滤器bloom-filter将所有可能存在的数据哈希到一个足够大的bitmap中不存在的数据会被这个bitmap过滤拦截掉避免对底层存储系统查询压力。布隆过滤器用于检索一个元素是否在一个集合中使用redisson可实现。底层是主要是初始化一个比较大数据里面存放二进制0或1一开始都是0当一个key进来后经历3次hash计算模于数组长度找到数据的下标然后把数组中原来的0改为1三个若一个查询返回数据为空仍然将空结果进行缓存过期时间可以设置很短如30s不超过5min通过直接设置默认值放入Redis缓存第二次查询缓存就可以获取值不会继续访问数据库。代码层面的接口层增加校验如用户鉴权校验、参数校验等不合法参数直接返回异常。
缓存击穿
介绍
对于一个key非常热点不停的去访问这个key承受高并发当key失效瞬间持续的高并发瞬间击穿缓存直接请求数据库。对于设置了过期时间的key缓存在某个时间点过期的时候恰好这个时间点对这个key有大量的并发请求进来发现缓存过期直接从后端DB加载数据并回设到缓存压垮DB。
解决方案
设置热点数据永远不过期。加互斥锁缓存失效是不立即去load db先使用如redis的setnx去设置一个互斥锁当操作成功返回时在进行load db的操作并回设缓存否则重试get缓存方法。分布式锁可以保证数据强一致性但是性能不高。逻辑过期在设置key的时候设置一个过期时间字段一块存入缓存中不给当前key设置过期时间当查询的时候从redis取出数据后判断时间是否过期瑞过期则开通另外一个线程进行数据同步当前线程正常返回数据这个数据是旧的服务降级而已适用于to c无需保证数据强一致性时可以用。
解决思路
事前Redis 高可用主从哨兵Redis cluster避免全盘崩溃。事中本地 ehcache 缓存 Hystrix 限流降级避免MySQL 被打死。事后Redis 持久化 RDBAOF一旦重启自动从磁盘上加载数据快速恢复缓存数据。
双写一致性
方法一使用redisson实现的读写锁在读的时候添加共享锁保证读读不互斥读写互斥。当更新数据时添加排他锁读写、读读都互斥保证在写数据的同时不会有其他线程读写数据避免脏数据。底层使用setnx保证同时只有一个线程操作锁住的方法。方法二延时双删若是写操作先删除缓存数据然后更新数据库最后再延时删除缓存中的数据但这个延时玄学也可能出现脏数据并不能保证强一致性。方法三采用阿里的canal组件实现数据同步。部署一个canal服务伪装成mysql的一个从节点当mysql数据更新后canal读取binlog数据然后通过canal的客户端获取到数据更新缓存。
Redis数据类型
概述
String类型value可以是String也可以是数字做一些复杂的计数功能缓存。hash类型value存放结构化对象如单点登录时存储用户信息以cookieId作为key设置30min为缓存时间。list类型可做简单的消息队列。set类型可做全局去重功能。sorted set类型可按照score进行排序可做排行榜应用。
字符串string
介绍
redis的字符串是动态字符串可修改。采用预分配冗余空间来减少内存的频繁分配内部为当前字符串分配的实际空间大小一般要高于实际字符串长度。当字符串长度小于1MB时扩容都是加倍。字符串最大长度为512MB。
常用命令
get、set、incr、decr、mget
应用场景
计数器控制接口调用次数如通过incrby命令进行递增。共享session分布式服务会将用户信息访问负载均衡到不同的节点上。限速如短信获取验证码功能为了短信服务不会被频繁访问限制用户每分钟获取验证码的频率、当天最大获取短信的次数。
散列hash
介绍
hash是一个键值对集合适合存储对象。hash内部是无序字典内部存储多个键值对采用渐进式的rehash策略在rehash时保留新旧两个hash结构查询会同时查询新旧hash结构渐进将旧hash内容迁移到新hash中。最终旧hash被自动删除内存被回收。
常用命令
hget、hset、hmget、hmset、hgetall
应用场景
存储对象value存储为HashMap
集合set
介绍
set是string类型的无序集合通过散列表实现。set内部相当于一个特殊字典所有value都一个NULL值。当集合中最后一个元素被移除后数据结构自动删除内存被回收。
常用命令
sadd、srem、spop、sdiff、smemners、sunion
应用场景
去重数据功能如用户访问列表查询。
有序集合zset
介绍
zset类似set区别是每个元素都会关联一个double类型的分数通过分数来为集合的成员进行从小到大的排序。zset中的成员是唯一的但分数可以重复。zset内部是使用“跳跃列表”的数据结构实现的。zset集合中最后一个元素被移除后数据结构自动删除内存被回收。
常用命令
zadd、zrange、zrem、zcard
应用场景
去重并自动排序的数据。
列表list
介绍
list是简单的字符串列表按照插入顺序排序可增加一个元素到列表的头部或尾部。list的插入和删除速度快索引定位慢。list中的每个元素之间都是使用双向指针顺序连接同时支持前后遍历。当最后一个元素被弹出后数据结构自动删除内存被回收。
常用命令
lpush、rpush、lpop、rpop、lrange、blpop
应用场景
消息队列如最新通知排名利用list的push操作将任务存list中再通过工作线程用pop操作将任务取出执行。
Redis原理
Redis单线程
为何Redis是单线程
Redis是基于内存操作CPU不是瓶颈最大的瓶颈可能是机器内存的大小或者网络带宽采用队列技术将并发访问变成串行访问。绝大部分请求是纯粹的内存操作采用单线程避免不必要的上下文切换和竞争条件。非阻塞I/O速度快支持丰富数据类型如String、list、set、sorted set、hash。 支持事务操作都是原子性具有丰富的特性如可用于缓存、消息队列、按key设置过期时间。
原子性
因为redis是单线程的一个操作不可再分要么都执行要么都不执行。多个命令在并发中不一定是原子的如get set操作。使用redis事务或者redislua可以实现。
Redis过期策略
为何不采用定时删除
用定时器负责监视key过期则删除虽然可以及时释放内存但消耗cpu资源在大并发情况下cpu要将时间应用于处理各种请求而不是删除key。
redis采用定期删除惰性删除策略。
定期删除默认每隔100ms检查是否有过期的key有则删除但不是所有key都检查一次而是随机抽取进行检查这种会造成很多key到时间未删除。惰性删除获取某个key会检查是否设置过期时间过期则删除这样就可以比避免定期删除时遗留的未删除的key。
问题
问题若定期删除没有删除到key且没有及时请求该key导致惰性删除未生效导致redis内存越来越高。。解决方案采用内存淘汰机制在redis.conf中配置maxmemory-policy volatile-lru即从已设置过期时间的数据集中挑选出最近最少使用的数据进行淘汰。
分类
惰性删除
在设置该key过期时间后不去管它当需要该key时会检查是否过期若过期直接删除否则返回该key。定期删除会导致很多过期key到了时间并没有被删除掉所以需要惰性删除主动检查过期的key发现key过期立即删除不会返回任何东西。惰性删除属于零散处理。
定期删除
定期删除就是每隔一段时间对一些key进行检查删除里面过期的key。redis会将每个设置了国企时间的key都放入一个独立的字典中后续会定期遍历这个字典来删除到期的key默认是每秒进行十次过期扫描所以是100ms/次扫描。定期删除是采用简单的贪心策略避免全部key扫描对CPU带来负载从过期字典中随机扫描20个key删除这20个key中已经过期的key若过期的key比率超过1/4就继续随机扫描。定期删除属于集中处理。模式分类 1SLOW模式定时任务执行频率默认为10hz每次不超过25ms通过修改配置文件redis.conf的hz选项来调整次数。 2FAST模式执行频率不固定每次事件循环会尝试执行但两次间隔不低于2ms每次耗时不超过1ms。
Redis事务
介绍
Redis事务功能通过MULTI、EXEC、DISCARD、WATCH四个原语实现。redis会将一个事务中所有命令序列化然后按顺序执行。redis不能在一个事务执行过程中插入零一二客户端发出的请求。redis不支持回滚redis在事务失败时会继续执行剩余命令内部可以保持简单且快速。如果在一个事务中命令出现错误则所有命令都不会执行。如果一个事务中出现运行错误则正确的命令会被继续执行。
四个原语
MULTI
MULTI命令用于标记事务块的开始将后续命令逐个放入队列中然后才能使用EXEC命令原子化执行该命令序列。返回值是一个简单的字符串总是OK。
EXEC
在一个事务中执行所有先前放入队列的命令然后恢复正常的连接状态。使用WATCH命令时只有当受监控的键未被修改时才能使用EXEC命令执行事务块命令采用CAS检查再设置的机制。返回值是衣蛾数组每个元素分别是原子化事务中每个命令的返回值。当使用WATCH命令时若事务执行中止则返回一个Null值。
DISCARD
清除所有先前在一个事务块中放入队列的命令然后恢复正常的连接状态。返回值是一个简单的字符串总是OK。
WATCH
当某个事务需要按条件执行时就需要使用WATCH命令将给定的键设置为受监控。返回值是一个简单的字符串总是OK。为redis事务踢动CAS(check-and-set)行为可以监控一个或多个键一旦有一个键被修改或删除之后的事务不会执行监控一直持续到EXEC命令执行时。
Redis事件
基于事件
核心原理是基于事件的处理流程。
主程序处于一个阻塞状态的事件循环event loop中等待事件当有事件发生时根据事件的属性分发到相对应的处理函数中进行处理。事件是以并发的方式发送到服务处理器服务处理器将事件整合到一个有序队列中并发到具体的请求处理器进行处理。Redis程序都是围绕事件循环进行的。事件循环同时监控多个事件Redis对于连接套接字的抽象当套接字变为可读或者可写状态则会触发该事件把就绪的事件放在一个待处理事件的队列中以有序、同步的方式发送给事件处理器进行处理。Fire过程Redis事件循环会保存两个表events和fired列表前者存储正在监听的事件后者存储就绪的事件。Redis处理所有命令都是顺序执行的包括客户端的连接请求、内部定时执行的任务等。所以当Redis处理一个复杂度高、时间很长的请求如keys命令、自动删除一个过期的大key则其他客户端连接有可能被阻塞。所以一般不使用大key否则可能会造成业务卡顿。
Redis事件处理流程
加载配置配置参数初始化创建事件循环循环事件注册一个可读事件用于处理响应客户端请求执行事件循环等待连接和命令请求注册事件被eventLoop监听读写操作需要执行的就绪事件
Redis持久化
RDB
RDB是一个快照文件是把redis内存存储的数据写到磁盘上当redis实例宕机恢复数据的时候方便从RDB的快照文件中恢复数据。RDB是二进制文件保存的时候体积比较小恢复快但可能会丢失数据。
AOF
AOF是追加文件当redis操作写命令的时候都会存储这个文件中当redis实例宕机恢复数据的时候会从这个文件中再执行一遍命令恢复数据。通常在项目中使用AOF恢复数据速度虽然慢但丢数据的风险小AOF文件可设置刷盘策略如每秒批量写入一次命令。
Redis数据淘汰策略
概述
谈淘汰策略之前我们知道redis有过期删除根据TTL时间进行定期采样删除或惰性删除有过期策略为何还要淘汰策略因为过期策略不能够完全精准的全部删除数据会存在key没有被删除的场景所以需要内存淘汰策略进行兜底。
内存淘汰策略
noeviction当内存使用超过配置的时候会返回错误不会驱逐任何键allkeys-lru加入键的时候如果过限首先通过LRU算法驱逐最久没有使用的键volatile-lru加入键的时候如果过限首先从设置了过期时间的键集合中驱逐最久没有使用的键allkeys-random加入键的时候如果过限从所有key随机删除volatile-random加入键的时候如果过限从过期键的集合中随机驱逐volatile-ttl从配置了过期时间的键中驱逐马上就要过期的键volatile-lfu从所有配置了过期时间的键中驱逐使用频率最少的键allkeys-lfu从所有键中驱逐使用频率最少的键