Redis系列(一):各大厂都在用的Resid到底是什么?

一、redis是什么?

1.Redis的定义

先上一段官方定义:Redis 是开源免费(遵守BSD协议)、高性能的key-value数据库。

是不是觉得上面的一句话既熟悉又陌生,作者怎么想的为啥开源免费?BSD协议又是什么?key-value数据库是什么,与传统的mysql、oracle有什么区别?

别急,欲知详情,请看下面分解:

Redis是由意大利人Salvatore Sanfilippo(网名:antirez)开发的一款内存高速缓存数据库。Redis全称为:Remote Dictionary Server(远程字典服务),该软件使用C语言编写,Redis是一个key-value存储系统,它支持丰富的数据类型,如:string、list、set、zset(sorted set)、hash。众多语言都支持Redis。

那么BSD协议是什么呢?简单来说就是一个开源协议,具体请看https://www.runoob.com/note/13176

key-value数据库?就是像python中的dict类型一样的数据存储模式,传统的mysql、oracle是关系型数据库,key-value模式的数据库是非关系型的数据库(NoSQL)。

2.Redis的用途

作为公共缓存:Redis交换数据速度快,在架构中常用来存储一些需要频繁调取的数据,这样可以大大节省系统直接读取磁盘来获得数据的I/O开销,并且可以极大提升速度

以大型网站来举个例子,比如a网站首页一天有100万人访问,其中有一个板块为推荐新闻。要是直接从数据库查询,那么一天就要多消耗100万次数据库请求。上面已经说过,Redis支持丰富的数据类型,所以这完全可以用Redis来完成,将这种热点数据存到Redis(内存)中,要用的时候,直接从内存取,极大的提高了速度和节约了服务器的开销。

3.Redis的特点

1)支持数据的持久化:可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。

2)支持丰富的数据类型:不仅支持简单的key-value类型,同时还支持string、list,set,zset(sorted set),hash等数据结构的存储。

3)支持数据的备份:即master-slave模式的数据备份。

二、为什么要部署一台Redis服务器,而不是简单的给服务器添加内存条?

这个理解起来有点深,跟服务器集群、数据的队列访问、程序代码对内存的控制有关。就像一般存储数据都是用mysql、oracle等数据库,而不是使用excel一样。Redis是标准的数据存储和管理方式,只不过与关系型数据库不同的是,Redis的数据存在内存中,效率比关系型数据库高很多。但如果我们自己给服务器添加内存条,我们就要自己写数据的管理方式等,非常繁琐,有现成的为什么不直接用呢?

三、Redis的经典应用场景

场景描述
缓存热数据热数据(进入市场时经常被查询,但未被修改或删除的数据),首选使用redis缓存,redis的性能非常优越。
计数器由于具有单个线程,因此可以计算诸如单击,访问,喜欢,评论,视图等的计数,以避免并发问题,确保数据的准确性和100%毫秒的性能,同时启用Redis持久性为了促进数据的持久性。
单线程机制验证上一段中的重复请求,并可以自由扩展类似情况。可以通过redis进行过滤。例如,每个请求都使用请求IP,参数和接口的哈希值作为存储Redis的键,并设置有效期限。然后,下一次请求结束时,现在将检索redis中是否存在此密钥,然后验证它是否为“在一定时间内不是重复提交”。例如,要限制用户登录的数量,最好不要超过一天中错误登录的数量。基于redis的Spike系统是单线程功能,可防止数据库超卖,全局增量ID生成等。
排行榜得分最高的人排名第一,例如高点击率,活跃度,最高销售数量,投票数最高的前10名,等等。
分布式锁Redis可用于实现分布式锁。为了确保分布式锁可用,至少锁的实现必须同时满足以下条件:互斥在任何时候,只有一个客户端可以持有该锁。不会发生死锁。即使一个客户在锁定保持期间崩溃而没有主动解锁,也可以确保其他客户以后可以锁定。本的容错能力只能在大多数Redis节点上正常运行。然后,客户可以锁定和解锁。锁定和解锁必须是同一客户端,并且该客户端无法解锁他人添加的锁。
会话存储使用Redis进行会话缓存是很常见的情况。使用Redis在其他存储上缓存会话的优点是Redis提供了持久性。目前,很多解决方案都采用Redis作为会话存储解决方案。

四、Redis的五种数据类型

Redis 内部使用一个 RedisObject 对象来表示所有的 key 和 value。RedisObject 最主要的信息如上图所示:type 表示一个 value 对象具体是何种数据类型,encoding 是不同数据类型在 Redis 内部的存储方式。

比如:type=string 表示 value 存储的是一个普通字符串,那么 encoding 可以是 raw 或者 int。

类型简介特性场景
String(字符串)

1.Redis 最基本的类型

2.二进制安全

1. 最基本的类型:可以理解成与 Memcached一模一样的类型,一个 Key 对应一个 Value

2.二进制安全:可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M

/
Hash(字典)键值对集合,即编程语言中的Map类型适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去)存储、读取、修改用户属性
List(列表)链表(双向链表)增删改,提供了操作某一段元素的API

1.最新消息排行等功能(比如朋友圈的时间线)

2.消息队列

Set(集合)哈希表实现,元素不重复

1.添加、删除,查找的复杂度都是O(1)

2.为集合提供了求交集、并集、差集等操作

1.共同好友

2.利用唯一性,统计访问网站的所有独立ip 3.好友推荐时,根据tag求交集,大于某个阈值就可以推荐

Sorted Set(有序集合)将Set中的元素增加一个权重参数score,元素按score有序排列数据插入集合时,已经进行天然排序

1.排行榜

2.带权重的消息队列

五、Redis缓存热数据技术实现?

暂时不写

六、Redis如何保持缓存与数据库数据的一致性?

缓存数据与数据库不一致的情况大概有以下三种:

1. 数据库有数据,缓存没有数据:采用先读缓存在读数据库,且读数据库时把数据加载到缓存的策略会消除此种不一致。

2. 数据库有数据,缓存也有数据,数据不相等:无法解决,只能等下次更新数据

3. 数据库没有数据,缓存有数据:删除数据库成功但删除缓存失败了会导致这种情况的发生。

缓存读取策略:

先读缓存数据,如果读到数据则直接返回;如果读不到,就读数据库,并将数据会写到缓存,并返回。

缓存更新策略:

首先先来看下缓存的使用策略,一种常规的用法叫Cache Aside Pattern:

1)读数据:先读缓存数据,如果读到数据则直接返回;如果读不到,就读数据库,并将数据会写到缓存,并返回。

2)写数据:需要更新数据时,先更新数据库,然后把缓存里对应的数据失效掉(删掉)。

对于读数据,应该是毫无疑问肯定要先读缓存数据的,不然增加redis干嘛呢?那么思考一下,写数据的时候,如果不是先更新数据再删除缓存,而是先删除缓存再更新数据库会怎样呢?看下A、B两个线程同时要更新数据时会发生哪些情况:

1)A、B都完成了删除缓存且A、B更新数据库的中间有其他线程读取数据:假设A线程先更新数据库。此时C线程介入,C线程要读取数据,由于缓存没有则查数据库,并把A更新的数据写入了缓存,最后B线程更新数据库,以后D、E、F等线程读取数据的时候都是从缓存读取且B线程写入数据库的数据永远不会加载到缓存,由此形成了缓存与数据库数据的永久不一致,直至下次缓存数据被删除。。。

2)A、B都完成了删除缓存且A、B更新数据库的中间没有其他线程读取数据:这种情况要看A和B谁先更新了数据库,假设A线程先更新了数据,那么下次其他线程读取数据的时候便会把A线程的数据加载到缓存。这种情况无论A、B谁先更新了数据库,都不会导致缓存与数据库不一致。

另外有人会问,如果采用你提到的方法,为什么最后是把缓存的数据删掉,而不是把更新的数据写到缓存里

这么做引发的问题是,如果A,B两个线程同时做数据更新,A先更新了数据库,B后更新数据库,则此时数据库里存的是B的数据。而更新缓存的时候,是B先更新了缓存,而A后更新了缓存,则缓存里是A的数据。这样缓存和数据库的数据也不一致。

并发不高的情况:

读: 读redis->没有,读mysql->把mysql数据写回redis,有的话直接从redis中取;

写: 写mysql->成功,再写redis;

并发高的情况:

读: 读redis->没有,读mysql->把mysql数据写回redis,有的话直接从redis中取;

写:异步话,先写入redis的缓存,就直接返回;定期或特定动作将数据保存到mysql,可以做到多次更新,一次保存;

缓存删除策略:

1. 删除失败则重试:删除缓存失败的话需要进行重试,数据的一致性要求越高,重试得越快。

2. 定期全量更新:简单地说,就是定期把缓存全部清掉,然后再全量加载。

3. 给所有的缓存一个失效期:一个大杀器,任何不一致,都可以靠失效期解决,失效期越短,数据一致性越高。但是失效期越短,查数据库就会越频繁。因此失效期应该根据业务来定。

分布式环境下非常容易出现缓存和数据库间数据一致性问题,针对这一点,如果项目对缓存的要求是强一致性的,那么就不要使用缓存。只能采取合适的策略来降低缓存和数据库间数据不一致的概率,而无法保证两者间的强一致性。合适的策略包括上述的缓存更新策略:更新数据库后及时更新缓存、缓存失败时增加重试机制

 

参考文章:

搞懂这些Redis知识点,吊打面试官!

Redis 数据类型

Redis怎么保持缓存与数据库一致性?

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值