redis是一个nosql数据库,是一个key-value存储系统,支持五中存储类型,String,list,hash,hset,set。
为什么会用nosql数据库呢?
当数据量的大小过大,数据索引一个机器放不下,访问量(读写)放不下的时候
那么就要说说数据访问的各个进程了,单机时代我们存储只有一台机器装数据库,如果每次都存储上万条,十万条或者更多,这样就导致数据库的性能很差,,存储已经读取速度很慢,然后就演变成缓存+mysql+垂直拆扥的方式
Cache作为中间缓存时代,所有的数据先保存到缓存中,在存入mysql,减少数据库压力,提高效率,数据
主从分离时代,redis的高速缓存,mysql的中从复制,读写分离的基础上,mysql主库的写压力开始出现瓶颈,而数据量的持续猛增,儿mysql使用的是myisam使用表级锁,遇到瓶颈,高并发的情况下会遇到锁问题,这个时候就用到(innoDB行级锁)
nosql数据库的优势:
- 易扩展(不需固定的模式,无需多余的操作就可以进行横向的扩展),
- 大数据量提高性能,
- 多样灵活的数据模型
Redis 是一个使用 C 语言写成的,开源的 key-value 数据库。。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。目前,Vmware在资助着redis项目的开发和维护
那么为什么选择redis?
1:性能
我们在遇到数据持久化操作的时候耗时比较长,且数据结果不频繁的变动的情况下,特别适合将数据放到缓存中,后面的请求可以去缓存中读取,快速的响应,这个响应速度不固定,理想状态下
2:并发
在大并发的情况下,所以的请求都直接访问数据库,数据库会出现异常,那么这时候就需要redis做个缓冲操作,让请求先访问redis,而不是访问数据库
Redis的缺点
1:缓存和数据库双写一致性问题
2:缓存雪崩问题(即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常。)
3:缓存击穿
4:缓存穿透(请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。)
单线程的redis为什么这么快?
1:纯内存操作,
2:单线程操作,避免了频繁的上下文切换,
3:采用了非阻塞I/O多路复用机制
题外话:我们现在要仔细的说一说I/O多路复用机制,因为这个说法实在是太通俗了,通俗到一般人都不懂是什么意思。博主打一个比方:小曲在S城开了一家快递店,负责同城快送服务。小曲因为资金限制,雇佣了一批快递员,然后小曲发现资金不够了,只够买一辆车送快递
经营方式一
客户每送来一份快递,小曲就让一个快递员盯着,然后快递员开车去送快递。慢慢的小曲就发现了这种经营方式存在下述问题
• 几十个快递员基本上时间都花在了抢车上了,大部分快递员都处在闲置状态,谁抢到了车,谁就能去送快递
• 随着快递的增多,快递员也越来越多,小曲发现快递店里越来越挤,没办法雇佣新的快递员了
• 快递员之间的协调很花时间
综合上述缺点,小曲痛定思痛,提出了下面的经营方式
经营方式二
小曲只雇佣一个快递员。然后呢,客户送来的快递,小曲按送达地点标注好,然后依次放在一个地方。最后,那个快递员依次的去取快递,一次拿一个,然后开着车去送快递,送好了就回来拿下一个快递。
对比
上述两种经营方式对比,是不是明显觉得第二种,效率更高,更好呢。在上述比喻中:
• 每个快递员---------->每个线程
• 每个快递------------>每个socket(I/O流)
• 快递的送达地点------>socket的不同状态
• 客户送快递请求------>来自客户端的请求
• 小曲的经营方式------>服务端运行的代码
• 一辆车--------------->CPU的核数
• 于是我们有如下结论
1、经营方式一就是传统的并发模型,每个I/O流(快递)都有一个新的线程(快递员)管理。
2、经营方式二就是I/O多路复用。只有单个线程(一个快递员),通过跟踪每个I/O流的状态(每个快递的送达地点),来管理多个I/O流。
• 下面类比到真实的redis线程模型,如图所示
参照上图,简单来说,就是。我们的redis-client在操作的时候,会产生具有不同事件类型的socket。在服务端,有一段I/0多路复用程序,将其置入队列之中。然后,文件事件分派器,依次去队列中取,转发到不同的事件处理器中。
•
需要说明的是,这个I/O多路复用机制,redis还提供了select、epoll、evport、kqueue等多路复用函数库,大家可以自行去了解
•
redis的数据类型,以及每种数据类型的使用场景
五种数据类型:
1:String
String数据结构是简单的key-value类型,value其实不仅可以是String,也可以是数字。
常规key-value缓存应用;
常规计数:微博数,粉丝数等。
2:list
使用List的数据结构,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好list就是链表,Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如微博的关注列表,粉丝列表,最新消息排行等功能都可以用Redis的list结构来实现。
3:hash
Hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。 比如我们可以Hash数据结构来存储用户信息,商品信息等等。做单点登录的时候,就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果
4:set
因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的。
当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。
在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis可以非常方便的实现如共同关注、共同喜好、二度好友等功能
5:sorted set
sorted set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。sorted set可以用来做延时任务。最后一个应用就是可以做范围查找。
MySQL里有2000w数据,Redis中只存20w的数据,如何保证Redis中的数据都是热点数据(redis有哪些数据淘汰策略???)
相关知识:redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略(回收策略)。redis 提供 6种数据淘汰策略:
- volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
- volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
- volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
- allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
- allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
- no-enviction(驱逐):禁止驱逐数据
Redis常见性能问题和解决方案:
1:Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件:
2:如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次
3:为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内:
4:尽量避免在压力很大的主库上增加从库