Redis 开发规范

news2024/11/17 0:56:47
  • 原创 | Java 2021 超神之路,很肝~

  • 中文详细注释的开源项目

  • RPC 框架 Dubbo 源码解析

  • 网络应用框架 Netty 源码解析

  • 消息中间件 RocketMQ 源码解析

  • 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析

  • 作业调度中间件 Elastic-Job 源码解析

  • 分布式事务中间件 TCC-Transaction 源码解析

  • Eureka 和 Hystrix 源码解析

  • Java 并发源码

  • 一、键值设计

  • 二、命令使用

  • 三、客户端使用

  • 四、相关工具

  • 五 附录:删除bigkey


一、键值设计

1. key名设计

  • (1)【建议】: 可读性和可管理性

以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id

ugc:video:1
  • (2)【建议】:简洁性

保证语义的前提下,控制key的长度,当key较多时,内存占用也不容忽视,例如:

user:{uid}:friends:messages:{mid}简化为u:{uid}:fr:m:{mid}。
  • (3)【强制】:不要包含特殊字符

反例:包含空格、换行、单双引号以及其他转义字符

2. value设计

  • (1)【强制】:拒绝bigkey(防止网卡流量、慢查询)

string类型控制在10KB以内,hash、list、set、zset元素个数不要超过5000。

反例:一个包含200万个元素的list。

非字符串的bigkey,不要使用del删除,使用hscan、sscan、zscan方式渐进式删除,同时要注意防止bigkey过期时间自动删除问题(例如一个200万的zset设置1小时过期,会触发del操作,造成阻塞,而且该操作不会不出现在慢查询中(latency可查)),查找方法和删除方法

  • (2)【推荐】:选择适合的数据类型。

例如:实体类型(要合理控制和使用数据结构内存编码优化配置,例如ziplist,但也要注意节省内存和性能之间的平衡)

反例:

set user:1:name tomset user:1:age 19set user:1:favor football

正例:

hmset user:1 name tom age 19 favor football

3.【推荐】:控制key的生命周期,redis不是垃圾桶。

建议使用expire设置过期时间(条件允许可以打散过期时间,防止集中过期),不过期的数据重点关注idletime。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址: https://gitee.com/zhijiantianya/ruoyi-vue-pro
视频教程: https://doc.iocoder.cn/video/

二、命令使用

1.【推荐】 O(N)命令关注N的数量

例如hgetall、lrange、smembers、zrange、sinter等并非不能使用,但是需要明确N的值。有遍历的需求可以使用hscan、sscan、zscan代替。

2.【推荐】:禁用命令

禁止线上使用keys、flushall、flushdb等,通过redis的rename机制禁掉命令,或者使用scan的方式渐进式处理。

3.【推荐】合理使用select

redis的多数据库较弱,使用数字进行区分,很多客户端支持较差,同时多业务用多数据库实际还是单线程处理,会有干扰。

4.【推荐】使用批量操作提高效率

原生命令:例如mget、mset。非原生命令:可以使用pipeline提高效率。

但要注意控制一次批量操作的元素个数 (例如500以内,实际也和元素字节数有关)。

注意两者不同:

1. 原生是原子操作,pipeline是非原子操作。2. pipeline可以打包不同的命令,原生做不到3. pipeline需要客户端和服务端同时支持。

5.【建议】Redis事务功能较弱,不建议过多使用

Redis的事务功能较弱(不支持回滚),而且集群版本(自研和官方)要求一次事务操作的key必须在一个slot上(可以使用hashtag功能解决)

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 array"

  • 2.所有key,必须在1个slot上,否则直接返回error, "-ERR eval/evalsha command keys must in same slot"

7.【建议】必要情况下使用monitor命令时,要注意不要长时间使用。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址: https://gitee.com/zhijiantianya/yudao-cloud
视频教程: https://doc.iocoder.cn/video/

三、客户端使用

1.【推荐】

避免多个应用使用一个Redis实例

正例:不相干的业务拆分,公共数据做服务化。

2.【推荐】

使用带有连接池的数据库,可以有效控制连接,同时提高效率,标准使用方式:

执行命令如下:
Jedis jedis = null;
try {
    jedis = jedisPool.getResource();
    //具体的命令
    jedis.executeCommand()
} catch (Exception e) {
    logger.error("op key {} error: " + e.getMessage(), key, e);
} finally {
    //注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。
    if (jedis != null)
        jedis.close();
}

下面是JedisPool优化方法的文章:

  • Jedis常见异常汇总

  • JedisPool资源池优化

3.【建议】

高并发下建议客户端添加熔断功能(例如netflix hystrix)

4.【推荐】

设置合理的密码,如有必要可以使用SSL加密访问(阿里云Redis支持)

5.【建议】

根据自身业务类型,选好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只响应读操作。

四、相关工具

1.【推荐】:数据同步

redis间数据同步可以使用:redis-port

2.【推荐】:big key搜索

redis大key搜索工具

3.【推荐】:热点key寻找(内部实现使用monitor,所以建议短时间使用)

facebook的redis-faina

阿里云Redis已经在内核层面解决热点key问题,欢迎使用。

五 附录:删除bigkey

1. 下面操作可以使用pipeline加速。2. redis 4.0已经支持key的异步删除,欢迎使用。

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));    //删除bigkey    jedis.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;    }    //最终删除key    jedis.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));    //删除bigkey    jedis.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));    //删除bigkey    jedis.del(bigZsetKey);}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/351370.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

详细总结Ansible中使用playbook

文章目录前言一、Playbook的功能二、YAML三、playbook执行命令1.使用ansible-playbook部署ftp服务&#xff0c;并开启匿名用户访问权利2.使用ansible-playbook部署apache服务&#xff0c;设定默认发布文件内容为www.westos.org3.tags&#xff1a;标签四、使用vim解决yaml书写格…

使用git中可能出现的问题

问题1&#xff1a;如果遇到自己的文件在远程仓库dev分支被别人修改了&#xff0c;自己在本地仓库test分支继续在写代码先拉取最新的代码 覆盖本地dev分支 TortoiseGit->Pull被修改如图2.拉取最新的代码(拉取成功后 本地dev分支user有四条属性)3.切换到自己的分支tortoiseGit…

C++009-C++循环结构while

文章目录C009-C循环结构whilewhile循环while循环举例题目描述 对折多少次能超过nmm题目描述 输入整数和超过n题目描述 输入若干个大写字母&#xff0c;输出对应的小写字母题目描述 输入整数&#xff0c;逆序输出作业在线练习&#xff1a;总结C009-C循环结构while 在线练习&…

模型转换 PyTorch转ONNX 入门

前言 本文主要介绍如何将PyTorch模型转换为ONNX模型&#xff0c;为后面的模型部署做准备。转换后的xxx.onnx模型&#xff0c;进行加载和测试。最后介绍使用Netron&#xff0c;可视化ONNX模型&#xff0c;看一下网络结构&#xff1b;查看使用了那些算子&#xff0c;以便开发部署…

计算机网络第1章(概述)学习笔记

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

PPS文件如何转换成PPT?附两种方法

在工作中&#xff0c;PPS文件的使用还是很广泛的&#xff0c;因为作为幻灯片放映文件&#xff0c;点击后就能直接播放&#xff0c;十分方便。但如果想要修改PPS里的内容&#xff0c;PPS是无法编辑的&#xff0c;我们需要把文件转换成PPT&#xff0c;再进行修改。 那PPS文件如何…

详细解读ChatGPT:如何调用ChatGPT的API接口到官方例子的说明以及GitHub上的源码应用和csdn集成的ChatGPT

文章目录1. 解读ChatGPT1.1 词语解释1.2 功能解读2. GitHub上ChatGPT的应用源码3. 调用ChatGPT的API4. 官方例子说明5. 集成ChatGPT自ChatGPT出来到如今&#xff0c;始终走在火热的道路上&#xff0c;如今日活用户破亿&#xff0c;他为何有如此大的魅力&#xff0c;深受广大用户…

通用 GPU 领先企业登临科技加入龙蜥社区,完成与龙蜥操作系统的兼容适配

近日&#xff0c;上海登临科技有限公司&#xff08;以下简称“登临科技”&#xff09;签署了 CLA&#xff08;Contributor License Agreement&#xff0c;贡献者许可协议&#xff09;&#xff0c;正式加入龙蜥社区&#xff08;OpenAnolis&#xff09;。作为国内通用 GPU 领先企…

深入浅出带你学习GlassFish中间件漏洞

前文 上文给大家带来了WEBLOGIC常见的漏洞不知道大家理解了没有&#xff0c;今天给大家带来一个新的中间件漏洞的讲解——glassfish&#xff0c;本文会先介绍该中间件的简单信息然后解析一下该中间件可能存在的漏洞类型&#xff0c;下面我们展开文章来讲。 GlassFish GlassF…

2023美国大学生数学建模竞赛E题思路解析

背景&#xff1a;光污染是指任何过多或不当使用人造光的表现。我们所称为光污染的一些现象包括光侵入、过亮、以及光混乱。这些现象最容易在大城市太阳落山后观察到天空中的发光&#xff1b;然而&#xff0c;它们也可能发生在更偏远的地区。光污染改变了我们对夜空的看法&#…

(三十四)Vue之新生命周期钩子nextTick

文章目录普通实现的一个问题解决问题nextTick上一篇&#xff1a;&#xff08;三十三&#xff09;Vue之消息订阅与发布 首先先看这一个需求&#xff0c;给每个任务项新增一个编辑按钮 当编辑按钮点击时&#xff0c;任务项就会变成文本框&#xff0c;并且自动获取焦点 普通实…

中国天气——对流性天气过程复习笔记

对流性天气过程 对流性天气十分激烈&#xff0c;影响范围相对较小&#xff0c;持续时间短&#xff0c;通常是局部灾害性天气 雷暴结构 产生雷暴的积雨云叫雷暴云&#xff0c;也叫雷暴单体&#xff0c;水平尺度约为十几千米多个雷暴单体成群聚集在一起叫做雷暴群&#xff0c;…

【C语言】数组的声明和使用(一维数组、多维数组)

数组一、什么是数组&#xff1f;二、一维数组&#xff08;一&#xff09;一维数组声明&#xff08;二&#xff09;一维数组初始化&#xff08;三&#xff09;一维数组的引用三、多维数组&#xff08;以二维数组为例&#xff09;&#xff08;一&#xff09;二维数组声明&#xf…

PyQt5数据库开发1 4.3 QSqlTableModel 之 Qt项目的创建

目录 一、新建Qt项目 1. 编辑资源文件 2. 添加前缀 3. 新建放资源文件的目录 4. 添加图标文件 二、Action 1. 新建打开数据库Action 2. 添加其他Action 三、工具栏 1. 添加工具栏 2. 拖动actOpenDB到工具栏 3. 设置工具栏属性 4. 添加分隔符 5. 添加其他工具 6.…

精选案例 |《金融电子化》:光大银行云原生背景下的运维监控体系建设

顺应“十四五”规划中关于“加快金融机构数字化转型”要求&#xff0c;中国人民银行印发了《金融科技发展规划&#xff08;2022-2025年&#xff09;》。近几年来&#xff0c;金融行业牢牢占据着国内产业数字化转型市场投入的榜首位置。IDC调查显示&#xff0c;2022上半年&#…

北斗卫星信号类型及卫星颗数

文章目录一、北斗系统现阶段提供的公开服务信号二、北斗二号、三号卫星个数三、GNSS模块中的北斗信号参考来源这篇博客主要是整理一下北斗卫星现阶段提供的公开服务信号、二号和三号卫星个数&#xff0c;以及简单看看市场的GNSS模块对北斗信号的支持情况。一、北斗系统现阶段提…

智云通CRM:引起流单的三个问题,你了解了吗?

销售人员一般都会了解基本的销售流程&#xff0c;但是为什么还是出现了各种流单的问题&#xff1f;智云通CRM总结以下三个问题&#xff1a; 第一&#xff0c;采购流程是会发生反复的&#xff0c;不会一直向下走。 从整体上看&#xff0c;客户的采购流程遵循着上述规律&#x…

C++ 修改防火墙firewall设置(Windows)

文章目录1、简介1.1 防火墙概述1.2 入站&#xff0c;还是出站&#xff1f;1.3 防火墙规则优先级2、系统界面方式3、命令行方式3.1 防火墙基本状态设置3.2 入站出站规则设置3.3 其他设置3.4 telnet检测端口4、C方式4.1 注册表4.2 COM&#xff08;Windows XP&#xff09;4.3 COM&…

深度学习模型概念

Big data features: 5V--volume, velocity, variety, value, veracity.Big data challenges&#xff1a;高维、multi-modal、complexity、privacy 1. Federated Learning 联邦学习 Federated Learning&#xff1a;Server将model分散到各个用户user&#xff0c;clients利用本地…

不同相机之间图片像素对应关系求解(单应性矩阵求解)

一、场景 相机1和相机2相对位置不变&#xff0c;相机拍摄图片有重叠&#xff0c;求他们交叠部分的一一对应关系。数学语言描述为已知相机1图片中P点像素(u1, v1)&#xff0c;相机1中P点在相机2图片中像素值为(u2, v2)&#xff0c;它们存在某种变换&#xff0c;求变换矩阵。 因为…