应用服务器的压力:CPU和内存压力,解决方式:加服务器集群
数据库的压力:IO压力,解决方式:加缓存,分区/分表/分库/读写分离
- redis的作用:
服务器端的问题:解决多个服务器之间的共享信息问题,有效避免共享数据存在多个服务器造成的数据冗余,例如:分布式下的session共享
数据库端的问题:有效避免过多的访问数据库,减低IO读的操作,提升响应数据
避免mybatis的弊端:一个mapper一张表,比如A/B两张表关联,A表insert后,mybatis会更新A表的缓存,但是B表的不会,就会造成关联查询时数据不一致的情况
- redis优缺点:
需要牺牲一定的业务逻辑,没用存储在数据表中简单易懂,不遵循sql标准,不支持ACID
是一种典型的非关系型数据库Nosql,以简单的key-value模式存储,value是json增加了数据结构的灵活性
redis的适用场景:
对高并发的读写,海量数据的读写,对数据高可扩展性
需要支持事物的场景,需要各种关联查询,需要即席查询(如数据报表),海量数据的没法做即席查询,拉数据需要大数据来弄
- redis和memcached的区别:
Redis常被拿来和高性能键值缓存服务器Memcached进行对比,性能相差无几。
Redis不仅仅支持简单的K/V类型的数据,同时还提供List,Set,Hash等数据结构的存储,而Memcached只能存储普通的字符串键。
Memcached用户只能通过APPEND的方式将数据添加到已有的字符串的末尾,并将这个字符串当做列表来使用。但是在删除这些元素的时候,Memcached采用的是通过黑名单的方式来隐藏列表里的元素,从而避免了对元素的读取、更新、删除等操作。相反的Redis的List和Set允许用户直接添加和删除元素。
Redis和Memcached都是将数据存放在内存中,都是内存数据库。不过Memcached还可用于缓存其他东西,例如图片、视频等等;
虚拟内存–Redis当物理内存用完时,可以将一些很久没用到的Value 交换到磁盘;
分布式–设定Memcached集群,利用magent做一主多从;Redis可以做一主多从。都可以一主一从;
存储数据安全–Memcached挂掉后,数据没了;Redis可以定期保存到磁盘(持久化);
灾难恢复–Memcached挂掉后,数据不可恢复; Redis数据丢失后可以通过AOF恢复;
Redis支持数据的备份,即Master-Slave模式的数据备份;
应用场景不一样:Redis出来作为NoSQL数据库使用外,还能用做消息队列、数据堆栈和数据缓存等;Memcached适合于缓存SQL语句、数据集、用户临时性数据、延迟查询数据和Session等
- 使用Spring Data Redis操作Redis(集群版)
1、引入jar包
2、配置spring-data-redis的配置文件
①注入RedisClusterConfiguration,配置JedisPoolConfig的连接信息
②配置JedisConnectionFactory
③配置RedisTemplate
3、写RedisManage工具类整和到java代码
- redis的缺点
①缓存和数据库写一致性问题
②缓存雪崩问题
③缓存击穿问题
④缓存的并发竞争问题
- redis为什么读取快
官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。这个数据不比采用单进程多线程的同样基于内存的 KV 数据库 Memcached 差
①完全基于内存的,绝大多数都是纯粹的内存操作,数据存在内存中
②数据结构简单
③采用单线程,避免了不必要的上下文切换和竞争条件,不存在多线程或者多进程导致的切换而消耗CPU,不用考虑各种锁的问题导致的性能消耗
④使用多了I/O复用模型,非阻塞IO
- 为什么采用单线程
假设,有任务A和B,有如下两种执行方式
方式一:两个线程,一个线程执行A,另一个线程执行B
方式二:一个线程,先执行A,执行完以后继续习性B
以上方式其实是方式二更快一些:
因为方式一中,CPU在切换线程的时候,有一个上下文切换时间,而这个上下文切换时间是非常耗时的,而一次上下文切换,将近需要耗时0.002ms!而这个时间内,CPU什么都干不了,只是做了保存上下文都动作!
一般只用在I/O操作的时候采用多线程,例如磁盘I/O,网络I/O,一般IO操作分为两个阶段:等待I/O资源,操作I/O资源,在等待I/O的时间内,线程是在阻塞的,CPU就空闲了,如果存在其他线程就可以在这段时间内利用CPU去做其他事情,所以IO操作使用多线程更快
然而redis是内存数据库,不涉及IO,所以用单线程更好
- redis的事物
redis不支持普通意义上的事物
①事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打
②没有隔离级别的概念
③不保证原子性, Redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚
- redis的组队命令Multi/Exec/discard
从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,至到输入Exec后,Redis会将之前的命令队列中的命令依次执行,组队过程中可以通过discard来放弃组队
组队中某个命令出现了报告错误,执行时整个的所有队列会都会被取消。
如果执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚
- redis乐观锁
悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁
乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制(svn.git)。乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的。(先执行的可以成功,后执行的不行,必须先更新)
- redis持久化
Redis提供了2个不同形式的持久化方案
①RDB (Redis DataBase):间歇性备份
Redis会单独创建(fork)一个子进程来进行持久化(子进程和主进程都是单线程的),会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件,备份过程中不影响主进程的读写。 属于全盘备份,造成压力比较大,需要有间隔性的去做,2次间隔期间的数据可能丢失,一般用于对完整性不敏感的数据备份
②AOF (Append Of File):全盘备份命令
以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,Redis启动之初会读取该文件重新构建数据,换言之,Redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
③Rewrite:
AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集(指令合并).可以使用命令bgrewriteaof
重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件
④AOF的优缺点:
备份机制更稳健,丢失数据概率更低
可读的日志文本,通过操作AOF稳健,可以处理误操作
比起RDB占用更多的磁盘空间
恢复备份速度要慢
每次读写都同步的话,有一定的性能压力
存在个别Bug,造成恢复不能
- redis主从复制
主从复制,就是主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主,从内存到内存速度很快
存在的问题:
每一台机器上都保存一份完整数据,数据过大内存不够怎么办,除了物理扩容很难办,集群来实现水平扩容
所有读操作都会压在一台机器上, 压力太大
这时可以引入集群,分摊数据存储的方式
用处:读写分离,容灾快速恢复
原理:
建立主从关系时 从机会自动复制主机上所有的数据,包括建立主从关系前的,从机只能读不能写即读写分离
每次从机联机后,都会给主机发送sync指令,即同步信号
主机立刻进行存盘操作,发送RDB文件给从机
从机收到RDB文件后,进行全盘加载
之后每次主机的写操作,都会立刻发送给从机,从机执行相同的命令
主机宕机无法重新上机问题:
手动修改:用slaveof no one 将从机变为主机,其他地方不需要修改
增加哨兵模式:有了哨兵主机宕机后从机会自动变成主机,如果主机在重新上线就会自动转为从机
- redis集群
Redis 集群实现了对Redis的水平扩容(解决了把所有数据放到一个机器上出现的内存不足问题),即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数据的1/N,即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求
redis-cluster 集群 为无中中心化集群,不用关心访问的是集群中的谁,数据会分摊到集群中各台机器上,各台机器彼此连接,访问时可以随机访问任意一条机器都能找到你想要的数据