• [问题求助] docker中使用华为redis客户端sasl创建客户端耗时非常长
    用到了华为redis客户端,版本是jedisclient-3.6.3-h0.cbu.mrs.330.r9.jar创建客户端实例JedisCluster,本地和服务器上链接正常,使用docker创建镜像后,只有少数情况下正常,多数情况下都需要16秒才能创建,跟踪代码定位发现在JdisAuth.java中createSaslClient里调用Sasl.createSaslClient需要16秒,jdk换成和服务器正常使用的jdk一样也不行,怀疑可能是网络问题,各位有没有遇到相似问题的,麻烦提供一下指点,非常感谢
  • [专题汇总] 你想知道的这里都有,10月份干货合集,速进
     大家好,四季度的第一个干货合集来了,这次带来的东西主要涉及到golang,python,MySQL,redis,PostgreSQL,docker,minio,鸿蒙等等,希望可以帮助到到家 1. golang gin ShouldBind的介绍和使用示例详解【转载】 https://bbs.huaweicloud.com/forum/thread-02127165743740541019-1-1.html  2.golang flag介绍和使用示例【转载】 https://bbs.huaweicloud.com/forum/thread-0205165743832841012-1-1.html  3.Go语言中的格式化输出占位符的用法详解【转】 https://bbs.huaweicloud.com/forum/thread-0242165743874465013-1-1.html  4.Python中格式化字符串的方法总结【转载】 https://bbs.huaweicloud.com/forum/thread-02107165744051753023-1-1.html  5.Python使用进程池并发执行SQL语句的操作代码【转载】 https://bbs.huaweicloud.com/forum/thread-02111165744119162009-1-1.html  6.Mysql转PostgreSQL注意事项及说明【转】 https://bbs.huaweicloud.com/forum/thread-0205165745689855016-1-1.html  7.一文彻底讲清该如何处理mysql的死锁问题【转载】 https://bbs.huaweicloud.com/forum/thread-02111165745597896010-1-1.html  8.Redis实现分布式事务的示例【转载】 https://bbs.huaweicloud.com/forum/thread-0242165745553696016-1-1.html  9.MySQL服务无法启动且服务没有报告任何错误解决办法【转载】 https://bbs.huaweicloud.com/forum/thread-02127165745354539021-1-1.html      10.Python+OpenCV实现火焰检测【转载】 https://bbs.huaweicloud.com/forum/thread-0205165744941700014-1-1.html  11.Python Word实现批量替换文本并生成副本【转载】 https://bbs.huaweicloud.com/forum/thread-02127165744886949020-1-1.html  12.Python实现OFD文件转PDF【转载】 https://bbs.huaweicloud.com/forum/thread-0286165744755315017-1-1.html  13.Python中将文件从一个服务器复制到另一个服务器的4种方法【转】 https://bbs.huaweicloud.com/forum/thread-0242165744680560015-1-1.html  14.Python实现将pdf文档保存成图片格式【转载】 https://bbs.huaweicloud.com/forum/thread-0242165744483484014-1-1.html  15.Python通过keyboard库实现模拟和监听键盘【转载】 https://bbs.huaweicloud.com/forum/thread-0205165744195219013-1-1.html  16.docker 配置国内镜像源 https://bbs.huaweicloud.com/forum/thread-0286165634815059009-1-1.html  17.Typora 代码块Mac风格化 https://bbs.huaweicloud.com/forum/thread-02111165634917052004-1-1.html  18.MinIO上传和下载文件及文件完整性校验 https://bbs.huaweicloud.com/forum/thread-0286165634713872008-1-1.html  19.鸿蒙系统特性 https://bbs.huaweicloud.com/forum/thread-02127165634384647014-1-1.html  20.Java EasyExcel 导出报内存溢出如何解决 https://bbs.huaweicloud.com/forum/thread-02111165634289077003-1-1.html 
  • [技术干货] Redis实现分布式事务的示例【转载】
    最近公司生产环境需要排查慢SQL,导出日志txt文件后排查混乱,查找相关资料后并没有找到方便快捷的格式化处理工具,于是自己编写了一套Java读取慢SQL日志转为Excel小工具。Redis 本身并不是一个关系型数据库,它并不支持传统的 SQL 数据库中的 ACID 特性的事务。然而,Redis 提供了一种称为“事务”的特性,它允许客户端将多个命令捆绑在一起作为一个单独的序列发送给服务器。虽然 Redis 的事务并不能保证原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),但它可以用来确保一组命令作为一个整体被服务器接收和执行。Redis 的事务特性主要包括以下几个命令:MULTI:标记一个事务块的开始。EXEC:执行所有事务块内的命令。DISCARD:取消执行事务块内的所有命令。WATCH:监视一个或多个键,如果监视的键在 EXEC 前被其他命令改动,则整个事务不会被执行。下面是一个使用 Redis 进行简单事务操作的例子: import redis.clients.jedis.Jedis; import redis.clients.jedis.exceptions.JedisException;  public class RedisTransactionExample {      private static final String REDIS_HOST = "localhost";     private static final int REDIS_PORT = 6379;      public static void main(String[] args) {         Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT);          try {             // 开始事务             jedis.watch("product:p001");             String stockStr = jedis.get("product:p001");              if (stockStr != null && Integer.parseInt(stockStr) > 0) {                 jedis.multi(); // 标记事务开始                 jedis.decr("product:p001"); // 减少库存                 jedis.sadd("user:1001", "p001"); // 添加购买记录                 List<Object> results = jedis.exec(); // 执行事务                  if (results != null && results.size() == 2) {                     System.out.println("Transaction executed successfully.");                 } else {                     System.out.println("Transaction failed or was cancelled.");                 }             } else {                 System.out.println("Not enough stock.");             }          } catch (NumberFormatException e) {             System.err.println("Invalid stock value: " + stockStr);         } catch (JedisException e) {             System.err.println("Error while executing transaction: " + e.getMessage());         } finally {             if (jedis != null) {                 jedis.close();             }         }     } } 在这个例子中,我们使用 WATCH 来监视 product:p001 键的变化,然后在事务开始前检查库存是否充足。如果库存充足,我们将使用 MULTI 开始事务,并在事务内减少库存并记录用户的购买行为。最后,使用 EXEC 来执行事务。由于 Redis 的事务不具备 ACID 特性,因此它不能完全替代传统的关系型数据库事务。在高并发的情况下,仍然有可能出现竞态条件或其他一致性问题。如果需要更严格的事务支持,可能需要结合其他技术或机制来实现。对于更复杂的情况,如需要跨多个键或多个 Redis 实例的一致性操作,可能需要考虑使用外部协调服务(如 ZooKeeper 或 Etcd)来管理分布式事务,或者设计业务逻辑来容忍一定程度的不一致,例如使用最终一致性模型。
  • [问题求助] 调华为接口返回为空
    华为GaussDB有当天的拨打数据 但是调华为CMS接口却返回为空这是什么原因呢
  • [专题汇总] 9月份干货合集又来了,快看看有没有你想要的
     大家好,9月份合集又来了,本次主要带来的是python,redis,mysql,oralce等相关技术分享,希望可以帮到大家 1.Python语言中的重要函数对象用法小结【转】 https://bbs.huaweicloud.com/forum/thread-0292163074507230065-1-1.html  2.PyTorch中torch.no_grad()用法举例详解【转】 https://bbs.huaweicloud.com/forum/thread-02127163074675610068-1-1.html  3.解决遇到:PytorchStreamReader failed reading zip archive:failed finding central错误问题【转】 https://bbs.huaweicloud.com/forum/thread-0290163076531320030-1-1.html  4.解决遇到PermissionError:[Errno 13] Permission denied:XXXX错误的问题【转】 https://bbs.huaweicloud.com/forum/thread-0204163087169319057-1-1.html  5.使用python复制PDF中的页面的操作代码【转】 https://bbs.huaweicloud.com/forum/thread-0204163087217277058-1-1.html  6.Python中的Popen函数demo演示【转】 https://bbs.huaweicloud.com/forum/thread-0287163087322224052-1-1.html  7.Redis内存碎片率调优处理方式【转】 https://bbs.huaweicloud.com/forum/thread-02127163089843529071-1-1.html  8.oracle关联查询报invalid number错误的解决方法【转】 https://bbs.huaweicloud.com/forum/thread-0290163089973043031-1-1.html  9.sql中的regexp与like区别实现【转】 https://bbs.huaweicloud.com/forum/thread-02127163091329965072-1-1.html  10.SQL多表联查的几种方法示例总结【转】 https://bbs.huaweicloud.com/forum/thread-0234163091395788038-1-1.html  11.redis中如何做到内存优化【转】 https://bbs.huaweicloud.com/forum/thread-02127163091498087074-1-1.html  12.mysql数据库实现超键、候选键、主键与外键的使用【转】 https://bbs.huaweicloud.com/forum/thread-0290163091552614032-1-1.html  13.达梦数据库如何设置自增主键的方法及注意事项【转】 https://bbs.huaweicloud.com/forum/thread-0234163091642509039-1-1.html  14.解决生产环境遇到的curl和yum命令报错问题【转】 https://bbs.huaweicloud.com/forum/thread-0234163091687787040-1-1.html  15.Nginx实现404页面的配置方法的两种方法【转】 https://bbs.huaweicloud.com/forum/thread-0290163091762002033-1-1.html 
  • [技术干货] redis中如何做到内存优化【转】
    1、数据结构的优化1、使用数据结构的最小存储形式。例如,如果你需要存储一组唯一的用户ID,你可以将这些信息合并到一个大的哈希表中,而不是为每个用户创建单独的哈希表,以减少固定开销。2、使用整数编码。例如,存储用户的年龄信息时,将年龄存储为整数值而不是字符串,可以节省内存。3、使用Redis的HyperLogLog来进行基数估计,这比存储大量唯一值的集合更加节省内存。2、启用对象压缩Redis 6及以上版本引入了对字符串的内置LZF压缩支持。通过配置参数activerehashing可以启用对象压缩,减少存储空间。3、设置适当的过期时间为缓存的数据设置适当的过期时间,以防止内存泄漏。这可以确保在数据不再需要时及时释放内存。4、分片将数据分片到多个Redis实例中,以便每个实例只存储部分数据。这可以减小每个实例的内存需求,特别是在大规模部署时。5、使用持久化方式如果你使用了Redis的持久化机制,考虑使用RDB快照来定期将内存中的数据快照到磁盘,以便在需要时进行恢复。6、内存碎片整理定期执行MEMORY DOCTOR命令来检查和修复内存碎片。这可以通过将碎片的数据移动到一个新的实例中来实现。7、客户端和配置优化1、接入Redis服务器的TCP连接输入输出缓冲内存占用需要注意,特别是在异地部署主从或高并发场景下。2、使用client-output-buffer-limit参数配置输出缓冲占用,避免主节点上挂载过多的从节点。3、对于复制积压缓冲区(v2.8之后提供的一个可重用的固定大小缓冲区),合理配置repl-backlog-size参数,以避免全量复制。4、对于AOF缓冲区,根据AOF重写时间及增量来合理配置缓存大小。
  • [技术干货] Redis内存碎片率调优处理方式【转】
    1.背景概述在生产环境中Redis Cluster集群触发了内存碎片化的告警(碎片率>1.5),集群节点分布三台宿主机六个节点三主三从架构,Redis版本是6.2.X。2.redis内存碎片的形成内存碎片形成的原因主要有2点:内因:操作系统的内存分配机制。外因:Redis的负载特征造成。内因:内存分配器会按照固定大小来分配内存,而不是按需分配。例如Linux下默认是4KB,开启内存大页机制后就变成2MB。Redis中使用jemalloc分配器来分配内存。它会按照一系列固定大小的内存来进行分配。例如当Redis中需要申请一个20B大小的空间来保存数据,那么jemalloc分配器就会分配32B:倘若此时应用还要写入5B大小的数据,那么无需申请额外的空间。倘若此时应用还要写入20B大小的数据,那么必须在申请额外的空间了,此时就会有产生内存碎片的风险(之前分配的32B中,10B就是内存碎片了)外因:我们有一个Redis实例,里面有着不同大小的键值对,那么根据内存分配器的分配机制来看。就有可能分配着不同大小的连续内存空间。另一方面,我们对键值对也有可能有着不同的操作,增删改查。3.清理内存碎片清理内存碎片之前,首先应该做的就是判断是否有内存碎片:我们可以登录Redis后使用INFO MEMORY命令查看。mem_fragmentation_ratio参数的值就是内存碎片化的值。mem_fragmentation_ratio代表Redis实例当前的内存碎片率。其计算公式为:mem_fragmentation_ratio = used_memory_rss / used_memoryused_memory_rss:操作系统实际分配Redis的物理内存空间。used_memory:Redis为了保存数据而实际申请的空间。针对mem_fragmentation_ratio,有两个参考:mem_fragmentation_ratio ∈ (1, 1.5]:属于合理范围内,暂时可以放放。mem_fragmentation_ratio ∈ (1.5, +∞):表明内存碎片率超过了50%,需要采取措施降低内存碎片率。那么如何清理内存碎片呢(一般不会重启实例,因为生产上往往不允许这种神操作出现),在Redis4.0版本以后,Redis提供了内置的内存碎片清理机制。12345678910111213#内存碎片回收机制使用activedefrag yes# active-defrag-ignore-bytes与active-defrag-threshold-lower两个条件同时满足会触发内存碎片清理,当有一个不满足则停止清理# 启动活动碎片整理的最小碎片浪费量,内存碎片的字节数达到100M时开始清理active-defrag-ignore-bytes 100mb# 启动活动碎片整理的最小碎片百分比,内存碎片空间占操作系统分配给redis的总空间比例达到 10% 时开始清理active-defrag-threshold-lower 10# 内存碎片超过 100%,则尽最大努力整理active-defrag-threshold-upper 100# 以CPU百分比表示的碎片整理的最小工作量,自动清理过程所用CPU时间的比例不低于5%,保证能正常清理active-defrag-cycle-min 5# 自动清理过程所用CPU时间的比例不高于75%,超过75%停止清理,避免redis主线程阻塞active-defrag-cycle-max 75以上参数可根据主机资源配置及应用场景自行调整。除此之外,值得注意的是,虽然Redis提供了这样的自动内存清理机制,能够带来清理内存碎片的好处,但是与此同时的必定有着其对应的牺牲,也就是性能影响问题。Redis提供了内置的内存碎片清理机制的使用前提是在编译的过程中添加了内存分配器参数MALLOC=jemalloc1make MALLOC=jemalloc4.扩展当然我们在生产环境使用Redis过程中也可以使用自带的命令进行内存使用情况的诊断,便于我们及时对问题进行优化处理。我们可以使用MEMORY help查看:1234567127.0.0.1:6379> MEMORY help1) MEMORY <subcommand> arg arg ... arg. Subcommands are:2) DOCTOR - Return memory problems reports.3) MALLOC-STATS -- Return internal statistics report from the memory allocator.4) PURGE -- Attempt to purge dirty pages for reclamation by the allocator.5) STATS -- Return information about the memory usage of the server.6) USAGE <key> [SAMPLES <count>] -- Return memory in bytes used by <key> and its value. Nested values are sampled up to <count> times (default: 5).MEMORY STATSredis的内存使用不只包含全部的key-value数据,还有描述这些key-value的元信息,以及许多管理功能的消耗,好比持久化、主从复制,经过MEMORY STATS能够更好的了解到redis的内存使用情况
  • [活动公告] 【HUAWEI CONNECT 2024丨社区活动】掌握Redis部署,轻松实现电商平台秒杀抢购!
    因参与楼层不满足开奖条件,本活动不开奖。-------------------------------------------------------------------参加“掌握Redis部署,轻松实现电商平台秒杀抢购!”项目在本活动帖下回帖,提出你的问题与建议有机会获得开发者定制礼品【体验项目】掌握Redis部署,轻松实现电商平台秒杀抢购!【体验简介】通过本案例,开发者将掌握在云主机中安装和配置Redis,了解如何在Java项目中使用Jedis对接Redis服务器实现缓存功能并且使用CodeArts IDE模拟运行电商秒杀抢购场景。【体验形式】1.登录注册华为云账号,领取云主机;2、使用云主机资源进行应用开发。【活动时间】2024年9月13-10月12日【参与方式】直接在此活动帖下方回帖,将体验完成的截图和您的问题/建议/感受一起回帖即可比如体验中遇到的问题,对产品的建议、对活动感受等等PS:不要少于30字哦~【获奖规则】可提前填写获奖信息收集表,后续如您中奖,我们会及时发货,谢谢。获奖信息收集表: cid:link_0【活动规则】1、本帖的回帖建议不少于30字,仅限于对“掌握Redis部署,轻松实现电商平台秒杀抢购!”体验项目,其他项目建议不参与此次活动,否则将视为无效内容。2、本次活动将根据实际参与情况发放奖励,包括但不限于用户百分之百中奖或奖项轮空的情况;实物奖品具体发放视出库情况而定; 3、活动预计于结束后七天内完成奖项公示,并于结束后15个工作日内完成邮寄。【温馨提示】1、请务必使用个人实名账号参与活动(IAM、企业账号等账号参与无效)。如一个实名认证对应多个账号,只有一个账号可领取奖励,若同一账号填写多个不同收件人或不同账号填写同一收件人,均不予发放奖励。2、所有获得奖品的获奖用户,请于获奖后3日内完成实名认证,否则视为放弃奖励。
  • [技术干货] Redis increment 函数处理并发序列号案例【转】
    1. 创建Spring Boot项目首先,创建一个新的Spring Boot项目。你可以使用Spring Initializr(https://start.spring.io/)来生成项目结构。选择以下依赖:Spring WebSpring Data RedisLombok(可选,用于简化代码)2. 配置application.yml在你的 ​application.yml​文件中添加Redis配置:12345678spring:  cache:    type: GENERIC  redis:    host: ${sy.redis.ip}    password:    port: ${sy.redis.port}    database: ${sy.redis.database}3. 创建缓存配置类创建一个配置类来手动配置基于Redis的缓存管理器:import org.springframework.cache.CacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import java.time.Duration; @Configuration public class CacheConfig {     @Bean     public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {         RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()                 .entryTtl(Duration.ofMinutes(10)) // 设置缓存过期时间                 .disableCachingNullValues()                 .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));         return RedisCacheManager.builder(redisConnectionFactory)                 .cacheDefaults(cacheConfiguration)                 .build();     } }4. 创建服务类创建一个服务类来使用Redis的 ​INCR​方法生成每天的序号import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.time.format.DateTimeFormatter; @Service public class SequenceService {     @Autowired     private StringRedisTemplate redisTemplate;     public long getDailySequence() {         String dateStr = DateUtils.format(new Date(), "yyyy-MM-dd");         String key = "dailySequence_" + dateStr;         // 执行 increment 操作         Long applicantNumber = redisTemplate.opsForValue().increment(key);         // 设置过期时间为2天,不设置默认永久         redisTemplate.expire(key, 2, TimeUnit.DAYS);         //redisTemplate.expire(key) // 查询key的过期时间。         //-1: 表示键存在但没有设置过期时间。         //-2: 表示键不存在。         //返回秒:如上面返回值是 172780,这意味着该键将在大约 172780 秒(约 48 小时)后过期。         return applicantNumber;     } }5. 创建控制器创建一个控制器来暴露获取每天序号的API:import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class SequenceController {     @Autowired     private SequenceService sequenceService;     @GetMapping("/daily-sequence")     public String getDailySequence() {         long sequence = sequenceService.getDailySequence();         return "Daily sequence: " + sequence;     } }6. 启动类确保你的启动类包含 ​@EnableCaching​注解以启用缓存功能:import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication @EnableCaching public class RedisIncrApplication {     public static void main(String[] args) {         SpringApplication.run(RedisIncrApplication.class, args);     } }
  • [技术干货] redis搭建哨兵模式实现一主两从三哨兵【转】
    一、Redis 哨兵模式:哨兵的核心功能:在主从复制的基础上,哨兵引入了主节点的自动故障转移1、哨兵模式原理:哨兵:是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的Master 并将所有Slave 连接到新的 Master。所以整个运行哨兵的集群的数量不得少于3个节点。2、哨兵模式的作用:监控:哨兵会不断地检查主节点和从节点是否运作正常。自动故障转移:当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点。通知提醒:哨兵可以将故障转移的结果发送给客户端3、哨兵的结构:哨兵节点:哨兵系统由一个或多个哨兵节点组成,哨兵节点就是特殊的redis节点,不存储数据数据节点:主节点和从节点都是数据节点注意:哨兵的启动依赖于主从模式,所以须把主从模式安装好的情况下再去做哨兵模式,所有节点上都需要部署哨兵模式,哨兵模式会监控所有的Redis工作节点是否正常。4、故障转移机制:由哨兵节点定期监控主节点是否出现了故障,每个哨兵节点每隔1秒会向主节点、从节点及其它哨兵节点发送一次ping命令做一次心跳检测。 如果主节点在一定时间范围内不回复或者是回复一个错误消息,那么这个哨兵就会认为这个主节点主观下线了(单方面的),当超过半数哨兵节点认为该主节点下线了,这样就客观下线了。 此时哨兵节点会通过Raft算法〈选举算法)实现选举机制共同选举出一个哨兵节点为leader,来负责处理主节点的故障转移和通知。故障转移过程如下:● 将某一个从节点升级为新的主节点,让其它从节点指向新的主节点;● 若原主节点恢复也变成从节点,并指向新的主节点;● 通知客户端主节点已经更换。主节点的选举条件:过滤掉不健康的(已下线的),没有回复哨兵ping响应的从节点选择配置文件中从节点优先级最高的(replication-priority,默认值为100)选择复制偏移量最大的,也就是复制最完整的从节点。二、案例环境
  • [技术干货] 深入理解redis删除策略和淘汰策略【转】
    1、redis的删除策略Redis 是一种内存级数据库,数据都存在内存中,但是针对于已经过期的数据,reids 不 会立刻删除只是会存储在 expires 中,当执行删除策略的时候,才会从 expires 中寻找对应的数据存储的地址,在存储空间中找到对应的数据进行删除。数据删除其实就是内存和 CPU 占用之间寻找平衡,CPU 才能去处理事情,针对过期数据,要进行删除的时候,一般有三种策略 2、三种删除策略 (1)、定时删除顾名思义,给Key设置一个时间,时间到了,定时器任务立即执行删除,相当于消 耗 CPU 来减少内存使用,拿时间换空间。优点:节约内存,到时就删除,快速释放掉不必要的内存占用 缺点:CPU 压力大,无论 CPU 此时负载量多高,都会去占用 CPU 进行 key 的删除 操作,会影响 Redis 服务器响应时间和吞吐量,是一种比较低效的方式 结论:用 CPU 性能换取内存空间,时间换空间(2)、惰性删除 就是说,数据到达过期时间的时候,先不做处理,等到下次访问数据的时候,进行访问, 如未过期,返回数据,如过期,则删除。这就相当于节约了 CPU 但占用了内存,拿空间换 时间。优点:不占用 CPU 节约 CPU 性能,只在获取访问 key 的时候才判断是否过期,过期 则删除,只会删除当前获取的这一个 key,其他的 key 还是保持原样缺点:内存占用大,如果一直没有获取它,那么数据就会长期占用内存空间,当有大量 的 key 没有被使用到,也造成了大量内存浪费,对内存数据库来说,也不太友好 结论:空间换时间(3)、定期删除 前面说的两种方案 1.时间换空间,2.空间换时间都是两个极端方法,为避免前面方案带 来的问题,Redis 引入了定期删除策略(是他们的一个比较折中的方案)周期性轮询 Redis 库中的时效性数据,采取随机抽取的策略,利用过期数据占比的方式控制删除频度。在 Redis 服务器初始化时,读取 server.hz 的值,默认值为 10。定时轮询服务器,每秒钟执行 server.hz 次 serverCron() 函数。databaseCron() 在后台轮询处理 16 个 redis 数据库的操作,如这里的过期key 的处理activeExpireCycle(),对每个数据库的 expire 空间进行检测,每次执行250ms/server.hz 随机选取一批 expire 空间的 key(redis 有 16 个数据库,从 0 号数据库开始—15号数据库) 删除这批 key 中已过期的。如果这批 key 中已过期的占比超过 25%,那么再重复执行步骤一。(循环到小于 25%结束当前数据库的删除)如果这批 key 中已过期的占比 ≤ 25%,检测下一个数据库的 expire 空间(current_db++) 用 info 命令查看相关配置参数 每秒钟执行 hz 次 serverCron(),对服务器进行定时轮询3、三种策略对比 1:定时删除: 节约内存,无占用, 不分时段占用 CPU 资源, 频度高,拿时间换空间 2:惰性删除: 内存占用严重 延时执行, CPU 利用率高拿空间换时间3:定期删除: 内存定期随机清理 每秒花费固定的 CPU 资源维护内存 随机抽查,重点抽查4、淘汰/逐出策略 在 Redis 中经常会进行数据的增删查改操作,那么如果在添加数据的时候遇到了内存不足,该怎么办?在前面用的删除策略可以避免出现这种情况吗? 实际上,在前面所说的删除策略,它针对的是 expire 命令进行的操作,也就是说那些具有时效性的数据(已经过期,并且还在占用内存的数据) 针对那些并没有过期,或者是内存中的数据没有一个带有有效期,全是永久性数据,这时候删除策略就不起作用了,所以这个时候内存满了我们再去插入数据到内存是怎么做?那就需要用到淘汰策略了。redis 执行命令之前,都会用 freeMemoryIfNeeded()方法,检测这次内存是否充足,如果不满足加入新数据,则会执行淘汰策略(淘汰未过期的数据)(1)、淘汰策略分类检测带有时效性的数据进行淘汰(一般是有定时,会过期的数据的)volatile-lru:挑选最近最少使用的数据淘汰volatile-lfu:挑选最近使用次数最少的数据淘汰volatile-ttl:挑选将要过期的数据淘汰volatile-random:任意选择数据淘汰检测全库的数据进行淘汰allkeys-lru:挑选最近最少使用的数据淘汰allkeLyRs-lfu:挑选最近使用次数最少的数据淘汰allkeys-random:任意选择数据淘汰,相当于随机
  • [技术干货] 35个Redis企业级性能优化点与解决方案
    Redis的性能优化涉及到硬件选择、配置调整、客户端优化、持久化策略等多个层面。1. 硬件优化解决方案:选择更快的CPU、更多的内存、更快的磁盘(SSD推荐)和足够的网络带宽。2. 合理的实例部署解决方案:根据业务访问模式,决定是使用单实例、主从复制、哨兵系统还是Redis集群。3. 连接数优化解决方案:调整redis.conf中的maxclients参数,以适应业务需求。示例配置:maxclients 100004. 命令优化解决方案:避免使用耗时的命令,如KEYS、FLUSHDB等,使用SCAN替代。5. 使用连接池解决方案:使用客户端连接池减少连接建立和销毁的开销。示例代码(Java Jedis连接池):JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(100); poolConfig.setMaxIdle(10); poolConfig.setMinIdle(5); JedisPool jedisPool = new JedisPool(poolConfig, "localhost", 6379); Jedis jedis = jedisPool.getResource(); // 执行命令 jedis.set("foo", "bar"); // 关闭连接 jedis.close();6. Pipelining批量命令解决方案:使用Pipeline批量执行命令,减少网络延迟。示例代码(Java Jedis Pipeline):Jedis jedis = jedisPool.getResource(); Pipeline pipeline = jedis.pipeline(); pipeline.set("foo", "bar"); pipeline.get("foo"); List<Object> results = pipeline.syncAndReturnAll(); jedis.close();7. 键值对设计解决方案:选择合适的数据类型,使用散列(Hash)存储相关联的字段。示例代码:// 使用Hash存储用户信息 hset "user:1000" "name" "John Doe" hset "user:1000" "email" "john@example.com"8. 内存优化解决方案:使用内存淘汰策略,如volatile-lru或allkeys-lru。示例配置:maxmemory-policy allkeys-lru9. 持久化策略解决方案:根据数据的重要性选择合适的持久化方式(RDB、AOF或两者结合)。示例配置:appendonly yes appendfsync everysec10. 禁用持久化解决方案:对于可以容忍数据丢失的场景,可以完全禁用持久化。示例配置:save "" appendonly no11. Lua脚本解决方案:使用Lua脚本来打包多个命令,减少网络延迟。示例代码:-- Lua脚本,实现原子增减操作 return redis.call('INCR', KEYS[1])12. 慢查询日志解决方案:开启慢查询日志,分析慢查询原因。示例配置:slowlog-log-slower-than 10000 slowlog-max-len 12813. 主从复制解决方案:使用主从复制提高读性能,同时实现数据的热备份。示例配置:slaveof <masterip> <masterport>14. Redis集群解决方案:使用Redis集群实现数据的自动分区和高可用。示例命令:./redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:700215. 监控和报警解决方案:使用Redis自带的监控工具或第三方监控系统,实时监控Redis状态。示例命令:redis-cli info16. 禁用THP解决方案:禁用Transparent HugePages,避免内存页管理的性能损耗。示例命令:echo never > /sys/kernel/mm/transparent_hugepage/enabled17. 操作系统优化解决方案:调整操作系统参数,如文件描述符限制、TCP缓冲区大小等。示例命令:sysctl -w net.core.somaxconn=1024 ulimit -n 409618. 网络优化解决方案:优化TCP堆栈参数,如TCP接收和发送缓冲区大小。示例命令:sysctl -w net.ipv4.tcp_rmem='4096 87380 6291456' sysctl -w net.ipv4.tcp_wmem='4096 16384 4194304'19. 数据压缩解决方案:对于大体积的数据,使用数据压缩算法减少存储大小和传输时间。示例:使用ZIPLIST编码的数据结构存储小对象。20. 优化键设计解决方案:设计具有前缀的键名,便于管理和迁移。示例:// 使用命名空间来区分不同的数据类型 set user:1000:name "John Doe" set user:1000:email "john@example.com"21. 避免大Key和大Value解决方案:大Key和大Value会影响Redis的性能和稳定性,应尽量避免。示例:将大的列表或集合分割成多个小的集合。22. 使用二进制序列化解决方案:使用二进制序列化协议提高数据传输效率。示例:使用MSGPACK或PROTOBUF序列化Java对象。23. 优化数据访问模式解决方案:根据业务特点,优化数据的访问模式,如使用缓存预热、缓存雪崩的解决方案等。24. 合理的数据过期策略解决方案:为数据设置合理的过期时间,避免过期数据占用内存。示例配置:expire user:1000:email 8640025. 减少网络延迟解决方案:优化网络环境,使用QoS策略减少网络延迟。26. 使用SSD而不是HDD解决方案:使用固态硬盘(SSD)代替机械硬盘(HDD),提高磁盘I/O性能。27. 优化持久化日志解决方案:调整AOF持久化的策略,比如使用everysec或no选项。示例配置:appendfsync no28. 使用Redis 4.0以上的版本解决方案:新版本的Redis提供了更多的功能和性能改进,如增加了模块系统、支持多线程等。29. 避免使用阻塞命令解决方案:在可能的情况下,避免使用可能导致阻塞的命令,如BLPOP、BRPOP等。30. 定期进行性能评估解决方案:定期对Redis实例进行性能评估,根据评估结果调整配置。示例工具:使用redis-benchmark工具进行基准测试。31. 使用Redisson客户端解决方案:对于Java应用,使用Redisson客户端可以提供更高级的功能,如分布式锁、原子操作等。示例代码(Redisson配置):Config config = new Config(); SingleServerConfig singleServerConfig = config.useSingleServer(); singleServerConfig.setAddress("redis://127.0.0.1:6379"); RedissonClient redisson = Redisson.create(config);32. 避免全量扫描解决方案:在可能的情况下,避免使用KEYS命令进行全量扫描,这会导致性能急剧下降。33. 优化数据迁移解决方案:在进行数据迁移时,使用MIGRATE命令,它可以原子性地迁移数据。示例命令:MIGRATE "127.0.0.1" 6379 "127.0.0.1" 6380 "key" 0 5000 REPLACE34. 优化日志级别解决方案:根据需要调整日志级别,避免冗余日志占用过多磁盘空间和CPU资源。示例配置:loglevel warning35. 优化Redis配置文件解决方案:定期审查和优化redis.conf配置文件,以匹配当前的业务需求。最后以上是Redis企业级性能优化的一些关键点和解决方案。转载自https://www.cnblogs.com/wgjava/p/18267106
  • [技术干货] 无法启动Redis打开redis-server闪退的问题解决办法【转】
    【问题】① 双击redis-server.exe闪退。② 终端运行redis-server没反应。但是终端运行redis -cli没问题。【解决方法】步骤1:找到Redis文件夹,右击,在终端打开。步骤2:输入命令:redis-server.exe redis.windows.conf 就按下面步骤输入命令并回车:步骤1:redis-cli.exe步骤2:shutdown(结束)步骤3:exit (退出)步骤4:redis-server.exe redis.windows.conf  重新启动就可以了!
  • [技术干货] Redission实现分布式锁lock()和tryLock()方法的区别小结【转】
    本文主要介绍了 Redission实现分布式锁lock()和tryLock()方法的区别小结,具体如下:1lock.lock(30, TimeUnit.SECONDS); // 尝试获取锁30秒,如果获取不到则放弃12//尝试获取锁,等待5秒,持有锁10秒钟boolean success = lock.tryLock(5, 10, TimeUnit.SECONDS);Redisson 是一种基于 Redis 的分布式锁框架,提供了 lock() 和 tryLock() 两种获取锁的方法。lock() 方法是阻塞获取锁的方式,如果当前锁被其他线程持有,则当前线程会一直阻塞等待获取锁,直到获取到锁或者发生超时或中断等情况才会结束等待。该方法获取到锁之后可以保证线程对共享资源的访问是互斥的,适用于需要确保共享资源只能被一个线程访问的场景。Redisson 的 lock() 方法支持可重入锁和公平锁等特性,可以更好地满足多线程并发访问的需求。而 tryLock() 方法是一种非阻塞获取锁的方式,在尝试获取锁时不会阻塞当前线程,而是立即返回获取锁的结果,如果获取成功则返回 true,否则返回 false。Redisson 的 tryLock() 方法支持加锁时间限制、等待时间限制以及可重入等特性,可以更好地控制获取锁的过程和等待时间,避免程序出现长时间无法响应等问题。因此,两种获取锁的方式各有优缺点,在实际应用中需要根据具体场景和业务需求来选择合适的方法,以确保程序的正确性和高效性。直接看代码例子lock.tryLock等待时间和持有时间都为0时。    public String RedissonLock1() {         RLock lock = redissonClient.getLock("order_lock");         boolean success = true;         try {             System.out.println("获取锁前的时间:"+LocalDateTime.now());             // 尝试获取锁,等待0秒,持有锁0秒钟             success = lock.tryLock(0, 0, TimeUnit.SECONDS);             // lock.lock(0, TimeUnit.SECONDS);             System.out.println("获取锁后的时间:"+LocalDateTime.now());             if (success) {                 System.out.println(Thread.currentThread().getName() + "获取到锁"+ LocalDateTime.now());                 // 模拟业务处理耗时                 // TimeUnit.SECONDS.sleep(3);                 // 模拟业务处理耗时 大于锁过期,可能导致非自己持有的锁被释放。                 TimeUnit.SECONDS.sleep(20);             } else {                 System.out.println(Thread.currentThread().getName() + "未能获取到锁,已放弃尝试");             }         } catch (InterruptedException e) {             e.printStackTrace();         } finally {             // 判断当前线程是否持有锁             if (success && lock.isHeldByCurrentThread()) {                 //释放当前锁                 lock.unlock();                 System.out.println(Thread.currentThread().getName() + "释放锁"+ LocalDateTime.now());             }         }         return "";     } lock()方法的持有锁时间为0时    public String RedissonLock2() {         RLock lock = redissonClient.getLock("order_lock");         boolean success = true;         try {             System.out.println("获取锁前的时间:"+LocalDateTime.now());             // 尝试获取锁,等待5秒,持有锁10秒钟            // success = lock.tryLock(0, 0, TimeUnit.SECONDS);             lock.lock(0, TimeUnit.SECONDS);             System.out.println("获取锁后的时间:"+LocalDateTime.now());             // 模拟业务处理耗时             // TimeUnit.SECONDS.sleep(3);             // 模拟业务处理耗时 大于锁过期,可能导致非自己持有的锁被释放。             TimeUnit.SECONDS.sleep(20);         } catch (InterruptedException e) {             e.printStackTrace();         } finally {             // 判断当前线程是否持有锁             if (success && lock.isHeldByCurrentThread()) {                 //释放当前锁                 lock.unlock();                 System.out.println(Thread.currentThread().getName() + "释放锁"+ LocalDateTime.now());             }         }         return "";     }lock() 和 tryLock()都会用的 tryAcquireAsync(),看到区别,其实核心是leaseTime是否 > 0 所以是否使用看门狗不算是tryLock和lock()的区别,可以看下面这5种情况。             //走if (leaseTime > 0)逻辑             lock.tryLock(5, 10, TimeUnit.SECONDS);             lock.lock(10, TimeUnit.SECONDS);              //不走if (leaseTime > 0)逻辑             lock.tryLock(0, -1, TimeUnit.SECONDS);             lock.lock(-1, TimeUnit.SECONDS);             //lock()不带参数,默认leaseTime = -1             lock.lock();  当oldEntry == null时,执行renewExpiration(); 就是个定时器,即是看门狗核心逻辑了。    private void renewExpiration() {         ExpirationEntry ee = EXPIRATION_RENEWAL_MAP.get(getEntryName());         if (ee == null) {             return;         }                  Timeout task = commandExecutor.getConnectionManager().newTimeout(new TimerTask() {             @Override             public void run(Timeout timeout) throws Exception {                 ExpirationEntry ent = EXPIRATION_RENEWAL_MAP.get(getEntryName());                 if (ent == null) {                     return;                 }                 Long threadId = ent.getFirstThreadId();                 if (threadId == null) {                     return;                 }                                  CompletionStage<Boolean> future = renewExpirationAsync(threadId);                 future.whenComplete((res, e) -> {                     if (e != null) {                         log.error("Can't update lock {} expiration", getRawName(), e);                         EXPIRATION_RENEWAL_MAP.remove(getEntryName());                         return;                     }                                          if (res) {                         // reschedule itself                         renewExpiration();                     } else {                         cancelExpirationRenewal(null);                     }                 });             }         }, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS);                  ee.setTimeout(task);     } 其中有下面红圈这段逻辑,也就是看门狗之所以在三分之一的时候执行的原因, 没有自定义时1config.setLockWatchdogTimeout(10000); // 设置锁的看门狗超时时间为10秒默认就是30秒 除以3  也就是10秒时执行。ChaGPT解释此段LUA:这是 Redisson 中 RedissonLock 类实现的 tryLockInnerAsync() 方法。该方法用于尝试获取锁,它会先检查锁是否已经被其他线程持有,如果没有被持有,则将当前线程设置为锁的持有者,并返回 null;否则返回当前线程需要等待的时间,以便稍后再次尝试获取锁。具体地说,Lua 脚本的逻辑是这样的:如果锁不存在或者锁已经被当前线程持有(使用 hash 存储锁的持有者),则将当前线程作为锁的持有者,并且设置锁的过期时间,并返回 null。这里的代码具体操作包括使用 HEXISTS 命令检查锁的持有情况,使用 HINCRBY 命令来设置持有者和持有计数器并提高计数器的值,以及使用 PEXPIRE 命令来设置锁的过期时间。如果锁已经被其他线程持有,则返回当前线程需要等待的时间,以便稍后再次尝试获取锁。这里使用 PTTL 命令来查询锁的过期时间,并返回给调用方。需要注意的是,因为 tryLockInnerAsync 方法的实现是原子的,所以它可以保证在分布式环境下的正确性。同时,它也支持重入锁的功能,因为它保留了锁的持有者和持有计数器的值。
  • [问题求助] MRS中使用Flinksql,使用redis流表,将kafka数据写入redis的问题
    流表配置如下,使用hash结构:flinksql语句,简单统计时间和数量:所得结果:问题:想要使用begin_time作为hash的key,sum作为value该如何配置