Java和Redis实现一个简单的热搜功能
1. 前言
我们有一个简单的需求:
- 搜索栏展示当前登陆的个人用户的搜索历史记录,删除个人历史记录。
- 用户在搜索栏输入某字符,则将该字符记录下来 以zset格式存储的redis中,记录该字符被搜索的个数以及当前的时间戳 (用了DFA算法)。
- 每当用户查询了已在redis存在了的字符时,则直接累加个数, 用来获取平台上最热查询的十条数据。(可以自己写接口或者直接在redis中添加一些预备好的关键词)。
- 做不雅文字的过滤功能。
2. 实现
2.1 引入依赖
<dependencies> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.7.0</version> <!-- 使用你需要的版本 --> </dependency>
</dependencies>
2.2 实现代码
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Tuple;import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;public class HotSearch {private static final String REDIS_HOST = "localhost";private static final int REDIS_PORT = 6379;private static final String HISTORY_SET = "history";private static final String ZSET_PREFIX = "zset:";private static final int TOP_TEN = 10;private static final String BAD_WORDS = "bad"; // 替换为需要过滤的关键词 private static final String FILTERED_WORD = "***"; // 替换为过滤后的关键词 private static final int BAD_WORD_THRESHOLD = 100; // 替换为过滤的阈值,超过则认为是不雅文字 private static final List<String> BAD_WORD_LIST = IntStream.range(0, BAD_WORDS.length()).mapToObj(i -> BAD_WORDS.substring(i, i + 1)).collect(Collectors.toList()); // 将BAD_WORDS转为List,方便后续操作 public static void main(String[] args) {Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT);String userId = "user1"; // 当前登陆的个人用户ID,需要根据实际情况获取 String searchWord = "test"; // 需要搜索的字符 hotSearch(jedis, userId, searchWord);}public static void hotSearch(Jedis jedis, String userId, String searchWord) {// 获取当前用户的搜索历史记录 Set<String> history = jedis.smembers(HISTORY_SET + ":" + userId);if (history == null) history = new HashSet<>();history.add(searchWord); // 将新搜索词加入历史记录 jedis.sadd(HISTORY_SET + ":" + userId, history); // 将历史记录存入redis中 history.remove(searchWord); // 去掉新搜索词,只保留旧的历史记录 // 将搜索词加入zset中,记录该字符被搜索的个数以及当前的时间戳 jedis.zadd(ZSET_PREFIX + userId, getScore(searchWord), searchWord);System.out.println("Added " + searchWord + " to hot search with score " + getScore(searchWord));// 过滤不雅文字,如果是不雅文字则替换为***,并累加不雅文字的搜索次数 if (BAD_WORD_LIST.contains(searchWord)) {if (jedis.zscore(ZSET_PREFIX + userId, FILTERED_WORD) == null) { // 如果该词在zset中不存在,则加入并设置得分 jedis.zadd(ZSET_PREFIX + userId, BAD_WORD_THRESHOLD, FILTERED_WORD); // 设置得分为BAD_WORD_THRESHOLD,表示这是一个不雅文字 jedis.incrBy(HISTORY_SET + ":bad", 1); // 累加不雅文字的搜索次数,存储在bad历史的集合中,方便后续统计和过滤处理 } else { // 如果该词在zset中已存在,则只累加搜索次数,并更新得分(得分+1) jedis.zincrby(ZSET_PREFIX + userId, 1, FILTERED_WORD); // 得分为当前得分+1,表示这是一个不雅文字的再次搜索 jedis.incrBy(HISTORY_SET + ":bad", 1); // 累加不雅文字的搜索次数,存储在bad历史的集合中,方便后续统计和过滤处理 }System.out.println("The word " + searchWord + " is filtered and replaced with " + FILTERED_WORD); // 输出过滤后的结果 } else { // 如果不是不雅文字,则正常加入热搜列表并设置得分 jedis.zadd(ZSET_PREFIX + userId, getScore(searchWord), searchWord); // 正常加入热搜列表并设置得分 System.out.println("Added normal word " + searchWord + " to hot search with score " + getScore(searchWord)); // 输出正常加入热搜列表的结果}// 获取平台上最热搜索的十条数据 Set<Tuple> hotData = jedis.zrevrangeWithScores(ZSET_PREFIX + userId, 0, TOP_TEN - 1);List<String> hotWords = hotData.stream().map(Tuple::getElement).collect(Collectors.toList());List<Integer> hotScores = hotData.stream().map(Tuple::getScore).collect(Collectors.toList());System.out.println("Top " + TOP_TEN + " hot searches are: " + hotWords + " with scores: " + hotScores);}// 用于计算得分的方法,这里采用了最简单的得分方式,只考虑了搜索频率和时间戳,实际情况可能需要更复杂的算法 private static int getScore(String word) {return 1;}
}
2.3 实现原理
- 搜索历史记录:
- 我们使用Redis的set数据结构来存储用户的搜索历史。每个用户都有自己的历史记录集合,通过
HISTORY_SET + ":" + userId
来区分不同用户的搜索历史。 jedis.sadd
方法用于添加新搜索词到历史记录集合中。- 删除操作没有直接在代码中体现,但可以通过
jedis.srem
方法从集合中移除某个元素来实现。
- 我们使用Redis的set数据结构来存储用户的搜索历史。每个用户都有自己的历史记录集合,通过
- 更新热搜列表:
- 我们使用Redis的有序集合(zset)来存储热搜数据。每个用户都有自己的有序集合,通过
ZSET_PREFIX + userId
来区分不同用户的热搜数据。 - 每个搜索词都与一个得分相关联,该得分由函数
getScore
计算得出。新搜索词得分为1,旧搜索词得分为0。这个得分代表了搜索的频率和时间戳。 jedis.zadd
方法用于向有序集合中添加新元素,并设置其得分。
- 我们使用Redis的有序集合(zset)来存储热搜数据。每个用户都有自己的有序集合,通过
- 获取平台上最热查询的十条数据:
- 我们使用
jedis.zrevrangeWithScores
方法获取有序集合中的前十个元素(得分最高的十个搜索词)。 - 返回的结果是一个包含元素和得分的集合,我们通过流处理将其转换为列表。
- 我们使用
- 不雅文字过滤:
- 这部分功能在代码中有直接实现,其原理是当用户输入搜索词时,系统会检查该词是否在预定义的
BAD_WORDS
列表中。 - 如果在列表中,并且该词的搜索频率超过
BAD_WORD_THRESHOLD
,则认为这是一个不雅文字,将其替换为FILTERED_WORD
。 - 注意:在实际应用中,可能需要更复杂的不雅文字过滤算法和策略,而不仅仅是基于频率的检查。
- 这部分功能在代码中有直接实现,其原理是当用户输入搜索词时,系统会检查该词是否在预定义的
3. 注意事项
- 安全性:
- 确保Redis服务器的安全性。这包括使用强密码、配置防火墙规则、使用SSL连接等。不要将敏感数据暴露给不必要的用户或应用程序。
- 在存储和传输用户搜索数据时,考虑到数据的机密性和隐私保护。根据当地的隐私法律和政策,可能需要采取额外的措施来保护用户数据。
- 性能监控和调优:
- 监控Redis的性能指标,如内存使用情况、连接数、查询速度等。根据实际负载情况,可能需要调整Redis的配置参数或增加硬件资源。
- 定期检查代码的性能,确保在大量请求下能够保持稳定的性能。对于瓶颈部分,可能需要优化算法或调整数据结构。
- 异常处理:
- 添加适当的异常处理逻辑,以处理Redis连接失败、查询错误等情况。确保应用程序能够优雅地处理这些异常,并为用户提供适当的错误消息。
- 对于可能出现的Redis故障或维护时段,考虑实现一种回退机制或通知系统,以便及时通知相关人员并采取措施。
- 数据一致性和备份:
- 确保Redis中的数据与应用程序中的其他数据源保持一致。在写入数据时,要确保幂等性以避免数据冲突。
- 定期备份Redis中的数据,以防数据丢失。考虑使用快照或追加日志的方式来备份数据。
- 扩展性和高可用性:
- 如果应用程序需要处理大量的搜索请求,考虑使用Redis集群来分担负载和提高可用性。确保集群配置正确,并能够自动处理节点故障转移。
- 在设计系统时,考虑到未来的扩展需求。使用可扩展的数据结构或算法,以便在需要时轻松地增加功能和优化性能。
- 日志和监控:
- 配置适当的日志记录系统,记录Redis的操作和关键事件。这有助于故障排查和性能分析。
- 使用监控工具来实时跟踪Redis的性能指标和应用程序的健康状况。这样可以在问题发生时迅速采取行动。
- 测试和验证:
- 在将代码部署到生产环境之前,进行充分的测试和验证。确保代码的功能正确、性能良好,并且没有安全漏洞。
- 考虑使用集成测试、单元测试和负载测试来评估代码的健壮性和稳定性。确保代码能够承受实际工作负载和各种边界条件。
- 代码维护和文档:
- 为代码添加适当的注释和文档,以帮助其他开发人员理解其工作原理和维护方式。这也有助于未来的代码审查和维护工作。
- 保持代码的清洁和可维护性,遵循最佳实践和编码规范。定期重构代码以消除冗余和提高可读性。
相关文章:
Java和Redis实现一个简单的热搜功能
1. 前言 我们有一个简单的需求: 搜索栏展示当前登陆的个人用户的搜索历史记录,删除个人历史记录。用户在搜索栏输入某字符,则将该字符记录下来 以zset格式存储的redis中,记录该字符被搜索的个数以及当前的时间戳 (用…...
超越传统,想修哪里就修哪里,SUPIR如何通过文本提示实现智能图像修复
项目简介 通过参数增加使得模型不仅能够修复图像中的错误或损坏,还能根据文本提示进行智能修复。例如根据描述来改变图像中的特定细节。这样的处理方式提升了图像修复的质量和智能度,使得模型能够更准确、更灵活地恢复和改进图像。 SUPIR的主要功能图像…...
《如何画好架构图》学习笔记
看了一堂《如何画好架构图》的公开课,结合网上的资料与经验做一些思考总结。文中的例子和图片大多是从课程中摘录的。 1. 4R架构定义 4R架构定义其实是软件架构定义经过归纳提炼后的简称。 软件架构定义:软件架构是指软件系统的顶层(Rank&am…...
redis整合
一.redis的发布订阅 什么 是发布和订阅 Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。 Redis 客户端可以订阅任意数量的频道。 1、Redis的发布和订阅 客户端订阅频道发布的消息 频道发布消息 订阅者就可以…...
开循环低温样品架节约液氦操作技巧
开循环低温样品架以降温快、无轰动源、重量轻、装置便利等特色遭到大多数客户的喜爱。但是制冷剂消耗量引起的运用本钱是客户在运用过程中zhong点重视的问题,特别是随着全球液氦价格继续飙升,开循环样品架的运用本钱也在逐渐添加,如何节约液氦…...
年薪30W+,待遇翻倍,我的经历值得每个测试人借鉴
从自考大专到出走公司,从半年无业露宿深圳北站,从8k…到11.5k…再到20k,我的经历值得每个测试人借鉴 或许学历并没有那么重要 12年高考之后,在朋友的介绍下(骗了过去),没有好好的读大学&#x…...
DEB方式安装elastic search7以及使用
参考:https://www.cnblogs.com/anech/p/15957607.html 1、安装elastic search7 #手动下载安装 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.1-amd64.deb wget https://artifacts.elastic.co/downloads/elasticsearch/elastics…...
[Tomcat] [最全] 目录和文件详解
打开tomcat的解压之后的目录可以看到如下的目录结构: Bin bin目录主要是用来存放tomcat的命令,主要有两大类,一类是以.sh结尾的(linux命令),另一类是以.bat结尾的(windows命令)。 …...
微信小程序元素/文字在横向和纵向实现居中对齐、两端对齐、左右对齐、上下对齐
元素对齐往往是新学者的一大困惑点,在此总结常用的各种元素和文字对齐方式以供参考: 初始显示 .wxml <view style"width: 100%;height: 500rpx; background-color: lightgray;"><view style"width: 200rpx;height:100rpx;bac…...
兼容树莓派扩展模块,专注工业产品开发的瑞米派强势来袭
近日,米尔电子和瑞萨电子共同定义和开发了瑞萨第一款MPU生态开发板——瑞米派(Remi Pi)正式上市了!在各种Pi板卡琳琅满目的当下,Remi Pi是一款与众不同的开发板,他兼顾了严肃产品开发和爱好者创意实现两种需…...
云原生 - 微信小程序 COS 对象存储图片缓存强制更新解决方案
问题描述 遇到一个这样的情况:在微信小程序里图片缓存十分麻烦,网上很多说在腾讯云里的 COS 存储对象服务里设置对应的图片缓存(Header 头 Cache-Contorl),说实话真不好用,一会儿生效,一会儿没…...
设计公司设计ppt的优势—南京梵构广告
在这个时代的发展下,PPT软件越来越好用,投影仪越来越便宜,直接导致许多商界人士不再撰写文件了。他们只是在编写演示文稿,这些文稿只是些没有细节、缺乏支持的概要。许多人不喜欢撰写详尽文件所付出的脑力劳动。 视觉效果 一个好…...
gitlab设置/修改克隆clone地址端口
最近由于公司要停测试库云服务器? 什么?要停测试库服务器??? 是的! 你没听错。 真是醉了,多大的集团,为了省钱,也真是拼了, 作为开发人员,没有测试服务器,犹如断臂之人。 所以,在之前搭建环境的时候都没有写文档,今天算是弥补上,以后都可以作为参考了, …...
Jellyfin影音服务本地部署并结合内网穿透实现公网访问本地资源
文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及,各种各样的使用需求也被开发出来&…...
笨蛋学设计模式行为型模式-责任链模式【18】
行为型模式-责任链模式 8.5责任链模式:arrow_up::arrow_up::arrow_up:8.5.1概念8.5.2场景8.5.3优势 / 劣势8.5.4责任链模式可分为8.5.5责任链模式8.5.6实战8.5.6.1题目描述8.5.6.2输入描述8.5.6.3输出描述8.5.6.4代码 8.5.7总结 8.5责任链模式⬆️⬆️⬆️ 8.5.1概念 责任…...
【.NET Core】深入理解任务并行库 (TPL)
【.NET Core】深入理解任务并行库 (TPL) 文章目录 【.NET Core】深入理解任务并行库 (TPL)一、概述二、数据并行(任务并行库)三、Parallel.For 循环示例四、Parallel.ForEach 循环示例五、处理并行循环中的异常六、数据并行总结6.1 不要假定并行的速度始…...
win10安装redis并配置加自启动(采用官方推荐unix子系统)
记录,为啥有msi安装包,还这么麻烦的用linux版本redis的安装方式,是因为从github上下载别人制作的msi报毒,还不止一处,这种链接数据库的东西,用别人加工过的,都报毒了还用就是傻逼了。 所以采用…...
【大数据面试题】HBase面试题附答案
目录 1.介绍下HBase 2.HBase优缺点 3.介绍下的HBase的架构 4.HBase的读写缓存 5.在删除HBase中的一个数据的时候,它是立马就把数据删除掉了吗? 6.HBase中的二级索引 7.HBase的RegionServer宕机以后怎么恢复的? 8.HBase的一个region由哪些东西组成? 9.…...
SpringBoot中从HikariCP迁移到Oracle UCP指南
本博客文章的目标是作为从 HikariCP 和Oracle UCP(通用连接池)迁移的指南,因为它是连接到Oracle 数据库时的推荐方法。 HikariCP 简介 HikariCP是与 Spring Boot 应用程序一起使用的 JDBC 连接池。 简而言之,从 Java 开发人员的…...
第3章 接口和API设计
第15条:用前缀避免命名空间冲突 OC没有其他语言那种内置的命名空间机制。因此,我们在起名时要设法避免潜在的命名冲突,否则很容易就重名了。若是发生重名冲突,那么应用程序相应的链接过程就会出错。例如: 错误原因在…...
HBase入门:实现原理
文章目录 说明HBase的实现原理HBase功能组件表和 RegionRegion 的定位 说明 本文参考自林子雨老师的《大数据技术原理与应用(第三版)》教材内容,仅供学习和交流 HBase的实现原理 HBase功能组件 HBase 的实现包括 3 个主要的功能组件:库函数ÿ…...
Redis入门到实战-基础篇+实战篇+高级篇+原理篇
Redis入门到实战-基础篇实战篇高级篇原理篇 文章目录 Redis入门到实战-基础篇实战篇高级篇原理篇一、基础篇二、实战篇三、高级篇四、原理篇 一、基础篇 1.基础篇笔记:https://blog.csdn.net/cygqtt/article/details/126974142 二、实战篇 1.实战篇笔记:…...
redis 工具类
在Spring Boot项目中,Redis是一个常用的分布式缓存解决方案。下面展示的RedisCache工具类封装了对Redis进行基本操作的方法,包括存储和获取各种类型的数据、设置过期时间以及处理集合类型的缓存。 /*** redis 工具类***/ SuppressWarnings(value { &q…...
焕新升级,不同以“网” | AnyCase客户端全新上线
升级啦~ 2024年1月23日 箱讯AnyCase官网全新改版上线! 全球贸易All in One集成平台 集物流服务、外贸服务、供应链金融服务、企业风控服务、碳中和服务于一体 添加图片注释,不超过 140 字(可选) 优化首页布局→体验升级 此次…...
导出 MySQL 数据库表结构、数据字典word设计文档
一、第一种 :利用sql语句查询 需要说明的是该方法应该适用很多工具,博主用的是navicat SELECT TABLE_NAME 表名,( i : i 1 ) AS 序号,COLUMN_NAME 列名, COLUMN_TYPE 数据类型, DATA_TYPE 字段类型, CHARACTER_MAXIMUM_LENGTH 长度, IS_NULLABLE…...
conda管理python安装包与虚拟环境的相关命令汇总
conda的简单介绍 Anaconda,是一个开源的Python发行版本,包含了conda、Python以及一大堆安装好的工具包及依赖项。 conda是Anaconda中的一个开源的、Python包和环境的管理工具,包含于Anaconda的所有版本当中。因此使用conda需要先安装Anacon…...
Vue3引用echart5 报错解决
一、TypeError: Cannot read properties of undefined (reading type) 原因:由于把echart实例绑定到了一个响应式的变量上 解决方案 【1】使用markRaw 把响应式变量定为非响应式变量 import { markRaw } from vue; export default {data() {return {chartConta…...
浅析HTTP协议
首先,前端请求后端数据,后端响应数据给前端,这是我们大家都知道的,那其中所涉及到的数据传输协议又是什么呢?这个传输规范就是我们大名鼎鼎的HTTP协议! 什么是HTTP协议? HTTP(超文本…...
etcd未授权到控制k8s集群
在安装完 K8s 后,默认会安装 etcd 组件,etcd 是一个高可用的 key-value 数据库,它为 k8s 集群提供底层数据存储,保存了整个集群的状态。大多数情形下,数据库中的内容没有加密,因此如果黑客拿下 etcd&#x…...
制作一个简单的HTML个人网站
在当今数字化的世界里,拥有一个个人网站已经成为了展示个人品牌、分享作品和信息的必备工具。虽然有各种复杂的内容管理系统(CMS)和平台可以帮助我们快速搭建个人网站,但对于初学者或者想要了解更多技术细节的人来说,从…...
网站源码设计/全国人大常委会
Jailer数据文件提取工具是一款简单易用的数据库数据提取程序,通过这款工具,用户可以从数据库中提取任何您所需要的数据,而且还允许分析与删除数据库中过时数据以及一些不需要的数据,从而能够让系统运行更加的流畅以及提升数据库性…...
石湾做网站/百度知道答题赚钱
OSSIM安装注意事项 1.如何选择OSSIM版本 SIEM (安全信息和事件管理)是软件和服务的组合,是安全信息管理和安全事件管理的融合体。SIEM可以管理企业IT资源产生的安全信息(包括日志、告警等)进行统一的实时监控误操作行为进行监控、审计分析、调查取证、出具各种报表报告。OSS…...
盘锦做网站建设的/晚上偷偷看b站软件推荐
一:安装Sublime Text 3插件的方法安装package control组件,然后直接在线安装:1、按Ctrl调出console(注:安装有QQ输入法的这个快捷键会有冲突的。输入法属性设置-输入法管理-取消热键切换至QQ拼音) 2、粘贴下…...
深圳福田网站优化网络营销培训学校/全国疫情最新数据
20145203 《信息安全系统设计基础》第七周学习总结 第六章 存储器层次结构 教材学习内容总结 绪论 存储器系统是一个具有不同容量、成本和访问时间的存储设备的层次结构。 第一节 存储技术 一、随机访问存储器(RAM) RAM分类: ①静态的SRAM-更…...
淘宝做网站/希爱力双效片
第1章:智能音箱行业界定及发展环境剖析1.1 智能音箱行业界定及统计说明 1.1.1 音箱的界定及分类 (1)音箱的定义 (2)音箱主要分类 1.1.2 智能音箱的界定与分类 (1)产品界定 (2&a…...
安平县护栏网站建设/上海外贸seo
1.功能描述:支持对图片中的手写中文、手写数字进行检测和识别,针对不规则的手写字体进行专项优化,识别准确率可达90%以上2.平台接入具体接入方式比较简单,可以参考我的另一个帖子,这里就不重复了:http://ai…...