阿里云Redis开发规范

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

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

<span class="hljs-selector-tag">ugc<span class="hljs-selector-pseudo">:video<span class="hljs-selector-pseudo">:1</span></span></span>
  • (2)【建议】:简洁性

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

<span class="hljs-symbol">user:{uid}<span class="hljs-symbol">:friends<span class="hljs-symbol">:messages<span class="hljs-symbol">:{mid}&#x7B80;&#x5316;&#x4E3A;<span class="hljs-symbol">u:{uid}<span class="hljs-symbol">:fr<span class="hljs-symbol">:m<span class="hljs-symbol">:{mid}&#x3002;</span></span></span></span></span></span></span></span>
  • (3)【强制】:不要包含特殊字符

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

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

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

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

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

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

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

反例:

<span class="hljs-keyword">set <span class="hljs-keyword">user:<span class="hljs-number">1:<span class="hljs-keyword">name tom
<span class="hljs-keyword">set <span class="hljs-keyword">user:<span class="hljs-number">1:age <span class="hljs-number">19
<span class="hljs-keyword">set <span class="hljs-keyword">user:<span class="hljs-number">1:favor football</span></span></span></span></span></span></span></span></span></span></span>

正例:

<span class="hljs-selector-tag">hmset <span class="hljs-selector-tag">user<span class="hljs-selector-pseudo">:1 <span class="hljs-selector-tag">name <span class="hljs-selector-tag">tom <span class="hljs-selector-tag">age 19 <span class="hljs-selector-tag">favor <span class="hljs-selector-tag">football</span></span></span></span></span></span></span></span>

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

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

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

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

&#x539F;&#x751F;&#x547D;&#x4EE4;&#xFF1A;&#x4F8B;&#x5982;mget&#x3001;mset&#x3002;
&#x975E;&#x539F;&#x751F;&#x547D;&#x4EE4;&#xFF1A;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;pipeline&#x63D0;&#x9AD8;&#x6548;&#x7387;&#x3002;

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

注意两者不同:

<span class="hljs-bullet">1. &#x539F;&#x751F;&#x662F;&#x539F;&#x5B50;&#x64CD;&#x4F5C;&#xFF0C;pipeline&#x662F;&#x975E;&#x539F;&#x5B50;&#x64CD;&#x4F5C;&#x3002;
<span class="hljs-bullet">2. pipeline&#x53EF;&#x4EE5;&#x6253;&#x5305;&#x4E0D;&#x540C;&#x7684;&#x547D;&#x4EE4;&#xFF0C;&#x539F;&#x751F;&#x505A;&#x4E0D;&#x5230;
<span class="hljs-bullet">3. pipeline&#x9700;&#x8981;&#x5BA2;&#x6237;&#x7AEF;&#x548C;&#x670D;&#x52A1;&#x7AEF;&#x540C;&#x65F6;&#x652F;&#x6301;&#x3002;</span></span></span>

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

  • 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”

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

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

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

&#x6267;&#x884C;&#x547D;&#x4EE4;&#x5982;&#x4E0B;&#xFF1A;
Jedis jedis = <span class="hljs-keyword">null;
<span class="hljs-keyword">try {
    jedis = jedisPool.getResource();
    </span></span>

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

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

设置合理的密码,如有必要可以使用SSL加密访问(阿里云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只响应读操作。

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

&#x963F;&#x91CC;&#x4E91;Redis&#x5DF2;&#x7ECF;&#x5728;&#x5185;&#x6838;&#x5C42;&#x9762;&#x89E3;&#x51B3;&#x70ED;&#x70B9;key&#x95EE;&#x9898;&#xFF0C;&#x6B22;&#x8FCE;&#x4F7F;&#x7528;&#x3002;

五 附录:删除bigkey

<span class="hljs-bullet">1. &#x4E0B;&#x9762;&#x64CD;&#x4F5C;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;pipeline&#x52A0;&#x901F;&#x3002;
<span class="hljs-bullet">2. redis 4.0&#x5DF2;&#x7ECF;&#x652F;&#x6301;key&#x7684;&#x5F02;&#x6B65;&#x5220;&#x9664;&#xFF0C;&#x6B22;&#x8FCE;&#x4F7F;&#x7528;&#x3002;</span></span>
public <span class="hljs-keyword">void delBigHash(<span class="hljs-built_in">String host, int port, <span class="hljs-built_in">String password, <span class="hljs-built_in">String bigHashKey) {
    Jedis jedis = <span class="hljs-keyword">new Jedis(host, port);
    <span class="hljs-keyword">if (password != <span class="hljs-literal">null && !<span class="hljs-string">"".equals(password)) {
        jedis.auth(password);
    }
    ScanParams scanParams = <span class="hljs-keyword">new ScanParams().count(<span class="hljs-number">100);
    <span class="hljs-built_in">String cursor = <span class="hljs-string">"0";
    <span class="hljs-keyword">do {
        ScanResult<entry<<span class="hljs-built_in">String, <span class="hljs-built_in">String>> scanResult = jedis.hscan(bigHashKey, cursor, scanParams);
        List<entry<<span class="hljs-built_in">String, <span class="hljs-built_in">String>> entryList = scanResult.getResult();
        <span class="hljs-keyword">if (entryList != <span class="hljs-literal">null && !entryList.isEmpty()) {
            <span class="hljs-keyword">for (Entry<<span class="hljs-built_in">String, <span class="hljs-built_in">String> entry : entryList) {
                jedis.hdel(bigHashKey, entry.getKey());
            }
        }
        cursor = scanResult.getStringCursor();
    } <span class="hljs-keyword">while (!<span class="hljs-string">"0".equals(cursor));

    </span></span></span></span></span></span></span></span></entry<<span></span></entry<<span></span></span></span></span></span></span></span></span></span></span></span></span></span>
<span class="hljs-function"><span class="hljs-keyword">public <span class="hljs-keyword">void <span class="hljs-title">delBigList(<span class="hljs-params">String host, <span class="hljs-keyword">int port, String password, String bigListKey) {
    Jedis jedis = <span class="hljs-keyword">new Jedis(host, port);
    <span class="hljs-keyword">if (password != <span class="hljs-literal">null && !<span class="hljs-string">"".equals(password)) {
        jedis.auth(password);
    }
    <span class="hljs-keyword">long llen = jedis.llen(bigListKey);
    <span class="hljs-keyword">int counter = <span class="hljs-number">0;
    <span class="hljs-keyword">int left = <span class="hljs-number">100;
    <span class="hljs-keyword">while (counter < llen) {
        </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
public <span class="hljs-keyword">void delBigSet(<span class="hljs-built_in">String host, int port, <span class="hljs-built_in">String password, <span class="hljs-built_in">String bigSetKey) {
    Jedis jedis = <span class="hljs-keyword">new Jedis(host, port);
    <span class="hljs-keyword">if (password != <span class="hljs-literal">null && !<span class="hljs-string">"".equals(password)) {
        jedis.auth(password);
    }
    ScanParams scanParams = <span class="hljs-keyword">new ScanParams().count(<span class="hljs-number">100);
    <span class="hljs-built_in">String cursor = <span class="hljs-string">"0";
    <span class="hljs-keyword">do {
        ScanResult<<span class="hljs-built_in">String> scanResult = jedis.sscan(bigSetKey, cursor, scanParams);
        List<<span class="hljs-built_in">String> memberList = scanResult.getResult();
        <span class="hljs-keyword">if (memberList != <span class="hljs-literal">null && !memberList.isEmpty()) {
            <span class="hljs-keyword">for (<span class="hljs-built_in">String member : memberList) {
                jedis.srem(bigSetKey, member);
            }
        }
        cursor = scanResult.getStringCursor();
    } <span class="hljs-keyword">while (!<span class="hljs-string">"0".equals(cursor));

    </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
public <span class="hljs-keyword">void delBigZset(<span class="hljs-built_in">String host, int port, <span class="hljs-built_in">String password, <span class="hljs-built_in">String bigZsetKey) {
    Jedis jedis = <span class="hljs-keyword">new Jedis(host, port);
    <span class="hljs-keyword">if (password != <span class="hljs-literal">null && !<span class="hljs-string">"".equals(password)) {
        jedis.auth(password);
    }
    ScanParams scanParams = <span class="hljs-keyword">new ScanParams().count(<span class="hljs-number">100);
    <span class="hljs-built_in">String cursor = <span class="hljs-string">"0";
    <span class="hljs-keyword">do {
        ScanResult<tuple> scanResult = jedis.zscan(bigZsetKey, cursor, scanParams);
        List<tuple> tupleList = scanResult.getResult();
        <span class="hljs-keyword">if (tupleList != <span class="hljs-literal">null && !tupleList.isEmpty()) {
            <span class="hljs-keyword">for (Tuple tuple : tupleList) {
                jedis.zrem(bigZsetKey, tuple.getElement());
            }
        }
        cursor = scanResult.getStringCursor();
    } <span class="hljs-keyword">while (!<span class="hljs-string">"0".equals(cursor));

    </span></span></span></span></span></tuple></tuple></span></span></span></span></span></span></span></span></span></span></span></span></span>

Original: https://www.cnblogs.com/Alight/p/9596982.html
Author: 一束光
Title: 阿里云Redis开发规范

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/529038/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Centos7 无法上网问题

    最近在VMware虚拟机里玩Centos,装好后发现上不了网。经过一番艰辛的折腾,终于找到出解决问题的方法了。最终的效果是无论是ping内网IP还是ping外网ip,都能正常pin…

    Linux 2023年6月13日
    075
  • ruoyi接口权限校验

    此文章属于ruoyi项目实战系列 ruoyi系统在前端主要通过权限字符包含与否来动态显示目录和按钮。为了防止通过http请求绕过权限限制,后端接口也需要进行相关权限设计。 @Pre…

    Linux 2023年6月7日
    0154
  • linux中python虚拟环境的创建及问题

    linux中python虚拟环境的创建 LINUX 出现 -BASH-4.2# 问题的解决方法 linux中python虚拟环境的创建 1)安装依赖 >: pip3 inst…

    Linux 2023年6月14日
    092
  • Linux Ubuntu 添加新用户

    1. 了解配置文件 Linux下与用户信息相关的配置文件有 /etc/passwd、 /etc/group、 /etc/shadow等,其权限分别如下: /etc/passwd:保…

    Linux 2023年5月27日
    0135
  • 【持久层框架】- SpringData-JPA

    SpringData – JPA 😄生命不息,写作不止🔥 继续踏上学习之路,学之分享笔记👊 总有一天我也能像各位大佬一样🏆 一个有梦有戏的人 @怒放吧德德🌝分享学习心得…

    Linux 2023年6月6日
    076
  • 高速USB转8串口产品设计-TTL串口

    基于480Mbps 高速USB转8路串口芯片CH348,可以为各类主机扩展出8个独立的串口。使用厂商提供的VCP串口驱动程序,可支持Windows、Linux、Android、ma…

    Linux 2023年6月7日
    074
  • 计算机系统领域学术会议论文评审流程

    今天看到海波老师的一张图,进行转载一下,下图记录了SOSP, OSDI, Eurosys 等计算机系统顶会的评审流程: 保持更新;cnblogs.com/xuyaowen。 Ori…

    Linux 2023年6月14日
    088
  • 前端Web实训项目-教务系统成绩查询

    通过暑期前半个月实训,我们选的方向是Web前端(虽然我想选Java全栈的),所以我们最终确立的主题是做一个网页。 这个项目是我们组四个人做的,因为技术水品都不咋样,所以有很多地方需…

    Linux 2023年6月7日
    0118
  • redis 学习指南

    2、 redis.windows.conf各项配置参数介绍 默认情况下,redis不是在后台模式运行的,如果需要在后台进程运行,把该项的值更改为yes,默认为no daemoniz…

    Linux 2023年5月28日
    088
  • 使用PowerShell收集多台服务器的性能计数器

    写在前面 当管理多台Windows Server服务器时(无论是DB、AD、WEB以及其他的应用服务器),当出现性能或其他问题后,参阅性能计数器都是一个非常好的维度从而推测出问题可…

    Linux 2023年5月28日
    089
  • 无线配置多一个路由器作为家庭wifi的无线热点?

    以下内容为本人的著作,如需要转载,请声明原文链接微信公众号「englyf」 https://mp.weixin.qq.com/s/8OcDnY3O6ux41GntesHHcg 手头…

    Linux 2023年6月6日
    0113
  • 剑指offer计划链表

    剑指offer计划链表 从尾到头打印链表 /** * public class ListNode { * int val; * ListNode next = null; * * …

    Linux 2023年6月11日
    073
  • centos 更换yum 源

    1.如果系统有wget : 备份yum repo cd /etc/yum.repos.d for i in $(ls);do mv ${i}{,.bak};done for i i…

    Linux 2023年6月13日
    085
  • DDoS攻击–TCP攻击概述

    https://blog.csdn.net/qq_34777600/article/details/81945594 posted @2020-12-10 18:07 珠峰之梦 阅…

    Linux 2023年6月7日
    0101
  • Redis分布式锁的N种姿势

    Redis几种架构 Redis发展到现在,几种常见的部署架构有: 单机模式; 主从模式; 哨兵模式; 集群模式; 我们首先基于这些架构讲解Redisson普通分布式锁实现,需要注意…

    Linux 2023年5月28日
    0109
  • 线程

    一、线程概念的引入 进程 之前我们已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区…

    Linux 2023年6月14日
    093
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球