精华内容
下载资源
问答
  • 1. 前戏 1. 数据字典文件模样 { "dict": [ { "code": [ { "text": "男1", "value": "01" }, { "text": "女2", "value": "02" } ],...

    1. 前戏

    1. 数据字典文件模样

    {
      "dict": [
        {
          "code": [
            {
              "text": "男1",
              "value": "01"
            },
            {
              "text": "女2",
              "value": "02"
            }
          ],
          "name": "性别",
          "key": "sex"
        },
        {
          "code": [
            {
              "text": "小学3",
              "value": "01"
            },
            {
              "text": "中学4",
              "value": "02"
            },
            {
              "text": "大学",
              "value": "03"
            }
          ],
          "name": "学校",
          "key": "school"
        },
    	{
          "code": [
            {
              "text": "大1傻",
              "value": "01"
            },
            {
              "text": "二呆",
              "value": "02"
            }
          ],
          "name": "小名",
          "key": "smallName"
        }
      ]
    }
    

    2. pom

       <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-cache</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.6</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
        </dependencies>
    

    1. 使用工具转成java类

    存在问题? json
    到最后展示的时候是不是有序的,讲师用的 LinkedHashMap百度可知他会保持有序

    涉及持久化的要 implements Serializable
    本次要存入redis 所以加上

    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    public class Code implements Serializable {
    
        private String text;
        private String value;
    }
    
    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    public class Dict implements Serializable {
    
        private List<Code> code;
        private String name;
        private String key;
    }
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    //@EqualsAndHashCode(callSuper = false)
    public class Dictionary implements Serializable {
        private List<Dict> dict;
    }
    
    ### 2. 监听本地文件
    ```java
    package com.xujiang.xujiang.listen;
    
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
    import org.apache.commons.io.monitor.FileAlterationObserver;
    import org.springframework.context.annotation.PropertySource;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.Arrays;
    
    @Slf4j
    @PropertySource("classpath:xu.properties")
    public class FileListener extends FileAlterationListenerAdaptor {
    
        private ListenerService listenerService;
    
        public FileListener(ListenerService listenerService) {
            this.listenerService = listenerService;
        }
        public static final String KEY="dict";
    //    @Autowired
    //    XuProperties properties;
    //    String key = "dict";
    
        @Override
        public void onFileCreate(File file) {
            log.info("FileListener 监听到文件新建,名称: {} 路径:{}", file.getName(), file.getAbsolutePath());
            try {
                listenerService.writeJsonFileToMemory(KEY, file);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void onFileChange(File file) {
            log.info("FileListener 监听到文件改变,名称: {} 路径:{}", file.getName(), file.getAbsolutePath());
            try {
                listenerService.writeJsonFileToMemory(KEY, file);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void onFileDelete(File file) {
            log.info("FileListener 监听到文件删除,名称: {} 路径:{}", file.getName(), file.getAbsolutePath());
            listenerService.clear(KEY);
    
            File folder = new File(file.getParent());
            String[] list = folder.list();
    
    
            if (list != null && list.length > 0) {
                Arrays.stream(list).filter((x) -> x.endsWith(".json")).forEach((y) -> {
                    try {
                        listenerService.writeJsonFileToMemory(KEY, new File(file.getParent() + "\\"+y));
                        log.info("虽然被删除,但是同目录下我找到了这个:{}", y);
    
                    } catch (IOException e) {
                        log.error("读文件错误, name: {}", y);
                    }
                });
    
            }
        }
    
    
        @Override
        public void onStart(FileAlterationObserver observer) {
            log.info("FileListener 启动完毕,监听路径: {}", observer.getDirectory().getAbsolutePath());
    
        }
    //
    //    @Override
    //    public void onDirectoryCreate(File directory) {
    //        log.info("FileListener 监听到文件夹创建,名称: {}", directory.getName());
    //
    //    }
    //
    //    @Override
    //    public void onDirectoryChange(File directory) {
    //        log.info("FileListener 监听到文件夹修改,名称: {}", directory.getName());
    //
    //    }
    //
    //    @Override
    //    public void onDirectoryDelete(File directory) {
    //        log.info("FileListener 监听到文件夹删除,名称: {}", directory.getName());
    //
    //    }
    
    
    }
    
    
    
    package com.xujiang.xujiang.listen;
    
    import com.xujiang.xujiang.XuProperties;
    import org.apache.commons.io.filefilter.FileFilterUtils;
    import org.apache.commons.io.filefilter.HiddenFileFilter;
    import org.apache.commons.io.filefilter.IOFileFilter;
    import org.apache.commons.io.monitor.FileAlterationMonitor;
    import org.apache.commons.io.monitor.FileAlterationObserver;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.stereotype.Component;
    
    import java.io.File;
    import java.util.concurrent.TimeUnit;
    
    @Component
    @ConditionalOnProperty(value = "dict.option", havingValue = "auto")
    
    public class FileListenerFactory {
        @Autowired
        XuProperties properties;
        // 设置监听路径
    //    private final String monitorDir = "/tmp/monitorTest";
    
        // 设置轮询间隔
        private final long interval = TimeUnit.SECONDS.toMillis(1);
    
        // 自动注入业务服务
        @Autowired
        private ListenerService listenerService;
    
        public FileAlterationMonitor getMonitor() {
            // 创建过滤器
            IOFileFilter directories = FileFilterUtils.and(
                    FileFilterUtils.directoryFileFilter(),
                    HiddenFileFilter.VISIBLE);
            IOFileFilter files = FileFilterUtils.and(
                    FileFilterUtils.fileFileFilter(),
                    FileFilterUtils.suffixFileFilter(".json"));
            IOFileFilter filter = FileFilterUtils.or(directories, files);
    
            // 装配过滤器
            // FileAlterationObserver observer = new FileAlterationObserver(new File(monitorDir));
            FileAlterationObserver observer = new FileAlterationObserver(new File(properties.WATCH_DICT), filter);
    
            // 向监听者添加监听器,并注入业务服务
            observer.addListener(new FileListener(listenerService));
    
            // 返回监听者
            return new FileAlterationMonitor(interval, observer);
        }
    }
    
    
    
    package com.xujiang.xujiang.listen;
    
    import org.apache.commons.io.monitor.FileAlterationMonitor;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.stereotype.Component;
    
    @Component
    @ConditionalOnProperty(value = "dict.option", havingValue = "auto")
    
    public class FileListenerRunner implements CommandLineRunner {
    
        @Autowired
        private FileListenerFactory fileListenerFactory;
    
        @Override
        public void run(String... args) throws Exception {
            // 创建监听者
            FileAlterationMonitor fileAlterationMonitor = fileListenerFactory.getMonitor();
            try {
                // do not stop this thread
                fileAlterationMonitor.start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    太多了 不想复制了 …

    展开全文
  • redis缓存部分数据库数据后,当需要更新数据库数据时,如何同步更新redis缓存内的数据了??求解,谢谢
  • Redis缓存数据与数据库如何同步,更新数据库时如何保证与缓存中的数据保持一致
  • redis缓存数据的流程

    千次阅读 2018-08-30 16:27:51
    现在我们数据每次都是从数据库读取,这样当网站访问量达到高峰时段,对数据库压力很大,并且...2.如果redis没有,这时去数据库查询,返回结果集,并且同步地把缓存数据放到redis中 3.如果redis没有,数据库也没有...

    现在我们数据每次都是从数据库读取,这样当网站访问量达到高峰时段,对数据库压力很大,并且影响执行效率。我们需要将这部分广告数据缓存起来。

    查询的时候走缓存,增删改的时候同步更新缓存

    查询的时候:先查redis,根据key去查

    1.如果redis有,直接返回结果集

    2.如果redis没有,这时去数据库查询,返回结果集,并且同步地把缓存数据放到redis中

    3.如果redis没有,数据库也没有,把key-null存到redis中

    问题1:不应该同步地把数据保存到缓存中,异步把数据放到缓存中,使用mq发消息

    问题2:查询的key永远没有value,每次的请求都会打到数据库,因为redis中没有缓存结果数据,会造成缓存的穿透,缓存value为空的数据

    问题3:如果恶意访问,故意制造一些数据库没有的数据进行攻击,如果说访问持续缓慢,需要降低被恶意程序盯上的几率,缓存的降级,不管什么请求,短时间,高并发,全部返回null,很可能是一个爬虫程序

    问题4:短信验证码,报警,请了武汉本地安全团队进行一些反制措施,最终找到这个人,短信轰炸机,调用别的公司的短信接口

    在发短信之前,可以使用随机验证码,请滑动图块

    展开全文
  • redis 缓存数据格式

    2020-08-14 21:17:46
    1.序列化字符串 ...2.Redis的其他数据类型,如hash、set、zset hmset('user:1:info', user_dict) 优点 读写时不需要序列化转换 可以更新内部数据 缺点 相比字符串,采用复合结构存储空间占用大 ...

    1.序列化字符串
    setex('user:1:info', expiry, json.dumps(user_dict))

    优点
    存储字符串节省空间
    缺点
    序列化有时间开销
    更新不方便(一般直接删除)

    2.Redis的其他数据类型,如hash、set、zset
    hmset('user:1:info', user_dict)

    优点
    读写时不需要序列化转换
    可以更新内部数据
    缺点
    相比字符串,采用复合结构存储空间占用大

    展开全文
  • redis缓存雪崩 同一个时间redis的key失效,缓存失效,所有的请求直接打到数据库,造成数据库并发增大或崩溃,(雪崩) 处理1:为每个key的失效时间设置一个随机值,避免同一时间失效 处理2:设置热点数据永不...

     

    redis 缓存雪崩

     

        同一个时间redis的key失效,缓存失效,所有的请求直接打到数据库,造成数据库并发增大或崩溃,(雪崩)

     

        处理1: 为每个key的失效时间设置一个随机值,避免同一时间失效

        处理2: 设置热点数据永不过期,更新时更新缓存即可;

     

    redis 缓存穿透

     

        只缓存与数据库均没有数据,当用户不断发请求,数据库压力过大,严重则击垮数据库。 例如:攻击者伪造不存在的key大量请求,每次都会给数据库带来压力,如传入用户ID为-1

     

        处理1:接口层面增加校验,增加鉴权,加密请求等,特殊值需求校验合法范围,如id<0 直接校验失败;

     

        处理2:如果缓存取不到值,DB也娶不到值,则将key对应的value存储为null,设置缓存30秒(时间太长影响正常业务),避免频繁查DB

     

        处理3:单个IP的请求拦截,可以在Nginx中进行配置,如果是用户操作不会太频繁


     

    redis 缓存击穿

        

        缓存击穿是指一个Key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个完好无损的桶上凿开了一个洞。

     

        处理1:热点的key设置永久不过期,变更后更新缓存即可;

     

        处理2:缓存击穿的话,设置热点数据永远不过期。或者加上互斥锁就能搞定了;


     

    大家一定要理解是怎么发生的,以及是怎么去避免的,发生之后又怎么去抢救






     

    展开全文
  • 在最近项目开发中,采用mysql存储持久化数据redis缓存热门数据,遇到一个问题,对于一些强实时性业务,我们需要先将数据写到mysql上,mysql写入成功后,再去更新redis,从而确保redis解决读的问题,同时保证了关键...
  • Redis缓存数据一致性

    2019-08-19 12:56:25
    场景1:更新数据库成功,更新缓存失败,数据不一致; 场景2:更新缓存成功,更新数据库失败,数据不一致; 场景3:更新数据库成功,清除缓存失败,数据不一致; 场景4:清除缓存成功,更新数据库失败,数据弱一致; 缓存...
  • 这个业务场景,主要是解决读数据Redis缓存,一般都是按照下图的流程来进行业务操作。读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据...
  • 这个业务场景,主要是解决读数据Redis缓存,一般都是按照下图的流程来进行业务操作。读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据一....
  • 这个业务场景,主要是解决读数据Redis缓存,一般都是按照下图的流程来进行业务操作。读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据...
  • 这个业务场景,主要是解决读数据Redis缓存,一般都是按照下图的流程来进行业务操作。读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据...
  • 这个业务场景,主要是解决读数据Redis缓存,一般都是按照下图的流程来进行业务操作。 读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据...
  • 这个业务场景,主要是解决读数据Redis缓存,一般都是按照下图的流程来进行业务操作。 读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MyS...
  • redis 同步更新缓存数据

    千次阅读 2019-02-11 11:47:26
    问题场景 练习项目写后台的时候,在后台对前端...出现问题:实际数据更新redis缓存中数据未更新 解决思路 在实际更新数据库操作的同时,对 redis 的缓存数据进行更新处理 具体步骤:删除原有的 redis 中的缓存...
  • 这个业务场景,主要是解决读数据Redis缓存,一般都是按照下图的流程来进行业务操作。 读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据...
  • redis缓存和mysql数据库同步解决方案一、对强一致要求比较高的,应采用实时同步方案,即查询缓存查询不到再从DB查询,保存到缓存;更新缓存时,先更新数据库,再将缓存的设置过期(建议不要去更新缓存内容,直接设置...
  • 当两个请求同时修改数据库,一个请求已经更新成功并删除缓存时又有读数据的请求进来,这时候发现缓存中无数据就去数据库中查询并放入缓存,在放入缓存前第二个更新数据库的请求成功,这时候留在缓存中的数据依然是第...
  • 关注我,可以获取最新知识、经典...这个业务场景,主要是解决读数据Redis缓存,一般都是按照下图的流程来进行业务操作。读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓...
  • 但是在更新缓存方面,对于更新完数据库,是更新缓存呢,还是删除缓存。又或者是先删除缓存,再更新数据库,其实大家存在很大的争议。目前没有一篇全面的博客,对这几种方案进行解析。于是博主战战兢兢,顶着被大家喷...
  • 缓存和数据库一致性更新原则缓存是一种高性能的内存的存储介质,它通过key-value的形式来存储一些数据;而数据库是一种持久化的存储复杂关系的存储介质。使用缓存和数据库结合的模式就使得软件系统的性能得到了更好...
  • 这个业务场景,主要是解决读数据Redis缓存,一般都是按照下图的流程来进行业务操作。读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的...
  • 最初级的缓存不一致问题及解决方案 问题:先修改数据库,再删除缓存。...因为读的时候缓存没有,则读数据库中旧数据,然后更新缓存中。 比较复杂的数据不一致问题分析 数据发生了变更,先删除了缓存,...
  • 这个业务场景,主要是解决读数据Redis缓存,一般都是按照下图的流程来进行业务操作。读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据一....
  • 这个业务场景,主要是解决读数据Redis缓存,一般都是按照下图的流程来进行业务操作。读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓存(Redis)和数据库(MySQL)间的数据一....
  • 缓存预热,是指系统上线后,先将数据加载到缓存系统,手动或定时刷新。 缓存更新 缓存更新,是指根据需要定期或触发清理过期或不需要的缓存缓存降级 缓存降级,是为保证核心服务可用,使部分关键数据自动降级...
  • 对于读多写少的高并发场景,我们会经常使用缓存来进行优化。...Redis缓存数据一致性问题那么基于上面的这个出发点,问题就来了,当用户的余额发生变化的时候,如何更新缓存中的数据,也就是说。我是先...
  • redis缓存更新策略

    2020-03-04 18:47:34
    Redis缓存设计原则 只应将热数据放到缓存中 所有缓存信息都应设置过期时间 缓存过期时间应当分散以避免集中过期 缓存key应具备可读性 应避免不同业务出现同名缓存key 可对key进行适当的缩写以节省内存空间 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,370
精华内容 948
关键字:

更新redis缓存数据

redis 订阅