redis设计规范
部分内容参考:阿里redis开发规范 同时,结合shigen在实习中的实践经验总结。
key的名称设计
可读性和管理性
业务名: 表名: id
pro:user:1001
简洁性
控制key的长度,可以用缩写
transaction -> tras
拒绝bigkey
防止网卡流量、慢查询,string 类型控制在 10KB 以内,hash、list、set、zset 元素个数不要超过 5000
非字符串的 bigkey,不要使用 del 删除,使用 hscan、sscan、zscan 方式渐进式删除,同时要注意防止 bigkey 过期时间自动删除问题 (例如一个 200 万的 zset 设置 1 小时过期,会触发 del 操作,造成阻塞,而且该操作不会不出现在慢查询中 (latency 可查)),查找方法和删除方法
选择合适的数据类型
| 数据结构 | 描述 | 常用场景 |
|---|---|---|
| String | 字符串类型,可存储文本或二进制数据 | 缓存、计数器、分布式锁等 |
| Hash | 键值对的无序集合 | 存储对象、缓存、配置信息等 |
| List | 有序的字符串元素集合 | 消息队列、最新消息获取、粉丝列表等 |
| Set | 无序且唯一的字符串元素集合 | 标签系统、好友关系、集合操作等 |
| Sorted Set | 有序的字符串元素集合,每个元素关联一个分数 | 排行榜、范围查询、优先级队列等 |
| Bitmap | 位数组,可进行位级别的操作 | 用户在线状态、统计活跃用户等 |
| HyperLogLog | 基数估计算法,用于统计唯一元素的数量 | 网站UV统计、独立用户计数等 |
| Geospatial | 地理空间位置(经纬度)与元素之间的映射关系 | 地理位置查询、附近的人等 |
| Pub/Sub | 发布者/订阅者模式,用于实现消息发布和订阅机制 | 实时消息通知、事件驱动等 |
| Streams | 类似于日志的有序消息流 | 消息队列、事件溯源、实时分析等 |
控制key的生命周期
防止key集中过期-> 缓存雪崩
命令的使用
1、O(N) 命令关注 N 的数量
例如 hgetall、lrange、smembers、zrange、sinter 等并非不能使用,但是需要明确 N 的值。有遍历的需求可以使用 hscan、sscan、zscan 代替。
ZSCAN myset 0 MATCH prefix:* COUNT 10
2、禁用命令
禁止线上使用 keys、flushall、flushdb 等,通过 redis 的 rename 机制禁掉命令,或者使用 scan 的方式渐进式处理。
scan删除keys的shell脚本:
#!/bin/bash# 连接到 Redis 服务器
REDIS_CLI="/path/to/redis-cli"
HOST="localhost"
PORT="6379"
DB="0"# 定义删除操作函数
delete_all_keys() {# 初始化游标cursor="0"while true; do# 执行 SCAN 命令response="$($REDIS_CLI -h $HOST -p $PORT -n $DB SCAN $cursor)"# 解析 SCAN 命令的返回值cursor="$(echo "$response" | head -n 1)"keys="$(echo "$response" | tail -n +2)"# 删除当前页的所有键for key in $keys; do$REDIS_CLI -h $HOST -p $PORT -n $DB DEL "$key"done# 如果已经迭代完成了所有键if [ "$cursor" == "0" ]; thenbreakfidone
}# 调用删除操作函数
delete_all_keys
3、合理使用 select
redis 的多数据库较弱,使用数字进行区分,很多客户端支持较差,同时多业务用多数据库实际还是单线程处理,会有干扰。
4、使用批量操作提高效率
- 原生命令:例如 mget、mset。
- 非原生命令:可以使用 pipeline 提高效率。
但要注意控制一次批量操作的元素个数 (例如 500 以内,实际也和元素字节数有关)。
注意两者不同:
- 原生是原子操作,pipeline 是非原子操作
- pipeline 可以打包不同的命令,原生做不到
- pipeline 需要客户端和服务端同时支持
5、不建议过多使用 Redis 事务功能
Redis 的事务功能较弱 (不支持回滚),而且集群版本(自研和官方) 要求一次事务操作的 key 必须在一个 slot 上(可以使用 hashtag 功能解决)
官方:redis设计成单线程,就是为了提升效率
6、Redis 集群版本在使用 Lua 上有特殊要求
1、所有 key 都应该由 KEYS 数组来传递,redis.call/pcall 里面调用的 redis 命令,key 的位置,必须是 KEYS array, 否则直接返回 error,“-ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS arrayrn”
2、所有 key,必须在 1 个 slot 上,否则直接返回 error, “-ERR eval/evalsha command keys must in same slotrn”
7、monitor 命令
必要情况下使用 monitor 命令时,要注意不要长时间使用。
客户端的使用
避免多个应用使用一个redis实例
不想干的业务拆分,公共数据做服务化
使用连接池
有效的控制链接、提高效率,shigen在之前的文章中也分享过
合理的加密
redis密码的设置
淘汰策略
根据自身业务类型,选好 maxmemory-policy(最大内存淘汰策略),设置好过期时间。
默认策略是 volatile-lru,即超过最大内存后,在过期键中使用 lru 算法进行 key 的剔除,保证不过期数据不被删除,但是可能会出现 OOM 问题。
其他策略如下:
- allkeys-lru:根据 LRU 算法删除键,不管数据有没有设置超时属性,直到腾出足够空间为止。
- allkeys-random:随机删除所有键,直到腾出足够空间为止。
- volatile-random: 随机删除过期键,直到腾出足够空间为止。
- volatile-ttl:根据键值对象的 ttl 属性,删除最近将要过期数据。如果没有,回退到 noeviction 策略。
- noeviction:不会剔除任何数据,拒绝所有写入操作并返回客户端错误信息 “(error) OOM command not allowed when used memory”,此时 Redis 只响应读操作。
相关工具
删除 bigkey
案例中展示的是java的操作,可以根据实际的情况改写成shell或python脚本
1、Hash 删除: hscan + hdel
public void delBigHash(String host, int port, String password, String bigHashKey) {Jedis jedis = new Jedis(host, port);if (password != null && !"".equals(password)) {jedis.auth(password);}ScanParams scanParams = new ScanParams().count(100);String cursor = "0";do {ScanResult<Entry<String, String>> scanResult = jedis.hscan(bigHashKey, cursor, scanParams);List<Entry<String, String>> entryList = scanResult.getResult();if (entryList != null && !entryList.isEmpty()) {for (Entry<String, String> entry : entryList) {jedis.hdel(bigHashKey, entry.getKey());}}cursor = scanResult.getStringCursor();} while (!"0".equals(cursor));//删除bigkeyjedis.del(bigHashKey);
}
2、List 删除: ltrim
public void delBigList(String host, int port, String password, String bigListKey) {Jedis jedis = new Jedis(host, port);if (password != null && !"".equals(password)) {jedis.auth(password);}long llen = jedis.llen(bigListKey);int counter = 0;int left = 100;while (counter < llen) {//每次从左侧截掉100个jedis.ltrim(bigListKey, left, llen);counter += left;}//最终删除keyjedis.del(bigListKey);
}
3、Set 删除: sscan + srem
public void delBigSet(String host, int port, String password, String bigSetKey) {Jedis jedis = new Jedis(host, port);if (password != null && !"".equals(password)) {jedis.auth(password);}ScanParams scanParams = new ScanParams().count(100);String cursor = "0";do {ScanResult<String> scanResult = jedis.sscan(bigSetKey, cursor, scanParams);List<String> memberList = scanResult.getResult();if (memberList != null && !memberList.isEmpty()) {for (String member : memberList) {jedis.srem(bigSetKey, member);}}cursor = scanResult.getStringCursor();} while (!"0".equals(cursor));//删除bigkeyjedis.del(bigSetKey);
}
4、SortedSet 删除: zscan + zrem
public void delBigZset(String host, int port, String password, String bigZsetKey) {Jedis jedis = new Jedis(host, port);if (password != null && !"".equals(password)) {jedis.auth(password);}ScanParams scanParams = new ScanParams().count(100);String cursor = "0";do {ScanResult<Tuple> scanResult = jedis.zscan(bigZsetKey, cursor, scanParams);List<Tuple> tupleList = scanResult.getResult();if (tupleList != null && !tupleList.isEmpty()) {for (Tuple tuple : tupleList) {jedis.zrem(bigZsetKey, tuple.getElement());}}cursor = scanResult.getStringCursor();} while (!"0".equals(cursor));//删除bigkeyjedis.del(bigZsetKey);
}
相关文章:
redis设计规范
部分内容参考:阿里redis开发规范 同时,结合shigen在实习中的实践经验总结。 key的名称设计 可读性和管理性 业务名: 表名: id pro:user:1001简洁性 控制key的长度,可以用缩写 transaction -> tras拒绝bigkey 防止网卡流量、慢查询&…...
用于非线性多载波卫星信道的多输入多输出符号速率信号数字预失真器DPD(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
【Spark】用udf和withColumn在dafaframe中创建新列
udf使用 import org.apache.spark.sql.functions.udf udf接收一个函数(func)作为参数,返回一个UserDefinedFunction。 UserDefinedFunction接收列(Column)作为参数,并返回Column. func可以接收普通类型参数…...
AIGC 设计能替代真正的设计师设计吗?
AIGC 设计能替代真正的设计师设计吗? 目录 一、写在前面的话 二、AIGC 设计能替代真正的设计师吗? 1.1、传统设计师设计 1.2、AIGC设计 1.3、相关概念 1.4、观点分析 (1)、审美角度 (2)、版权角度 …...
【1++的C++进阶】之emplace详解
👍作者主页:进击的1 🤩 专栏链接:【1的C进阶】 在前面C11系列的文章里,我们漏掉了几个知识点,这篇文章对其中一个知识点进行讲解,关于剩余的知识点的文章在后面会相继出炉。 C11中,针…...
React入门
一、react开始 1、react是什么 用于构建用户界面的JavaScript库 操作DOM呈现页面 (发送请求获取数据和处理数据不由react处理)fessbook开发 2、为什么要学 原生js操作DOM繁琐、效率低 使用原生js直接操作DOM,浏览器会进行大量重绘重排 原…...
第三方登录以及验证
第三方登录是指用户可以通过使用已有的第三方账号进行登录,而无需再次注册新的账号。常见的第三方登录平台包括微信、QQ、微博、GitHub等。 验证是指系统需要验证用户提供的信息是否正确,以确保用户可以登录系统。验证方式包括密码验证、手机号验证、邮…...
MS SQL Server问题汇总
1.报SQL Server Agent连接不上的错误 15:38:57.991 [debezium-sqlserverconnector-sqlserver_transaction_log_source-change-event-source-coordinator] WARN i.d.connector.sqlserver.SqlServerStreamingChangeEventSource - No maximum LSN recorded in the database; pl…...
在线海报图片设计器、图片编辑器源码/仿照稿定设计源码
在线海报设计系统素材设计源码是一个漂亮且功能强大的在线海报图片设计器,仿照稿定设计而成。该系统适用于多种场景,包括海报图片生成、电商分享图、文章长图、视频/公众号封面等。用户无需下载软件,即可轻松实现创意,迅速完成排版…...
KMP算法(C++)
KMP算法与BF算法不一样的在于,当主串与子串不匹配时,主串不回溯,选择了子串回溯,大大提高了运算效率。 借用了next1【】数组,让子串回溯。get_next函数求next1【】数组,get_next函数的实现难点在于下列几行…...
C++的异常类型与多级catch匹配
try-catch 的用法: try{// 可能抛出异常的语句 }catch(exceptionType variable){// 处理异常的语句 } 我们还遗留下一个问题,就是 catch 关键字后边的exceptionType variable,这节就来详细分析一下。exceptionType是异常类型,它指明了当前的 catch 可以处理什么类型的异常…...
查询IP地址可得到哪些信息
通过IP地址定位,可以获取一些基本的信息,包括以下内容: 1. 地理位置:你可以确定IP地址所在的地理位置,包括国家、州或省、城市和地理坐标。这通常是通过将IP地址与地理位置数据库进行匹配来实现的。 2. ISPÿ…...
考研算法47天:01背包
问题描述 算法详细步骤 代码随想录 (programmercarl.com) ac代码 #include <iostream> using namespace std; int bag[1001]; int bagMax[1001]; int bagvalue[1001]; int main(){int n,v;cin>>n>>v;for(int i0;i<n;i){cin>>bag[i]>>bagva…...
Docker实战技巧(一):Kubernetes基础操作实战
Kubernetes定位在Saas层,重点解决了微服务大规模部署时的服务编排问题 1、关闭防火墙并设置开机禁用 systemctl stop firewalld systemctl disable firewalld 2、配置repo cd /etc/yum.repos.d/ 下载Docker repo wget https://mirrors.aliyun.com/docker-…...
android java读写yaml文件
目录 申请读写权限: build.gradle中添加库引用: android java读写yaml文件 java修改yaml文件 YamlFile: 修改yaml文件方法2 Yaml: 删除值: 申请读写权限: <uses-permission android:name"and…...
科学计算器网站Desmos网站
科学计算器网站Desmos网站 有时在学习工作或者生活中,需要用到计算问题,但由于电脑上没有安装相应的专业软件,难以计算有的问题,因而,本文推荐一种免费的在线计算网站Desmos。 一、Desmos网址 Desmos官网的地址为&a…...
结构体-时间的计算
任务描述 本关任务需要你编写函数计算一个时间之前“xx小时xx分xx秒”的时间是多少。 以24小时制的格式记录当前时间,譬如“09:19:52”,表示上午9点19分52秒,则“1小时20分30秒”前的时间应该是“同一天”的“07:59:22”。 提示:…...
pt24django教程
静态文件访问 不能与服务器端做动态交互的文件都是静态文件,如: 图片,css,js,音频,视频,html文件(部分) 静态文件配置 在 settings.py 中配置一下两项内容: STATIC_URL 静态文件的访问路径,通过哪个url地址找静态文件 ,STATIC_URL ‘/s…...
Golang开发-new关键字
在Go语言中,new关键字用于创建一个新的零值对象,并返回指向该对象的指针。它是Go语言中用于分配内存的一种方式。 new关键字的语法如下: ptr : new(Type)其中,Type表示要创建的对象的类型,ptr是指向新对象的指针。 …...
遗传算法与粒子群算法的Python实现
遗传算法本文应用的是 python geatpy module粒子群算法本文应用的是 python pyswarm module 遗传算法 它的不等约束是...<0 import geatpy as ea import numpy as npea.Problem.single def evalVars(Vars): x1 Vars[0]x2 Vars[1]x3 Vars[2]x4 Vars[3]f (x1 2)**2 \…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...
Java后端检查空条件查询
通过抛出运行异常:throw new RuntimeException("请输入查询条件!");BranchWarehouseServiceImpl.java // 查询试剂交易(入库/出库)记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...
网页端 js 读取发票里的二维码信息(图片和PDF格式)
起因 为了实现在报销流程中,发票不能重用的限制,发票上传后,希望能读出发票号,并记录发票号已用,下次不再可用于报销。 基于上面的需求,研究了OCR 的方式和读PDF的方式,实际是可行的ÿ…...
