啰里吧嗦redis

1.redis是什么
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker.
It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes with radius queries and streams.
Redis has built-in replication, Lua scripting, LRU eviction, transactions and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster
Redis是一个开源(BSD许可),内存数据结构存储,用做数据库,缓存和消息代理
它支持的数据结构有字符串、哈希表散列(键值对)、列表、集合、可随机查询的有序集合、bitmaps位图、hyperloglogs
基数统计、用于半径查询的地理位置索引
Redis已经内置功能有主从复制,LUA脚本,最近最少使用算法失效,事物、各类级别硬盘持久化,Redis哨兵保证可用性、Redis集群自动分片.....
 
简单来讲咱们把redis看成一个高性能的key-value数据库来使用
 
2.redis的下载安装配置
  • linux的直接去官网下载就好了,下面都有介绍,经过make命令进行安装,看不懂英语的百度下如何使用chrome自带的翻译插件
windows的比较麻烦,还得去github上下载,访问比较卡的能够参考我以前的一篇文章,直接设置hosts, 跳过DNS解析的过程
  • 下载完毕后解压,随便找个redis版本,好比redis-windows-master\redis-windows-master\downloads\redis64-3.0.501.zip解压后放到本身合适的目录下, 例E:\redis64-3.0.501
  • 在解压目录下,按住shift , 鼠标右击, 选中在此处打开命令窗口, 输入命令
redis-server.exe redis.windows.conf
若是不想每次都手写命令,能够写个脚本
目录结构
E:\redis\redis64-3.0.501-6379
在此目录下 新建一个txt 

@echo off
redis-server.exe redis.windows.conf
@pause

重命名为startRedisServer.bat
bat结尾的是windows可识别的批处理程序  能够直接执行命令窗口的命令
@echo off DOS批处理中的,
不想显示器显示 dos批处理中 的 每条命令 ,  加 echo off 
“echo off”也是命令,它自己也会显示,若是连这条也不显示,就在前面加个“@”。

@自己就是一条指令,意思是跟在它后面的指令的执行及结果都不会在DOS界面上显示出来

pause暂停命令
运行该命令时,将显示消息:请按任意键继续 . . .,通常用于看清楚屏幕上显示的内容

而后新建一个txt,在E:\redis目录下
@echo off
cd redis64-3.0.501-6379
startRedisServer.bat

重命名为start6379.cmd


cmd开启客户端
@echo off
cd redis64-3.0.501-6379
redis-cli
@pause

 

 
 
添加描述
出现此画面表明redis运行成功了,在此目录下接着打开一个命令行
输入以下命令 >redis-cli > set age 32 ok > get age "32"
注1:若是不想每次都进入目录下执行命令,可参考前面的zookeeper,在 系统path下配置环境变量,
这样就能在任意目录下经过redis-cli访问redis了(猜想window系统会根据命令行的命令先去 --系统path路径下找--可执行的文件)
注2:若是不想关闭cmd窗口就终止redis服务,可把redis设置成windows下的服务
设置服务命令

redis-server --service-install redis.windows-service.conf --loglevel verbose


卸载服务:redis-server --service-uninstall

开启服务:redis-server --service-start

中止服务:redis-server --service-stop

 

经过右击计算机---计算机管理--服务和应用程序--服务可查看多出了一个redis服务
注3:E:\redis64-3.0.501\redis.windows-service.conf
Redis安装的服务默认加载的是该文件,自定义配置信息
 
附:redis解压包和 可视化界面客户端
redis客户端工具你们找找吧,超过10M我就不上传了
 
添加描述
 
 
3.redis实战,spring和redis的结合
项目中如何使用redis呢,思路3部曲,先导包,再配置,最后测试
我自建的项目都是maven方式管理jar包
首先在pom.xml文件添加依赖,由于我用的spring框架,因此导了一个spring-data-redis,jackson包是为了能保持对象


<dependencies>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.7.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>1.6.2.RELEASE</version>
        </dependency>
        
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.1.0</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.1.0</version>
        </dependency>

</dependencies>

 

在src/main/resources目录下新建一个redis.properties文件里面配置redis的信息
#访问地址
redis.host=127.0.0.1
#访问端口  
redis.port=6379  
#注意,若是没有password,此处不设置值,但这一项要保留  
redis.password=  
  
#最大空闲数,数据库链接的最大空闲时间。超过空闲时间,数据库链接将被标记为不可用,而后被释放。设为0表示无限制。  
redis.maxIdle=300  
#链接池的最大数据库链接数。设为0表示无限制  
redis.maxActive=600  
#最大创建链接等待时间。若是超过此时间将接到异常。设为-1表示无限制。  
redis.maxWait=1000  
#在borrow一个jedis实例时,是否提早进行alidate操做;若是为true,则获得的jedis实例均是可用的;  
redis.testOnBorrow=true

 

在applicationContext.xml下配置好自动注解扫描,bean文件扫描
<!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 --> <context:component-scan base-package="com.one.*" /> <!--写本身的包的路径 --> <!-- 加载bean配置 --> <import resource="classpath*:conf/beans-*.xml"/> <!-- 由于个人bean文件都是 conf目录下的 名字以beans-开头的 例如 beans-redis.xml -->
 
 
目录结构
在beans-redis.xml文件里配置bean信息
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd ">
    
    
    <!--  若是在多个spring配置文件中引入<context:property-placeholder .../>标签,
    最后须要加上ignore-unresolvable="true",不然会报错。
    
    ignore-unresolvable="true" 
    在加载第一个property-placeholder时出现解析不了的占位符进行忽略掉 -->
    <!-- 链接池基本参数配置,相似数据库链接池 -->
    <context:property-placeholder location="classpath:redis.properties"
        ignore-unresolvable="true" />
    
    <!-- redis链接池 -->  
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxTotal" value="${redis.maxActive}" />
        <property name="maxIdle" value="${redis.maxIdle}" />
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>

    <!-- 链接池配置,相似数据库链接池 -->
    <bean id="jedisConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.host}"></property>
        <property name="port" value="${redis.port}"></property>
        <!-- <property name="password" value="${redis.pass}"></property> -->
        <property name="poolConfig" ref="poolConfig"></property>
    </bean>

    <!--redis操做模版,使用该对象能够操做redis  -->  
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >    
        <property name="connectionFactory" ref="jedisConnectionFactory" />    
        <!--若是不配置Serializer,那么存储的时候缺省使用String,若是用User类型存储,那么会提示错误User can't cast to String!!  -->    
        <property name="keySerializer" >    
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />    
        </property>    
        <property name="valueSerializer" >    
            <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer" />    
        </property>    
        <property name="hashKeySerializer">    
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>    
        </property>    
        <property name="hashValueSerializer">    
            <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>    
        </property>    
        <!--开启事务  -->  
        <property name="enableTransactionSupport" value="true"></property>  
    </bean >   


    <!-- 下面这个是整合Mybatis的二级缓存使用的 
    <bean id="redisCacheTransfer" class="cn.qlq.jedis.RedisCacheTransfer">
        <property name="jedisConnectionFactory" ref="jedisConnectionFactory" />
    </bean>-->

</beans>

 

最后编写测试类开启测试啦, 工具类网上找找, 下面的代码注入RedisUtil报错,涉及的先都去掉
package com.one.redis;

import java.io.InputStream;
import java.util.*;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import redis.clients.jedis.Jedis;

@RunWith(SpringJUnit4ClassRunner.class)
// @ContextConfiguration("classpath:applicationContext-*.xml")
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
// 加载配置文件
@SuppressWarnings("all")
public class RedisTest {

    // @Autowired
    // private RedisUtil redisUtil;

    // 1.导包
    // applicationContext.xml <import resource="classpath*:conf/beans-*.xml"/>
    // beans-redis.xml
    // <bean id="redisTemplate"
    // class="org.springframework.data.redis.core.RedisTemplate" >
    @Resource(name = "redisTemplate")
    private RedisTemplate redisTemplate;

    @Test
    public void testSpringRedis() {
        // stringRedisTemplate的操做
        // String读写
        redisTemplate.delete("myStr");
        redisTemplate.opsForValue().set("myStr", "skyLine");
        System.out.println(redisTemplate.opsForValue().get("myStr"));
        System.out.println("---------------");
        // org.springframework.data.redis.RedisConnectionFailureException:
        // Cannot get Jedis connection; nested exception is
        // redis.clients.jedis.exceptions.JedisConnectionException: Could not
        // get a resource from the pool

        // List读写
        redisTemplate.delete("myList");
        redisTemplate.opsForList().rightPush("myList", "T");
        redisTemplate.opsForList().rightPush("myList", "L");
        redisTemplate.opsForList().leftPush("myList", "A");
        List<String> listCache = redisTemplate.opsForList().range("myList", 0,
                -1);
        for (String s : listCache) {
            System.out.println(s);
        }
        System.out.println("---------------");

        // Set读写
        redisTemplate.delete("mySet");
        redisTemplate.opsForSet().add("mySet", "A");
        redisTemplate.opsForSet().add("mySet", "B");
        redisTemplate.opsForSet().add("mySet", "C");
        redisTemplate.opsForSet().add("mySet", "C");
        Set<String> setCache = redisTemplate.opsForSet().members("mySet");
        for (String s : setCache) {
            System.out.println(s);
        }
        System.out.println("---------------");// ABC

        // Hash读写
        redisTemplate.delete("myHash");
        redisTemplate.opsForHash().put("myHash", "BJ", "北京");
        redisTemplate.opsForHash().put("myHash", "SH", "上海");
        redisTemplate.opsForHash().put("myHash", "HN", "河南");
        Map<String, String> hashCache = redisTemplate.opsForHash().entries(
                "myHash");
        for (Map.Entry entry : hashCache.entrySet()) {
            System.out.println(entry.getKey() + " - " + entry.getValue());
        }
        System.out.println("---------------");

        // Redis Incrby 命令将 key 中储存的数字加上指定的增量值,若是 key 不存在,那么 key 的值会先被初始化为 0
        // ,而后再执行 INCR 操做
        double stringValueDouble = redisTemplate.opsForValue().increment(
                "doubleValue", 5);
        System.out.println("经过increment(K key, double delta)方法以增量方式存储double值:"
                + stringValueDouble);
        // incrBy:将 key 所储存的值加上给定的增量值(increment) 。
        Jedis jedis = new Jedis("127.0.0.1", 6379);

        jedis.incrBy("key3", 5);
        String v3 = jedis.get("key3");
        System.out.println("结果:" + v3);

    }
    @Test
    public void delete() {

        redisTemplate.delete("myStr");
        redisTemplate.delete("mySet");
        redisTemplate.delete("myHash");
        redisTemplate.delete("key3");
        
        String str = "string";// 1.字符串
        redisUtil.set("str", str);
        System.out.println(redisTemplate.opsForValue().get("str"));
    }

    @Autowired
    private RedisUtil redisUtil;

    @Test
    public void testSpringRedis2() {
        String str = "string";// 1.字符串
        List<String> list = new ArrayList<String>();// list
        list.add("0");
        list.add("中国");
        list.add("2");
        Set<String> set = new HashSet<String>();// set
        set.add("0");
        set.add("中国");
        set.add("2");
        Map<String, Object> map = new HashMap();// map
        map.put("key1", "str1");
        map.put("key2", "中国");
        map.put("key3", "str3");

        redisUtil.del("myStr", "str");// 删除数据

        // 1.字符串操做
        System.out.println(str);
        
        redisUtil.set("str", str);
        redisUtil.expire("str", 120);// 指定失效时间为2分钟
        String str1 = (String) redisUtil.get("str");
        
        System.out.println(redisTemplate.opsForValue().get("str"));
        
        
        System.out.println("str1= " + str1);

        // 2.list操做
        redisUtil.lSet("list", list);
        redisUtil.expire("list", 120);// 指定失效时间为2分钟
        List<Object> list1 = redisUtil.lGet("list", 0, -1);
        System.out.println(list1);

        // 3.set操做
        redisUtil.sSet("set", set);
        redisUtil.expire("set", 120);// 指定失效时间为2分钟
        Set<Object> set1 = redisUtil.sGet("set");
        System.out.println(set1);

        // 3.map操做
        redisUtil.hmset("map", map);
        redisUtil.expire("map", 120);// 指定失效时间为2分钟
        Map<Object, Object> map1 = redisUtil.hmget("map");
        System.out.println(map1);

    }

    // TODO 哨兵集群

    // TODO CDN
}

 

这里要说明下,真实这些配置文件的地址其实都在classes 也就是classpath根目录下
E:\e\eclipse\work\one-parent\one-common\target\classes,若是读spring源码就大概能知道,spring是如何先读xml,而后在经过classpath 判断 怎么读配置文件
有的没引入单元测试包的
<properties>
    
        <junit.version>4.9</junit.version>
        <spring-version>3.1.2.RELEASE</spring-version>
    </properties>
        
<dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring-version}</version>
        </dependency>

 

4.redis哨兵集群
上面再介绍redis的基本状况的时候,官网把这个哨兵 sentinel放在最前面讲, 应该是很重要, 主要咱们项目中封装了一层又一层,找了很久才找到redis的真实地址,才知道运用了哨兵集群
//遍历哨兵地址和端口号 执行xxx 可忽略 Jedis jedis = new Jedis("", ); HostAndPort master = MyHostAndPort.toHostAndPort(jedis.sentinelGetMasterAddrByName(masterName));
首先是这样,既然redis要集群, 那么就得有集群管理工具,Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance),Redis 的 Sentinel 为Redis提供了高可用性,包括 监控,提醒,自动故障迁移
什么是高可用, 就是你挂了,我接着跑,生产环境偶尔会遇到服务器宕机,redis链接失败等状况
  • 先来看redis集群,简单来讲就是master-slave,主从复制, slave同步master的数据, 用于读写分离和容灾恢复
参考https://blog.csdn.net/u010648555/article/details/79427606

这么操做
1.先将E:\redis\redis64-3.0.501复制三份,分别命名为redis64-3.0.501-6379,redis64-3.0.501-6379,
redis64-3.0.501-6381

2.修改6380 6381下的redis.windows.conf文件,改为各自对应的端口号,都作6379的从节点

port 6380

# slaveof <masterip> <masterport>
slaveof 127.0.0.1 6379

3.经过上面介绍的cmd脚本形式启动6379, 而后启动6380,而后启动6379客户端,看下图
命令info replication

 

 
 
 
主节点可读可写,从节点只能读不可写,具体的能够本身试试
发现我写个打开redis-cli脚本,打开6380,弹出的命令窗口仍是127.0.0.1:6379>, 因而修改redis.windows-service.conf
也没用,后来查原来是从节点是要加个参数
@echo off cd redis64-3.0.501-6380 redis-cli -p 6380 @pause
 
 
当主节点从新启动后,从节点的状态【从节点依然能够链接主节点】
 
 
  • redis主从复制的缺点: 每次slave断开重连后,都要从新所有同步一遍, 复制延迟,若是master不能写入,会致使业务出错,可用性不高,因此采用哨兵模式
  • 接着上文的基础看redis-sentinel模式的配置,已经有了主从配置,E:\redis\redis64-3.0.501-6379在每一个文件夹下添加一个sentinel.conf的配置文件,这个文件在官网下载linux版本目录下直接有
 
在复制的redis文件夹里也加下该文件,而后改一下端口,26380,和 26381
能够在redis解压目录下 经过redis-server.exe redis.windows.conf
redis-server.exe sentinel.conf --sentinel 命令, 先启动Redis集群,再启动哨兵实例

也能够像以前那样,写个脚本执行

示例文件作了详细的配置说明,启动不了,估计是里面哪里配置有误,懒得找了,用下面的简化版sentinel.conf
port 26379
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 3000
sentinel failover-timeout mymaster 10000
sentinel config-epoch mymaster 0

执行后你会发现该文件有变化,写入了从服务器的信息
# Generated by CONFIG REWRITE
dir "E:\\redis\\redis64-3.0.501-6379"
sentinel leader-epoch mymaster 0
sentinel known-slave mymaster 127.0.0.1 6380
sentinel known-slave mymaster 127.0.0.1 6381
sentinel current-epoch 0

若是报Invalid argument during startup: Failed to open the .conf file: 
通常都是配置文件的问题,把它从其余地方关闭

 

 
 
生成哨兵ID(Sentinel ID),并自动识别主服务器和从服务器
启动后,可使用shutdown命令关闭master,看slave选举日志,80 81竞争master,恢复79,79就做为slave了
Redis-Sentinel是Redis官方推荐的高可用性(HA) 解决方案,Redis-sentinel自己也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换。Sentinel能够监视任意多个主服务器(复用),以及主服务器属下的从服务器,并在被监视的主服务器下线时,自动执行故障转移操做。
 
为了防止sentinel的单点故障,能够对sentinel进行集群化,建立多个sentinel。
 

 
5.几个常见的redis问题
  • Redis 有哪些类型
官方文档: strings, hashes, 我理解就是hashmap, lists, sets, sorted sets with range queries, 后面3个不知道是啥 bitmaps, hyperloglogs, geospatial indexes with radius queries and streams.
  • Redis 内部结构
了解一点,redis使用 c实现的, 使用kev-value的形式存储数据, 熟悉c语言的更好理解一点结构
1.大多数状况下数据以字符串形式展示 2.双端链表,Redis list的实现为一个双向链表,便可以支持反向查找和遍历 3.字典 4.跳跃表 Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序
 
 
  • 聊聊 Redis 使用场景
1.项目里面好比系统参数配置用到的是string, 还有常常要用的好比产品库存 2.Hash, 项目中用到的是 银行编码+缓存惟一标识作key , 身份证 , 用户ID key , 电子帐号 , 用户ID 3.Redis的list是每一个子元素都是String类型的双向链表,能够经过push和pop操做从列表的头部或者尾部添加或者删除元素, 这样List便可以做为栈,也能够做为队列。 list能够用在消息队列场景,最新消息排行 好比一些最新评论,展现在首页的能够用redis , 只有点击--显示所有--才须要访问数据库, 下降数据库
  • Redis 持久化机制
1.RDB持久化 Redis DataBase 2.AOF持久化 Append Only File
  • Redis 如何实现持久化
1.RDB : 默认的,内存中数据以 快照 的方式写入到 二进制文件 中,默认的文件名为dump.rdb 例子: save 900 1 #900秒内若是超过1个key被修改,则发起快照保存 方便备份,恢复快,最大化 Redis 的性能 不能避免在服务器故障时丢失数据:RDB 文件须要保存整个数据集的状态,并非一个轻松的操做 可能会至少 5 分钟才保存一次 RDB 文件。 在这种状况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据 2.AOF : 当redis重启时会经过从新执行文件中保存的写命令来在内存中重建整个数据库的内容 AOF 持久化会让 Redis 变得很是耐久(much more durable) AOF 的默认策略为每秒钟 fsync 一次,在这种配置下,Redis 仍然能够保持良好的性能,而且就算发生故障停机, 也最多只会丢失一秒钟的数据( fsync 会在后台线程执行,因此主线程能够继续努力地处理命令请求) appendonly yes //启用aof持久化方式 # appendfsync always //每次收到写命令就当即强制写入磁盘,最慢的,可是保证彻底的持久化,不推荐使用 appendfsync everysec //每秒钟强制写入磁盘一次,在性能和持久化方面作了很好的折中,推荐 # appendfsync no //彻底依赖os,性能最好,持久化没保证
  • Redis 集群方案与实现
参考上面的 哨兵集群
  • Redis 为何是单线程的
由于Redis是基于内存的操做,CPU不是Redis的瓶颈, 100000+的QPS(每秒内查询次数) per second Redis的瓶颈最有多是机器内存的大小或者网络带宽 了解: 单线程的方式是没法发挥多核CPU 性能,不过咱们能够经过在单机开多个Redis 实例 能够在同一个多核的服务器中,能够启动多个实例,组成master-master或者master-slave的形式 耗时的读命令能够彻底在slave进行 单线程,只是在处理咱们的网络请求的时候只有一个线程来处理 一个正式的Redis Server运行的时候确定是不止一个线程的
  • 缓存崩溃
集群,哨兵部署起来 redis备份和预热 缓存预热:系统上线后,将相关的缓存数据直接加载到缓存系统,好比咱们用一个job,能够手动执行,去加载全部须要缓存的信息 项目中, 先查缓存, 缓存不存在则从数据库查, 查到结果,置入缓存 因为原有缓存失效,新缓存未到期间(例如:咱们设置缓存时采用了相同的过时时间,在同一时刻出现大面积的缓存过时), 全部本来应该访问缓存的请求都去查询数据库了 一个简单方案就时讲缓存失效时间分散开,好比咱们能够在原有的失效时间基础上增长一个随机值, 好比1-5分钟随机,这样每个缓存的过时时间的重复率就会下降,就很难引起集体失效的事件 缓存标记,咱们项目中就使用了一个标记string字段: 在项目上线后, 将key :isReliable value:1作缓存,设置永久 先去查缓存,若是缓存中没有,多是redis所有挂了, 也多是真的没有数据, 那么查该标记,若是为空可能就是缓存挂了, 再去查数据库的里的表,由于咱们作了分表要一次性查20张表的数据 性能很低 若是不为空,说明缓存没挂,在根据业务逻辑进行处理,说明可能真的没存,直接找对应的表
  • 缓存降级
当访问量剧增,仍然要保证核心服务可用, 非核心服务提供有损的也能够,好比原本显示余额的 给它显示一个 "客观别急" 降级方式:能够经过一些数据进行自动降级 经过人工开关进行降级 服务降级的目的,是为了防止Redis服务故障,致使数据库跟着一块儿发生雪崩问题。所以,对于不重要的缓存数据, 能够采起服务降级策略,例如一个比较常见的作法就是,Redis出现问题,不去数据库查询,而是直接返回默认值给用户
缓存穿透: 缓存命中率问题, 用户查数据,数据库没有,则没有置入缓存,缓存中没有,每次都去查数据库 若是一个查询返回的数据为空(无论是数据不存在,仍是系统故障),咱们仍然把这个空结果进行缓存,但它的过时时间会很短, 最长不超过五分钟。经过这个直接设置的默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库 能够给key设置一些格式规则,而后查询以前先过滤掉不符合规则的Key
  • 使用缓存的合理性问题
1.热点数据 ,固然一些系统参数能够设置永久 2.包括上面提到的缓存降级,预热,穿透等等 3.频繁修改的数据要考虑是否会常常读
相关文章
相关标签/搜索