点击上方“蓝字”关注我们

本文转载自公众号“Java 高效学习”(ID: coder_love),原文链接

本文主要介绍在使用阿里云 Redis 的开发规范,从下面几个方面进行说明。

  • 键值设计

  • 命令使用

  • 客户端使用

  • 相关工具

通过本文的介绍可以减少使用 Redis 过程带来的问题。

一、键值设计

1、key 名设计

可读性和可管理性

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

ugc:video:1

简洁性

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

user:{uid}:friends:messages:{mid}简化为u:{uid}:fr:m:{mid}。

不要包含特殊字符

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

2、value 设计

拒绝 bigkey

防止网卡流量、慢查询,string 类型控制在 10KB 以内,hash、list、set、zset 元素个数不要超过 5000。

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

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

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

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

正例:

hmset user:1 name tom age =19 favor football

控制 key 的生命周期

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

二、命令使用

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 以内,实际也和元素字节数有关)。

注意两者不同:

  • 原生是原子操作,pipeline 是非原子操作。

  • pipeline 可以打包不同的命令,原生做不到

  • 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 arrayrn"

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

7、monitor 命令

必要情况下使用 monitor 命令时,要注意不要长时间使用。

三、客户端使用

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();}

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

下面操作可以使用 pipeline 加速。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> scanResult = jedis.hscan(bigHashKey, cursor, scanParams); List> entryList = scanResult.getResult(); if (entryList != null && !entryList.isEmpty()) { for (Entry 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 scanResult = jedis.sscan(bigSetKey, cursor, scanParams); List 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 scanResult = jedis.zscan(bigZsetKey, cursor, scanParams); List 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);}

 

猜你喜欢  

多目标跟踪算法解读无法登录的用户 | 一次问题排查过程超详细干货!Martin Fowler 解读源代码分支管理模式(下)超详细干货!Martin Fowler 万字解读源代码分支管理模式(上)

觉得不错,点个在看

redis 转义字符_阿里巴巴官方最新 Redis 开发规范相关推荐

  1. 最新版本Redis:Redis 7.0 安装使用,Docke启动Redis,Redis使用场景-2022年最新Redis图解安装

    最新版本Redis:Redis 7.0 安装使用,Docker安装Redis,Redis使用场景-2022年最新Redis图解安装 Redis 镜像版本地址:Docker Hub #拉取redis 7 ...

  2. redis 转义字符_一份完整的阿里云 Redis 开发规范,值得收藏!

    来源:yq.aliyun.com/articles/531067 本文主要介绍在使用阿里云Redis的开发规范,从下面几个方面进行说明. 键值设计 命令使用 客户端使用 相关工具 通过本文的介绍可以减 ...

  3. docker redis 配置文件_基于Docker搭建Redis一主两从三哨兵

    点击上方"Java知音",选择"置顶公众号" 技术文章第一时间送达! 作者:oscarwin juejin.im/post/5d26b03de51d454fa3 ...

  4. redis日志_为什么我的Redis这么“慢”?

    Redis 作为内存数据库,拥有非常高的性能,单个实例的 QPS 能够达到 10W 左右. 图片来自 Pexels 但我们在使用 Redis 时,经常时不时会出现访问延迟很大的情况,如果你不知道 Re ...

  5. Redis概述_使用命令对redis的数据进行增删改查_Jedis连接redis进行数据操作_redis进行数据缓存案例

    学习目标 redis 概念 下载安装 命令操作 1. 数据结构 持久化操作 使用Java客户端操作redis Redis 前言(从百度上抄的, 看看了解一下, 懒得排版了) 1. 概念: redis是 ...

  6. python redis 操作_使用Python操作redis

    在使用python操作redis之前,需要先安装redis库: pip install redis. 创建连接方式: StrictRedis:实现大部分官方命令. Redis:是StrictRedis ...

  7. key redis 遍历_快乐运维Redis大数据量查询与清理

    一. keys命令(生产环境禁止使用) 简单粗暴,由于Redis单线程这一特性,keys命令是以阻塞的方式执行的,keys是以遍历的方式实现的复杂度是 O(n),Redis库中的key越多,查找实现代 ...

  8. redis日志_面试题之Redis如何保证系统宕机数据不会丢失?

    我们都知道 Redis 的数据全部在内存里,如果突然宕机,数据就会全部丢失,因此必须有一种机制来保证 Redis 的数据不会因为故障而丢失,这种机制就是 Redis 的持久化机制. Redis 有两种 ...

  9. Redis学习_第六章(Redis面试、进阶知识点)

    目录 1:redis的数据类型和使用特点 2:redis实现分布式锁 3:如何保证redis的数据都是热点数据 4:redis数据的过期策略(懒汉模式和定期模式100毫秒) 5:redis的缓存穿透( ...

最新文章

  1. 关于学习Python的一点学习总结(30->递归实例)
  2. 业务处理速度变慢?且看IT如何成为救世主
  3. Problem F. Grab The Tree博弈
  4. python可以做什么工作-Python可以做什么工作?Python有哪些方向?
  5. 电烤箱计算机控制系统,台式电烤箱及其控制系统 Desktop oven and control system
  6. 免费分享全套java学习资料
  7. 知网查重报告html乱码,知网查重报告乱码如何解决?
  8. javaweb区分PC端和移动端
  9. python row函数_Python extmath.row_norms方法代码示例
  10. python的help()
  11. [SRM603] WinterAndSnowmen
  12. Linux笔记整理(1)系统的加载和main函数执行准备
  13. win10更新后任务栏卡死 的原因和解决办法
  14. 非线性规划的拉格朗日乘子法python编程python包编程
  15. PAT A1066 Root of AVL Tree ——春水碧于天,画船听雨眠
  16. python 点击按钮 click_selenium+Python(Js处理click失效)
  17. 火狐浏览器如何设置默认打开网页
  18. 测井等数据的噪声处理及图例
  19. 双系统ubuntu+ros indigo安装
  20. 优化大师修复IE右键

热门文章

  1. MySQL中的locate函数
  2. JS保证输入框里面的数值是数字
  3. MySQL建表时Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP
  4. delphi adoquery 上一个下一个_从一个起点冲向下一个起点
  5. mysql status uptime_MySQL优化(四) 慢查询的定位及优化
  6. java计算两个时间段的重合天数
  7. word度量单位无效_ABBYY FineReader 12的具体使用方法和word排版设置
  8. MySQL的SQL预处理(Prepared)
  9. vue ---- webpack -插件 html-webpack-plugin
  10. JavaSE----变量、String、运算符、流程控制