redis-缓存设计-记录前一个小时和最新的日志(代码片段)

意犹未尽 意犹未尽     2022-12-26     105

关键词:

需求

记录最新的日志 99条

同时记录上一个小时和最近一个小时的 日志出现次数

记录日志代码

 /**
     *
     * @param conn 连接
     * @param name 模块名字
     * @param message 日志信息
     * @param level 日志等级
     * @param timeout 重试时间
     */
    public static void logCommon(
            Jedis conn, String name, String message, String level, int timeout,Date date) 
        //日志出现数量的key
        String commonDest = "common:" + name + ‘:‘ + level;
        //记录当前所处小时数
        String startKey = commonDest + ":start";
        //上一次所属小时数
        String  pstartkey= commonDest + ":pstart";
        //计算重试后时间
        long end = System.currentTimeMillis() + timeout;
        //获得当前所处小时数
        String existing = conn.get(startKey);
        //yyyy-mm-dd  HH:00:00
        String hourStart = ISO_FORMAT.format(date);
        //是否需要重试
        while (System.currentTimeMillis() < end) 
            //对当前所处小时数进行监视 避免其他地方在下一小时切换 比如多线程调用
            conn.watch(startKey);

            Transaction trans = conn.multi();
            //表示第一次运行 进行初始化
            if (existing == null) 
                //保存当前最新小时数
                trans.set(startKey, hourStart);
                existing=hourStart;
            
            //如果是下一个小时了 将原来的日志的key重新命名
            if (existing != null && COLLATOR.compare(existing, hourStart) < 0) 
                //通过重命名记录当前记录的key 归档到上一个小时
                trans.rename(commonDest, pstartkey);
                //记录最新的小时数
                trans.set(startKey, hourStart);
            

            //记录日志出现次数 对日志出现数进行+1  这里只是记录日志出现次数
            trans.zincrby("common:" + name + ‘:‘ + level,1,message);
            //存储日志
            String recentDest = "recent:" + name + ‘:‘ + level;
            //消息追加到队列
            trans.lpush(recentDest,  message);
            //只保留0-99条
            trans.ltrim(recentDest, 0, 99);
            List<Object> results = trans.exec();
            // null response indicates that the transaction was aborted due to
            // the watched key changing.
            if (results == null) 
                continue;
            
            return;
        
    

 

返回上一次或者下一次日志

 /**
     * 打印日志信息
     * @param conn 连接
     * @param type top为上一次  current为当前
     */
    public static void printLog(Jedis conn,String name, String level,String type)
        String hourStart=null;
        String commonDest = "common:" + name + ‘:‘ + level;
        if(type=="top")
            commonDest=commonDest+":pstart";
        
        Set<Tuple> common = conn.zrevrangeWithScores(commonDest, 0, -1);
        for (Tuple tuple : common) 
            System.out.println("消息:  " + tuple.getElement() + ",出现次数 " + tuple.getScore());
        
    

 

测试

 public static final Collator COLLATOR = Collator.getInstance();

    /**
     * 用于比较是否是上一小时了
     */
    public static final SimpleDateFormat TIMESTAMP =
            new SimpleDateFormat("EEE MMM dd HH:00:00 yyyy");
    /**
     * 用于格式化为yyyy-MM-dd hh:00:00
     */
    private static final SimpleDateFormat ISO_FORMAT =
            new SimpleDateFormat("yyyy-MM-dd‘T‘HH:00:00");
    static 
        ISO_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
    

    public static void main(String[] args)
            throws Exception 
        Jedis conn = new Jedis("127.0.0.1", 6379);
        conn.flushDB();
        //录入100条日志信息
        for(int i=0;i<10;i++)
            logCommon(conn,"促销","前一个小时测试嗷嗷"+i,"info",2000,new Date());
        
        //模拟切换到下一小时i
        Calendar calendar=Calendar.getInstance();
        calendar.setTime(new Date());
        //追加一个小时
        calendar.add(Calendar.HOUR,1);
        for(int i=0;i<3;i++)
            logCommon(conn,"促销","当前一个小时测试嗷嗷"+i,"info",2000,calendar.getTime());
            //测试重复消息
            logCommon(conn,"促销","我是重复数据"+i,"info",2000,calendar.getTime());
            //
            logCommon(conn,"促销","我是重复数据"+i,"info",2000,calendar.getTime());
        
        //===================获得前一个小时的日志信息====================
        System.out.println("获得前一个小时的日志信息");
        printLog(conn,"促销","info","top");
        //===================获取当前的日志新====================
        System.out.println("获得当前最新的日志信息");
        printLog(conn,"促销","info","current");

    

打印

得前一个小时的日志信息
消息:  前一个小时测试嗷嗷9,出现次数 1.0
消息:  前一个小时测试嗷嗷8,出现次数 1.0
消息:  前一个小时测试嗷嗷7,出现次数 1.0
消息:  前一个小时测试嗷嗷6,出现次数 1.0
消息:  前一个小时测试嗷嗷5,出现次数 1.0
消息:  前一个小时测试嗷嗷4,出现次数 1.0
消息:  前一个小时测试嗷嗷3,出现次数 1.0
消息:  前一个小时测试嗷嗷2,出现次数 1.0
消息:  前一个小时测试嗷嗷1,出现次数 1.0
消息:  前一个小时测试嗷嗷0,出现次数 1.0
获得当前最新的日志信息
消息:  我是重复数据2,出现次数 2.0
消息:  我是重复数据1,出现次数 2.0
消息:  我是重复数据0,出现次数 2.0
消息:  当前一个小时测试嗷嗷2,出现次数 1.0
消息:  当前一个小时测试嗷嗷1,出现次数 1.0
消息:  当前一个小时测试嗷嗷0,出现次数 1.0

 

关于新框架中的常规日志记录、缓存和性能

】关于新框架中的常规日志记录、缓存和性能【英文标题】:Aboutgenerallogging,cachingandperformanceinnewframework【发布时间】:2009-08-3013:52:31【问题描述】:我正在根据Zend框架创建一个新的PHP框架。它将是用于Web开发的通用MVC框架。我... 查看详情

httpd静态文件缓存和日志不记录(代码片段)

httpd不记录指定元素的访问日志在访问一个web页面时,httpd会记录这个页面中的图片、js/css页面或视频访问一类的记录信息,并把这些信息存储到日志当中,记录日志是非常详细的,但是日志大小会增长的非常快,因为每一次访... 查看详情

sqlserver日志文件总结及日志满的处理

...文件    出于性能上的考虑SQLServer将用户的改动存入缓存中这些改变会立即写入交易日志但不会立即写入数据文件交易日志会通过一个标记点来确定某个交易是否已将缓存中的数据写入数据文件当SQLServer重启后它会查看日志... 查看详情

来自多个表的 MySQL 最新相关记录

】来自多个表的MySQL最新相关记录【英文标题】:MySQLlatestrelatedrecordfrommorethanonetable【发布时间】:2014-09-1608:41:13【问题描述】:假设一个主“作业”表和两个对应的“日志”表(一个用于服务器事件,另一个用于用户事件,每... 查看详情

实时海量日志分析系统的架构设计实现以及思考

...实现一个日志分析系统,但是将日志分析系统进行模块化设计可以收到更好的效果。模块化的设计至少有两方面的优点: 模块化设计可以使功能更加清晰。整个日志分析系统可以分为“数据采集-数据缓冲-数据处理-数据... 查看详情

redis缓存穿透和雪崩

一、什么是缓存穿透?定义:客户端查询了一个数据库中没有的记录导致缓存在这种情况下无法利用,称之为缓存穿透或者缓存击穿。如图,这是提条正常的查询语句,客户端查询id为“1”的这样一条记录,这... 查看详情

用以前的记录值更新最新记录

】用以前的记录值更新最新记录【英文标题】:Updatelatestrecordwithpreviousrecordvalues【发布时间】:2020-09-1723:20:56【问题描述】:我有一个名为Audits的表,它有一个CompanyId、Date、AuditNumber字段,每个公司可以有许多审计,而AuditNumber... 查看详情

程序猿修仙之路--数据结构之设计高性能访客记录系统(代码片段)

...往下看!!!有什么设计要点呢?用户的访客记录一定要缓存,要不然怎么抗住大并发呢?由于最新的访客记录变化非常快,要有一种能快速添加新数据,删除老数据的数据结构。缓存的篇章今日暂且不说,说一下以上的第二点... 查看详情

react错误处理和日志记录的思考与设计(代码片段)

文章目录React错误处理和日志记录的思考与设计前端需要采集哪些异常数据?前端怎么统一捕获异常?接口异常前端异常如何上报数据?接口异常前端异常存在的问题处理上报异常和通知参考React错误处理和日志记录的思考与设计在... 查看详情

Sqlite 返回最新值与 24 小时前值之间的行差异

...】:2020-05-1510:01:44【问题描述】:这里是Sqlite菜鸟。我有一个SQLite时间序列数据库,每四分钟更新一次,我想报告最近数据点与(大约)24小时前的数据点之间的行值差异。如果我运行SELECTentity_id, 查看详情

redis高频面试题汇总(上)(代码片段)

目录1.什么是Redis?2.为什么Redis这么快3.分布式缓存常见的技术选型方案有哪些?4.你知道Redis和Memcached的区别吗?5.Redis使用场景有哪些6.Redis常用的数据结构有哪些?7.Redis数据类型有哪些底层数据结构?8.为什么要... 查看详情

记录一次redis事故

公司在搞一次活动时,服务器一个应用服务出现异常,结果导致前端不断请求最终导致请求量过大,资源耗尽。追踪原因:1、调出应用日志,发现这个请求为获取微信信息的接口,微信的access_token过期了导致微信拒绝服务2、猜... 查看详情

aof持久化

...行恢复。Redis虽说是内存数据库,但是Redis其实是会把缓存数据保存到硬盘的,只要保存缓存数据的文件没有丢,缓存数据自然就能恢复。Rdedis共有两种持久化技术,分别是AOF日志和RDB快照Redis默认会开启RDB快照... 查看详情

@Cacheable 命中的 Spring 缓存日志记录

】@Cacheable命中的Spring缓存日志记录【英文标题】:Springcacheloggingon@Cacheablehit【发布时间】:2016-09-1320:23:37【问题描述】:目前我正在使用SpringCache和@Cacheable/@CacheEvict注释。我想获得某种控制台日志语句,例如"INFO:igotthosevalues... 查看详情

使用redis和java进行数据库缓存

使用Redis和Java探索数据库缓存,并查看一些不同的缓存策略。最近在优锐课学习收获颇多,记录下来大家一起进步!为什么数据库缓存如此重要?你在数据库中拥有的信息越多,随着时间的推移它将变得越慢。即使是经过精心设... 查看详情

小工匠聊架构-redis缓存一致性设计

文章目录Pre思路Spring注解使用:控制Redis缓存更新一致性问题是如何产生的?双更新模式:操作不合理,导致数据一致性问题“后删缓存”能解决多数不一致(Cache-AsidePattern)1.如果先删缓存2.如果后删缓存高并发,“后删缓存”依... 查看详情

elkstack

...ginx日志监控分析。nginx的每个请求状态等都有日志文件来记录,可以通过读取日志文件来分析;logstash有agent(Shipper)和server(Indexer)端,agent端负责监控本地日志文件的变化,及时把日志文件的最新内容收集起来, 查看详情

实现缓存最终一致性的两种方案

  一、重客户端  写入缓存:     应用同时更新数据库和缓存  如果数据库更新成功,则开始更新缓存,否则如果数据库更新失败,则整个更新过程失败。  判断更新缓存是否成功,如果成功则返回  如果缓... 查看详情