内存数据库,读写速度快,被应用于缓存。redis
数据类型丰富,支持事务、持久化、LUA脚本、LRU驱动事件、多种集群方案。算法
丰富的特性:缓存,消息,过时,自动删除数据库
hash:k-v集合,适用于存储对象。因为组合式的压缩,内存利用率更高。后端
字符串:一个键最大能存512MB缓存
列表:按照插入顺序排序。安全
异步队列:rpush为生产消息,lpop为消费消息。可是消费者下线时,生产消息会丢失。服务器
set集合:string类型的无序集合,经过哈希表实现,增删查的复杂度是O(1)。网络
zset:有序集合,且不重复。数据结构
redis通信协议RESP格式的命令文本存储。是redis客户端和服务端以前使用的一种通信协议。特色:实现简单、快速解析、可读性好。多线程
a 假如用户第一次访问数据库中的某些数据。这个过程会比较慢,由于是从硬盘上读取的。b 将该用户访问的数据存在缓存中,这样下一次再访问这些数据的时候就能够直接从缓存中获取了。操做缓存就是直接操做内存,因此速度至关快。c 若是数据库中的对应数据改变的以后,同步改变缓存中相应的数据便可!
直接操做缓存可以承受的请求是远远大于直接访问数据库的,因此咱们能够考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用通过数据库。
分布式缓存:
使用 redis 或 memcached 之类的称为分布式缓存,在多实例的状况下,各实例共用一份缓存数据,缓存具备一致性。缺点是须要保持 redis 或 memcached服务的高可用,整个程序架构上较为复杂。
1.彻底基于内存操做,绝大部分请求是纯粹的内存操做,很是快速。数据存在内存中,查找和操做的时间复杂度都是O(1)
忽略磁盘操做。
2.数据结构简单,对数据操做也简单
3.采用单线程,避免频繁的上下文切换和竞争条件,也不存在多进程或者多线程致使的切换而消耗CPU,不用去考虑各类锁的问题,不存在加锁释放锁操做,没有由于可能出现死锁而致使的性能消耗
4.采用I/O多路复用机制,非阻塞。
5.使用底层模型不一样,它们之间底层实现方式以及客户端之间的通讯的应用协议不同,redis直接本身构建了VM机制,由于通常的系统调用系统函数的话,会浪费必定的时间去移动和请求。
持久化就是将内存的数据写到磁盘中,防止宕机时内存数据丢失。
持久化策略包括RDB(redis database)快照和AOF(append-only file)日志。
RDB是每隔一段时间对redis进行一次持久化,速度快,性能好,可是数据不完整。核心函数有rdbSave为rdb文件和rdbLoad。
AOF是从新执行命令,数据完整,安全可是速度慢,文件大。主要是调用flushappendonlyfile函数。将aof_buf中的缓存写入到AOF文件,或者是调用fsync、fdatasync函数,将AOF文件保存到磁盘中。
单机版:内存容量有限,处理能力有限,没法高可用。
分布式:主从复制。保证数据相同。没法保证高可用。没有解决master写的压力。
哨兵:分布式系统中监控redis主从服务器,并在主服务器下线时自动进行故障转移。
特性:监控:不断地检查主从服务器是否运做正常。
提醒:当被监控的某个redis服务器出现问题时,哨兵能够经过API向管理员或者其余应用程序发送通知。
自动故障迁移:当一个主服务器不能正常工做时,哨兵会开始一次自动故障迁移操做。
特色:保证高可用、监控各个节点、自动故障迁移;主从模式,切换须要时间,可能丢数据,没有解决master写的压力
集群proxy:
特色:twemproxy,代理服务器,快速的,单线程。
优势:能够支持多种hash算法,失败节点会自动删除,后端sharding分片逻辑对业务透明,业务方的读写方式和操做单个redis一致。
缺点:增长新proxy时,须要维护高可用。不支持故障的自动转移。
须要本身实现failover,扩展性差。手动干预扩容和缩容。
集群codis:
和twemproxy效果一致,可是支持在节点数量改变的状况下,旧节点恢复到新hash节点。
集群直连型:无中心结构,每一个节点保存数据和整个集群状态,每一个节点都和其余节点链接。
特色:没有中心节点,没有proxy层。
节点间数据共享,能够动态调整数据分布。
可扩展,到1000个节点,节点可动态增长或者删除。
高可用,部分节点不可用时,集群仍然可使用。slave作备份数据。
实现故障自动failover,节点间经过gossip协议交换状态信息,投票机制完成slave到master的角色提高。
缺点:资源隔离性差,容易互相影响。
数据异步复制,不保证数据的一致性。
hash槽:根据CRC16(key) mod 16384,以为key-value放入哪一个桶(节点)。
Memcached相似于一致性哈希的分布式算法实现分布式存储。
一致性哈希:DHT能够经过减小影响范围的方式,解决增减服务器致使的数据散列问题,解决分布式环境下负载均衡问题。若是存在热点数据,能够经过增添节点的方
Redis中有个设置时间过时的功能,即对存储在 redis 数据库中的值能够设置一个过时时间。做为一个缓存数据库,这是很是实用的。如咱们通常项目中的 token 或者一些登陆信息,尤为是短信验证码都是有时间限制的,按照传统的数据库处理方式,通常都是本身判断过时,这样无疑会严重影响项目性能。
咱们 set key 的时候,均可以给一个 expire time,就是过时时间,经过过时时间咱们能够指定这个 key 能够存活的时间。若是假设你设置了一批 key 只能存活1个小时,那么接下来1小时后,redis是怎么对这批key进行删除的?
按期删除+惰性删除。
可是仅仅经过设置过时时间仍是有问题的。咱们想一下:若是按期删除漏掉了不少过时 key,而后你也没及时去查,也就没走惰性删除,此时会怎么样?若是大量过时key堆积在内存里,致使redis内存块耗尽了。怎么解决这个问题呢? redis 内存淘汰机制。
redis 提供 6种数据淘汰策略:
4.0版本后增长如下两种:
Redis 经过 MULTI、EXEC、WATCH 等命令来实现事务(transaction)功能。事务提供了一种将多个命令请求打包,而后一次性、按顺序地执行多个命令的机制,而且在事务执行期间,服务器不会中断事务而改去执行其余客户端的命令请求,它会将事务中的全部命令都执行完毕,而后才去处理其余客户端的命令请求。
注意:redis同一个事务中若是有一条命令执行失败,其后的命令仍然会被执行,没有回滚。
当缓存服务器重启或者大量缓存集中在一个时间段失效,失效时会对后端系统带来很大压力,严重时数据库会宕机。
避免:
1.缓存失效后,经过加锁或者队列控制读数据库、写缓存的线程数量。好比某个key只容许一个线程查询数据和写缓存,其余线程等待
2.作二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,访问A2,A1缓存失效时间短时间,A2为长期
3.不一样的key设置不一样的过时时间,让缓存失效的时间点尽可能均匀。
通常的缓存系统是按照key去缓存查询,不存在对应的value时,会去后端系统查询。而恶意的请求会故意查询不存在的key,请求量直接到数据库上,请求量很大时,会对后端系统形成很大压力,就叫缓存穿透。
正常处理流程:
解决:
1.查询结果为空的状况进行缓存过时时间,缓存时间短,最长不超过5分钟,或者key对应的数据插入后清理缓存。
2.使用布隆过滤器。对必定不存在的key进行过滤。把全部可能存在的key放在一个大的bitmap(哈希表)中,查询时经过bitmap过滤,这样避免了对底层存储系统的查询压力。
缘由:
redis并发竞争key时,多个系统同时对一个 key 进行操做,可是最后执行的顺序和咱们指望的顺序不一样,这样也就致使告终果的不一样!
先使用setnx抢锁,设置超时时间以释放锁、超过一半的redis实例设置成功,就表示加锁完成。
注意:若是不存在 Redis 的并发竞争 Key 问题,不要使用分布式锁,这样会影响性能