浅谈Redis缓存

在计算机中,缓存是一个高速数据存储层,其中存储数据的子集,且通常是短暂的存储,这样日后再次请求此数据时,速度要比访问数据的主存储位要快,通过缓存可以高效的重用之前检索或计算的数据。(就是从访问比较慢的地方放到访问比较快的地方)

为什么要用缓存

  1. 提高应用程序的性能(因为内存的数据读取比磁盘快,所以整体性能也提升了)
  2. 降低数据库成本(同样的配置,缓存比数据库的读取速度更大)
  3. 减少后端负载(可以减少与数据库之间的连接)
  4. 可预测的性能
  5. 消除数据库热点(将数据库中经常访问的数据加载到缓存中)
  6. 提高读取吞吐量
    读多写少用缓存!!!

Redis

Redis是一个开源的使用C语言编写、支持网络、可基于内存亦可持久化的的日志型、key-value数据库,并提供多种语言的API。
本质时客户端-服务端应用软件程序。
特点是简单、性能强悍、功能使用场景丰富。

通用命令

命令描述
DEL key该命令用于在key存在时删除key
DUMP key序列化给定key,并返回序列化的值
EXISTS key检查给定key是否存在
EXPIRE key seconds为指定key设置过期时间,以秒为单位
TTL key以秒为单位返回给定key的剩余生存时间 TTL (time to live)
TYPE key返回key所储存的值的类型

数据结构

String

string 数据结构是简单的key-value类型,value其实不仅是String,也可以是数字。使用场景:微博数,粉丝数(常规计数)

常用命令
命令描述
Get获取指定key的值
Set设置指定key的值
Incr将key中存储的数值加一
Decr将key中存储的数值减一
Mget获取所有(一个或多个)给定key的值
List

List就是链表,使用场景:微博的关注列表,粉丝列表

常用命令
命令描述
Lpush将一个或多个值插入到列表的头部中
Rpush在列表中添加一个或多个值
Lpop移出并获取列表的第一个元素
Rpop移出列表的最后一个元素,返回值为移除的元素
Lrange获取所有(一个或多个)给定key的值
Set

Set就是一个集合,集合的概念就是一堆不重复值的组合,利用Redis提供的Set数据结构,可以存储一些集合行的数据。使用场景:实现共同关注、共同喜好、二度好友。

常用命令
命令描述
Sadd向集合中添加一个或多个成员
Spop移除并返回集合中一个随机元素
Smebers返回集合中所有的成员
sunion返回给定集合的并集
Sorted Set

Sorted Set 的使用场景与Se,区别在于Set不是有序的,而Sorted Set 可以通过用户额外提供一个优先级(Score)的参数来为成员排序,并且是插入有序的,即自动排序。使用场景:排行榜、按照用户投票和时间排序。

常用命令
命令描述
Zadd向有序集合添加一个或多个成员,或更新已存在的成员的分数
Zrange通过索引区间返回有序集合中指定区间内的成员
Zrem移除有序集合中的一个或多个成员
Zcard获取有序集合中的成员数
Hash

Hash是一个String类型的field和value的映射表,使用场景:存储部分变更的数据,如用户信息。

常用命令
命令描述
Hget获取存储在哈希表中的指定字段
HSet将哈希表key中的字段field的值设为value
Hgetall获取在哈希表中指定key的所有字段和值
GEO

GEO 3.2版本开始对GEO(地理位置)的支持,使用场景LBS应用开发

常用命令
命令描述
GEOADD增加地理位置的坐标,可以批量增加地理位置
GEODIST获取两个地理位置之间的距离
GEOHASH获取某个地址位置的geohash值
GEOPOS获取指定位置的坐标,可以批量获取多个地理位置的坐标
GEOREDIUS根据地理位置的坐标获取指定范围内的地理位置集合(注意:改命令的中心点由输入和维度决定)
GEOREDIUSBYMEMBER根据给定成员的位置获取指定范围内的位置信息集合(注意:改命令的中心点由输入和维度决定)
Stream

Stream 5.0版本开始的新的结构"流",使用场景:消费者生产者场景(类似MQ)

常用命令
命令描述
XADD往指定的流中添加消息
XLENstream流中的消息数量
XDEL删除流中的消息
XRANGE返回流中满足给定id范围的消息
XREAD从一个或多个流中读取消息
XINFO检索关于流和关联的消费者组的不同的信息

Redis的可以做什么

  1. 缓存:通过把数据放入到缓存中提高查询的效率降低数据库的IO
  2. 计数器:通过DECR和INCRBY执行增加或减少计数器的值。
  3. 消息队列:通过LIST,或着Stream可以实现简单的消息队列,Stream是5.0过后更新的其本质是在redis上实现一个消息发布和订阅的组件。
  4. 好友关系:通过Store Set 取用户的交集,并集,差集,这样方便查询用户之间的好友关系
  5. 排行榜:通过查找Store Set 起始位置和结束位置,从而实现排行榜。
  6. session共享:session是存储在服务器中的,在集群的情况下用户登录后可能会分发到不同的机器,这样在另一台机器上没有用户相关session,导致用户可能重复登录的问题。通过把session保存在redis中这样无论用户被分到那一台机器上都可以获取到相关session。
  7. 分布式锁:使用setnx可以实现redis分布式锁。

缓存一致性

一般我们查询缓存的步骤是:
1.先检查缓存中是否有数据 。
2.没有数据则查询数据库中数据。
3. 把数据库中的查询结果放到缓存中。
但是随着时间的推移和用户的操作可能会导致数据不一致。所以一般有一下几种方案来保证数据的一致性。

先更新数据库再更新缓存

这种方案是先更新数据库,数据库更新成功后再进行更新缓存操作,但是该方案会出现一个ABA的问题,也就是当前有A、B两个用户同时修改数据库中的一条数据,在数据库操作时,先执行A的操作把数据的值改成了1,后执行B操作把数据改成了2,但是当更新缓存的时候,B线程的执行较快先把数据改成了2,后再执行A线程的操作又把数据改成了1。所以就导致缓存中数据和数据库中的数据不一致。(不推荐)

先更新缓存再更新数据库

当出现同上一种方案先后执行的问题时,最终也会导致数据不一致。(不推荐)

先删除缓存再更新数据库

先删除缓存再更新数据库根据上面图片我们可以看出,当两个线程同时执行时,用户A过来先删除缓存中的数据,紧接着B用户又来做查询操作,当缓存中没有数据从数据库中读取后放入缓存,当A用户执行完数据库操作时数据库中的数据又和缓存不一致了。(不推荐)

先更新数据库再删除缓存

先更新数据库再删除缓存
如上图所示这种方案可以有效避免数据库和缓存不一致的问题。(推荐)

通过订阅binlog来更新redis

该种方案是mysql开启binlog,然后通过canal解析binlog。canal是阿里巴巴的一个组件,canal可以解析到binlog的日志,当mysql日志变化的时候会将数据发送到canal服务中,canal将数据存放到redis中。这种方案网上有很多操作示例,等有时间写一篇具体的文档。

缓存击穿

查询必然不存在的数据,请求透过Redis直击数据库。这样当查询量大的时候,会导致数据库的压力很大,甚至导致奔溃。
解决思路:在查询之前先判断目标数据是否存在,不存在直接忽略。将流量拦截于缓存和数据库之前。

布隆过滤器

布隆过滤器他实际上是一个很长的二进制数组和一系列hash函数,它可以用于检索一个元素是否在一个集合中,它的优点是空间效率和查询时间都比一般算法要好的多,缺点是有一定的识别率和删除困难。
实现思路:
构建一个二进制数组,将元素hash取模,塞到对应的位置中。查找时根据计算hash并计算出对应的位置。利用redis的特性和命令:bitmaps(setbit设置值,getbit获取值),可以redis中的bit数组长度是2的32次方,所以通过hash值对数组长度进行取模然后找到对应的位置,再用redis中的setbit插入对应位置值的状态,getbit获取获取是否有值。

二进制数据构建过程:

  1. 加载符合条件的记录
  2. 计算每条元素的hash值
  3. 将hash值与二进制数组的长度取模(余数),得到映射位置
  4. 将对应的位置值改成1

查找元素是否存在的过程

  1. 计算元素的hash值
  2. 将hash值与二进制数组的长度取模(余数),得到对应的二进制数组的位置
  3. 找到数组的对应值,0表示不存在,1表示存在

优点:
内存占用空间小(可存40多亿,但是占用空间只有512M)。
缺点:

  1. 需要不断的维护
  2. 并不能精准过滤(判定不存在则100%不存在,但是判定为存在则可能不存在)

理论上Hash计算值是有碰撞(不同的hash可以计算出同样的值),导致不存在的元素可能会被判断为存在,但是布隆过滤器并非是为了拦截所有的请求,是为了将缓存击穿控制在一定的量。

Redis集群

//TODO

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值