关于运维:干货丨Redis-性能测试和监控

**转自@twt社区,作者:泊涯很多人在装置部署好Redis后,就没有对Rredis的配置和部署等有效性和高可用性进行性能测试,最终导致上线呈现缓存穿透、雪崩等景象,导致性能还是有问题,其实做为技术运维人员在部署好Redis后能够应用Redis自带的压测工具进行简易型压测**,如下命令: redis-benchmark [option] [option value] 例如在本地搭建一个Redis服务,IP地址是10.100.81.171,这时须要模仿100用户并发链接申请,每个用户现场循环拜访100次。 redis-benchmark -h 10.100.81.171 -p 6379 -c 100 -n 100000 参数详解: 1、100000 requests completed in 1.60 seconds //默认是100000,下面有,申请在1.6s内实现 2、3 bytes payload,每次写入3个字节的数据 3、keep alive: 1,放弃一个连贯,一台服务器来解决这些申请 4、100.00% <= 2 milliseconds,所有申请2毫秒实现 5、62656.64 requests per second 每次能解决申请数量 具体如下图: Redis读写状况压测,如下:测试存取大小为500字节的数据包的性能 redis-benchmark -h 10.100.81.171 -p 6379 -q -d 500 这时能够通过监控命令或者其余工具看到Redis服务的服务器资源应用状况: redis-benchmark 工具命令应用介绍:

March 26, 2021 · 1 min · jiezi

关于redis:知识点问答

Q1:select count(*) from t;t中有id(主键),name,age,sex4个字段,假如数据10条,对sex增加索引,用explain 查看执行打算发现用了sex索引,为什么不是主键索引呢? A1: MySQL Innodb的主键索引是一个B+树,数据存储在叶子节点上,10条数据,就有10个叶子节点;sex索引是辅助索引,也是一个B+树,不同之处在于,叶子节点存储的是主键值,因为sex只有2个可能的值:男和女,因而,这个B+树只有2个叶子节点,比主键索引的B+树小的多;这个表有主键,因而不存在所有字段都为空的记录,所以COUNT(*)只有统计所有主键的值就能够了,不须要回表读取数据;SELECT COUNT(*) FROM t,应用sex索引,只须要拜访辅助索引的小B+树,而应用主键索引,要拜访主键索引的那个大B+树,明细工作量大,这就是优化器应用辅助索引的起因。

March 25, 2021 · 1 min · jiezi

关于java:Redis-分布式锁遇到的序列化问题

场景形容最近应用 Redis 遇到了一个相似分布式锁的场景,跟 Redis 实现分布式锁类比一下,就是开释锁失败,也就是缓存删不掉。又踩了一个 Redis 的坑…… 这是什么个状况、又是怎么排查的呢? 本文次要对此做个复盘。 问题排查既然是开释锁有问题,那就先看看开释锁的代码吧。 开释锁开释锁应用了 Lua 脚本,代码逻辑和 Lua 脚本如下: 开释锁示例代码public Object release(String key, String value) { Object existedValue = stringRedisTemplate.opsForValue().get(key); log.info("key:{}, value:{}, redis旧值:{}", key, value, existedValue); DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(COMPARE_AND_DELETE, Long.class); return stringRedisTemplate.execute(redisScript, Collections.singletonList(key), value);}开释锁应用的 Lua 脚本if redis.call('get',KEYS[1]) == ARGV[1]then return redis.call('del',KEYS[1])else return 0end;删除脚本中,会先获取 Redis key 的旧值,并与入参 value 比拟,二者相等时才会删除。 如果开释胜利,也就是 Redis 缓存删除胜利,返回值为 1,否则失败返回为 0。 乍一看代码仿佛没啥问题,测一下试试? 不过既然要开释锁,在此之前必定要加锁,先看看加锁的逻辑吧。 加锁说到加锁这里的逻辑,代码里有两种实现形式: 示例代码一public Object lock01(String key, String value) { log.info("lock01, key={}, value={}", key, value); return redisTemplate.opsForValue().setIfAbsent(key, value, LOCKED_TIME, TimeUnit.SECONDS);}示例代码二public Object lock02(String key, String value) { log.info("lock02, key={}, value={}", key, value); return stringRedisTemplate.opsForValue().setIfAbsent(key, value, LOCKED_TIME, TimeUnit.SECONDS);}其实它们的区别就在于前者应用了 RedisTemplate,而后者应用的是 StringRedisTemplate。 ...

March 25, 2021 · 2 min · jiezi

关于华为云:华为云PB级数据库GaussDBfor-Redis揭秘第六期Feed流场景中的应用

摘要:探讨常见的Feed流零碎蕴含的概念、架构和挑战以及如何应用高斯Redis设计一个Feed流零碎。本文分享自华为云社区《华为云PB级数据库GaussDB(for Redis)揭秘第六期:Feed流场景中的利用》,原文作者:高斯Redis官网博客。 一、背景GaussDB(for Redis)(下文简称高斯Redis),是华为自研的强统一、长久化NoSQL数据库,兼容Redis5.0协定。 在互联网时代,咱们日常生活充斥着Feed流,微信朋友圈、微博、抖音以及头条等等都在应用Feed流,将咱们关注的好友或感兴趣的内容及时推送给咱们,使咱们沉沦其中无法自拔,带来商业价值的晋升。接下来将和大家一起探讨常见的Feed流零碎蕴含的概念、架构和挑战以及如何应用高斯Redis设计一个Feed流零碎。 二、 概念Feed流零碎从模式上是Feed生成者将生产的Feed通过存储散发零碎传递给Feed消费者,最终以某种展示模式。 Feed:单次推送的内容。 一条微博就是一个Feed。Feed流:由间断的Feed组成的信息流。展示模式:展现模式目前次要有Timeline和Rank。比方微博以Timeline展现。头条客户端次要以举荐Rank来进行展现。Feed生产者:对于微博就是每个用户,针对头条就是举荐算法。Feed消费者:接管Feed告诉的主体。同步存储系统:这部分个别又能够分为三局部(具体实现会略有差别)。6.1 内容存储模块:这部分关怀Feed原始内容如何存储。如你发的一条微博。6.2 关联关系存储模块:对于微博存储的是用户的关注人和被关注人,对于头条存储的是人群(依据用户画像对所有用户进行分类)6.3 信箱模块:个别又可叫做消息传递模块,Feed音讯存储到信箱,能力最终造成Feed流。三、架构设计通过上述的概念介绍,咱们来看Feed如何从Feed生产者最终流转到Feed消费者。 Feed生产者创作一条内容后发到Server端,Server端先将音讯内容存储到音讯存储模块,接着依据信箱模块的设计查问关系存储库将告诉信息写入信箱模块, Feed消费者通过查问信箱获取及时音讯。 音讯存储模块:Feed内容个别都是半结构化数据,数据量大,须要长久化内容,逻辑上就是一个KV零碎,ID到内容的映射关系。 关系存储模块:关联关系会产生新增和删除,是一个变长的汇合,须要可能反对疾速的增删查动作,个别不须要反对join等简单操作。因而NoSQL数据库比拟适宜这类数据的存储。 信箱模块:说到信箱模块个别大家都会探讨是采纳推模式、拉模式或推拉模式联合形式。在华为云PB级数据库GaussDB(for Redis)揭秘第五期:高斯 Redis 在IM场景中的利用 也有过探讨。推模式,在查问完关联关系后,将Feed告诉写入到每个Feed消费者的收件箱中,Feed消费者查问本人的收件箱就能获取残缺的Feed流,告诉会写入每个须要告诉的人收件箱,写会放大。 拉模式,将Feed告诉写入本人的发件箱,Feed消费者先查问关系库,而后从所有关注人的发件箱中获取Feed音讯后合并展现,因而收件箱被读次数和被关注人数目无关,读会放大。 推拉模式联合:针对大多数用户的写入用推模式,特定用户采纳拉模式,Feed消费者读取时别离读取本人的收件箱和特定用户的发件箱,合并之后展现。 到底选用哪种模式,看具体业务场景和要求。 很多业务在具体实现的时候,会先将音讯写入音讯队列,一方面能够起到流量削峰的作用,另一方面能够实现一些特定的推送优化逻辑,如判断为垃圾广告或者敏感词不进行推送。 四、技术挑战咱们首先从微信朋友圈颁布的数据来感受一下。在2021年1月19日,在微信公开课Pro上微信创始人张小龙披露微信最新数据:微信每天有7.8亿用户进入朋友圈,1.2亿用户发表朋友圈。均匀每人关上浏览十几次,每天100亿次浏览量。若咱们想实现相似的Feed流零碎会有什么挑战。从存储量上来看,若用户均匀每天发送3次朋友圈,每条内容1kB,一年大概1000亿条记录,存储容量靠近100TB。从拜访申请次数来看,每天写入和读取OPS峰值至多百万级别,用户写入和读取提早都要有实时性,响应工夫至多都要在秒级内,否则用户分分钟敞开APP。因而咱们须要一个长久化、海量存储、高吞吐、易扩大、低提早、低存储老本的分布式存储系统。 五、高斯Redis的劣势5.1 高斯Redis简介 高斯Redis是华为云数据库团队自主研发且兼容Redis5.0协定的云原生数据库,采纳计算存储拆散架构。存储侧应用自研的存储系统DFV,容量有限扩大、强统一、高牢靠。计算侧基于 LSM 存储引擎实现,具备极佳的写性能和读性能。利用计算拆散架构的劣势,高斯Redis扩容无需进行数据拷贝,实现秒级扩容,充分发挥了云原生的弹性伸缩、资源共享的劣势。 5.2 Feed流场景如何利用高斯Redis劣势针对Feed流场景,能够依照如下形式应用高斯Redis: 音讯内容存储利用高斯Redis的KV构造即可实现,高斯Redis采纳存储计算拆散架构,能够轻松撑持海量数据存储及低提早拜访提早。关联关系存储高斯Redis汇合构造或字典构造能够轻松实现关联关系的增删改查。信箱存储信箱从实现上就是一个队列,反对从指定地位生产的能力。高斯Redis的Stream构造能够实现队列能力,轻松实现Feed流音讯读取。5.3 高斯Redis Feed流实际以下用高斯Redis实现一个简略的微博样例,采纳写扩散模型,用以阐明可行性。零碎中存在四个用户,Jay、Jolin、ZhangSan、LiSi。其中ZhangSan、LiSi关注了Jay,LiSi同时关注了Jolin。 以上实现了一个简略的微博零碎,实在零碎会比这个简单,会波及业务场景特定解决逻辑。用高斯Redis作为Feed流存储底座是比拟现实的技术选型。 六、总结高斯Redis具备长久化、海量存储、高吞吐、易扩大、低提早、低存储老本等长处, 作为Feed流存储底座十分适合,其优异的读写性能和高级个性将会极大简化利用开发。同时,高斯Redis在开源Redis根底之上,较好均衡了性能和老本,可能广泛应用在智慧医疗、流量削峰、计数器等畛域。 七、完结本文作者:华为云高斯Redis团队。更多技术文章,关注高斯Redis官网博客:https://bbs.huaweicloud.com/community/usersnew/id_1614151726110813 八、参考资料《GaussDB(for Redis)官方主页》https://www.huaweicloud.com/product/gaussdbforredis.html《华为云GaussDB(for Redis)与自建开源Redis的老本比照》https://www.modb.pro/db/42739《华为云PB级数据库GaussDB(for Redis)揭秘第一期:Redis与存算拆散》https://bbs.huaweicloud.com/blogs/238584《华为云PB级数据库GaussDB(for Redis)揭秘第二期:Redis音讯队列Stream的利用探讨》https://bbs.huaweicloud.com/blogs/245623《华为云PB级数据库GaussDB(for Redis)揭秘第五期:高斯 Redis 在IM场景中的利用》https://bbs.huaweicloud.com/blogs/249247《feed流拉取,读扩散,到底是啥?》https://cloud.tencent.com/dev...《朋友圈微博feed流,推拉实际》https://cloud.tencent.com/dev...点击关注,第一工夫理解华为云陈腐技术~

March 25, 2021 · 1 min · jiezi

关于docker:Docker启动MySQLMongoDBRedisElasticsearchGrafana数据库

前言: 长期应用数据库时能够应用docker运行,这样能够避免在零碎上装置毁坏环境,同时应用docker启动会比在零碎中装置配置要疾速,能够说是最快的形式装置部署并启动数据库。 docker配置启动运行MySQL 首先创立目录并进入 sudo docker run -p 3306:3306 \\--name mymysql \\--restart=always \\-v $PWD/conf:/etc/mysql/conf.d \\-v $PWD/logs:/logs \\-v $PWD/data:/var/lib/mysql \\-e MYSQL\_ROOT\_PASSWORD=123456 \\-d mysql:8--restart=always:在容器退出时总是重启容器 MYSQL\_ROOT\_PASSWORD=123456:root明码123456 mysql:8  应用MySQL8 -v $PWD/conf:/etc/mysql/conf.d  配置文件 -v $PWD/logs:/logs   日志 -v $PWD/data:/var/lib/mysql    数据 docker配置启动运行phpMyAdmin docker run -d \\ -p 8001:80 \\ -e UPLOAD\_LIMIT=128M \\ -e MAX\_EXECUTION\_TIME=10000 \\ --name phpmyadmin \\ phpmyadmin/phpmyadminUPLOAD\_LIMIT 和 MAX\_EXECUTION\_TIME 须要设置一下 *docker配置启动运行MongoDB* docker run -d \\ -p 27017:27017 \\ -v mongo-data:/data/db \\ -v mongo-config:/data/configdb \\ --name mongo \\ -e MONGO\_INITDB\_ROOT\_USERNAME=mongoadmin \\ -e MONGO\_INITDB\_ROOT\_PASSWORD=123123 \\ -v /data:/mnt/data \\ mongoMONGO\_INITDB\_ROOT\_USERNAME 用户名 ...

March 24, 2021 · 1 min · jiezi

关于redis:Redis的持久化数据备份方案和数据恢复

文章首发:Redis的长久化、数据备份计划和数据恢复 redis的长久化RDB长久化redis会fork创立一个子过程来进行长久化。将数据写进一个临时文件,长久化完结之后会替换上一个长久化好的RDB文件。在这期间redis主过程不会参加长久化,以保障redis的高性能。 触发: 客户端在执行shutdown命令时,如果没有开启AOF长久化,那么就会触发RDB的长久化。在redis的配置文件中有以下默认配置。在一下的条件成立时,就会触发RDB的长久化,而且是应用save命令实现的。然而save命令会阻塞主过程。个别应用bgsave命令,会fork出一个子过程进行长久化操作。 save 900 1 #after 900 sec (15 min) if at least 1 key changedsave 300 10 #after 300 sec (5 min) if at least 10 keys changedsave 60 10000 #after 60 sec if at least 10000 keys changed执行flushall命令清空内存中的数据时,同时触发长久化,清空磁盘。长处和毛病 长处:数据恢复比拟快,适宜大规模的数据恢复,适宜当作冷备的计划。 毛病:如果是忽然宕机,失落的数据比拟多。数据量大时,长久化生成快照RDB文件会影响redis的性能。 AOF长久化开启了AOF之后,会将所有命令追加到AOF缓冲区中,依据对应的写入策略写入到磁盘的AOF的长久化文件中。能够说就是redis的一个日志文件,外面记录的是redis的写操作。然而因为记录的是一条条命令,AOF文件会收缩的很快,达到一定量的时候,就会触发rewrite操作,重写AOF文件,来达到压缩的目标(fork子过程来实现)。 redis 应用单线程响应命令,如果每次写 AOF 文件命令都间接追加到硬盘,那么性能瓶颈齐全取于以后硬盘负载。先写入缓冲区 aof_buf 中,还有另一益处,redis 能够提供多种缓冲区同步硬盘的策略,在性能和安全性方面做出衡量。 触发: redis的配置文件中默认是没有开启AOF的,要开启在配置文件中关上即可appendonly no --->appendonly yes。也能够在redis曾经运行时设置:CONFIG SET appendonly yes,不过这样当redis重启时,设置会生效。配置的写入策略触发。 appendfsync everysec(默认):每秒同步一次命令到AOF长久化文件中,效率很高,可能会失落1秒的数据。appendfsync no:从不同步,只需将数据交给操作系统即可。更快,更不平安的办法。通常,Linux将应用此配置每30秒刷新一次数据,但这取决于内核的准确调整。appendfsync always:每次触发数据变更的时候立刻追加到AOF文件中,效率很低,然而很平安。重写机制: 默认配置。比如说上一次AOF rewrite之后,是128mb。而后就会接着128mb持续写AOF的日志,如果发现增长的比例,超过了之前的100%,256mb,就可能会去触发一次rewrite。然而此时还要去跟min-size,64mb去比拟,256mb > 64mb,才会去触发rewrite。 ...

March 24, 2021 · 1 min · jiezi

关于redis:redis缓存回收策略

redis-缓存回收策略Redis 缓存应用了内存保留数据,使数据的存储和读取都失去了极大的晋升,然而因为计算机中“内存”的造价却在磁盘的数百倍之上;这也导致咱们无奈应用 Redis 缓存所有的数据; 那样也衍生出一个问题:当Redis中缓存的数据大小,达到下限后,redis 会作出怎么的操作? 为了解决这个问题,redis 有着本身保护的一套 缓存数据的淘汰机制;其实简略来说 就是分成两步: 依据指定规定筛选出能够"放弃"的 key值开释对应key值的空间,用于保留新的Key值如何设置 redis 的内存暂用值Redis 中有一个 maxmemory 的概念,次要是为了将 redis 的应用内存限定在一个固定的大小,当应用内存超出限定值后,依据 maxmemory-policy 配置的策略进行内存回收; maxmemory 的设定值有如下两种形式:第一种:通过 congfig set 命令进行设置: 127.0.0.1:6379> config get maxmemory1) "maxmemory"2) "0"127.0.0.1:6379> config set maxmemory 1024MBOK127.0.0.1:6379> config get maxmemory1) "maxmemory"2) "1073741824"第二种:通过 redis.conf 文件批改 maxmemory 1024MB留神: 不配置 maxmemory 的值时,将默认为0; 64 bit零碎:maxmemory 设置为 0 示意不限度 Redis 内存应用 32 bit零碎:maxmemory 设置为 0 示意限度 Redis 内存 不能超过 3G。 (造成这个当初的其实是系统对内存应用的限度造成的,并不是redis造成的,有趣味能够理解下 不同 bit 系统对内存的利用) Redis 缓存有哪些策略Redis4.0 之前共实现了6种内存策略,之后又减少了两种内存策略;次要能够分成两类: ...

March 24, 2021 · 3 min · jiezi

关于redis:Redis持久化及内存优化-springboot实战电商项目mall4j

springboot实战电商我的项目mall4j (https://gitee.com/gz-yami/mall4j) Redis长久化及内存优化通过redis的配置文件来进行的一些长久化及内存优化操作,如有谬误欢送领导。 1. 为什么须要长久化如果将用户数据保留到内存中,在服务器断电或者宕机时则会导致内存数据将清空,导致缓存数据清空。 2. 对于长久化文件应用流程在咱们装置了redis之后,所有的配置都在redis.conf文件中,外面保留了RDB和AOF两种长久化机制的各种配置。 命令: save: 示意以后数据长久化一次,生成RDB文件。 bgsave: 内存数据在后盾长久化一次,生成RDB文件。命令区别: save: 当执行save指令时不容许用户持续set操作,陷入阻塞。 bgsave: 当执行bgsave时,示意告诉redis须要进行长久化操作了,这时redis会依据用户的应用状况进行长久化,不会陷入阻塞,相似于gc(垃圾回收机制)。长久化文件应用规定: 当程序失常运行时会生成长久化文件,如果当服务器宕机后重启时,会依据配置文件中指定的长久化文件,进行数据的复原。3. RDB模式3.1 阐明:RDB劣势 RDB模式是redis默认的长久化策略,文件紧凑,全量备份,非常适合用于进行备份和劫难复原。生成RDB文件的时候,redis主过程会fork()一个子过程来解决所有保留工作,主过程不须要进行任何磁盘IO操作。RDB 在复原大数据集时的速度比 AOF 的复原速度要快。RDB模式每次操作时记录内存数据的快照,长久化文件较小。RDB问题: 1.耗时,内存耗费,IO性能耗费,将内存中的所有数据转储到硬盘上须要破费肯定的工夫工夫。Bgsave模式fork()子过程占用额定的内存,大量的硬盘读写也会耗费IO性能。 2.无法控制的数据失落,在停机期间,上次快照之后写入的内存数据将失落。 3.2 批改长久化文件的名称和长久化文件保留的门路 3.3 RDB模式默认快照形式save 900 1 在900s之内,至多有1个key发生变化,则将快照写入磁盘。save 300 10 在300之内,至多有10个key发生变化,则将快照写入磁盘。save 60 10000 在60s之内,至多有10000个key发生变化,则将快照写入磁盘。4. AOF模式4.1什么是AOFRedis的RDB模式全量备份总是耗时的,AOF模式是对RDB模式的补充。当开启AOF模式(两种都关上时AOF的优先级高于RDB模式)时,每次执行redis write命令时,该命令会同时记录日志(以AOF结尾的日志文件)。当Redis产生故障时,只有执行日志回放,就能够复原数据。 4.2 开启AOF模式批改Redis配置文件,改为yes即可。 4.3 AOF的长久化策略 #appendfsync always #每次有数据发生变化时都会写入appendonly.aof #appendfsync everysec #默认形式,每秒同步一次到appendonly.aof #appendfsync no #不同步,数据不会长久化 no-appendfsync-on-rewrite no  #当AOF日志文件行将增长到指定百分比时,redis通过调用BGREWRITEAOF是否主动重写AOF日志文件。通常应用everysec策略,这也是AOF的默认策略。 4.4 AOF日志重写性能当AOF的日志文件过大,redis会主动重写AOF日志,append模式一直的将更新记录写入到老日志文件中,同时redis还会创立一个新的日志文件用于追加后续的记录。 Aof重写能够大大减小最终日志文件的大小。从而缩小磁盘耗费并放慢数据恢复。例如,咱们有一个计数服务,该计数服务具备许多主动递增操作,例如将密钥主动递增到1亿,这对于AOF文件来说是1亿incr。Aof重写仅记录一个记录。 4.5 两种AOF重写的办法Bgrewriteaof命令触发AOF重写Redis客户端将bgrewriteaof命令发送到Redis,并且Redis服务器派生一个子过程来实现AOF重写。此处的AOF重写是将Redis内存中的数据追溯到AOF文件。而不是重写AOF文件以生成要替换的新AOF文件。 AOF 重写配置 auto-aof-rewrite-min-size:重写AOF文件所需的大小auto-aof-rewrite-percentage :AOF文件增长aof\_current\_size:计算AOF的以后大小(字节)aof\_base\_size:上一次启动和重写AOF的大小(字节)AOF主动重写的触发工夫应同时满足以下两点: aof\_current\_size > auto-aof-rewrite-min-sizeaof\_current\_size - aof\_base\_size/aof\_base\_size > auto-aof-rewrite-percentage5. RDB和AOF比照命令RDBAOF阐明启动优先级低高当同时启用RDB和AOF时,重新启动Redis后抉择AOF进行复原。在大多数状况下,它保留的数据比RDB更新体积小大RDB以二进制模式存储并压缩。只管AOF被AOF重写,然而它的容量绝对较大。毕竟它是以日志记录的模式复原速度快慢RDB体积小,复原速度较快。AOF量大,复原迟缓。数据安全丢数据依据策略决定RDB在最初一个快照后会失落数据。AOF依据Always,everysec和No的策略来决定是否失落数据。轻重重轻Aof是一个追加日志,因而它是一个轻量级的操作。RDB是一项占用大量CPU的操作,会占用大量磁盘以及对内存耗费会比拟大。6. Redis内存优化策略Redis反对多种内存驱赶策略以限度内存使用量,局部基于LRU和LFU的算法。 ...

March 24, 2021 · 1 min · jiezi

关于java:使用Redis你必须知道的21个注意要点

1、Redis的应用标准1.1、 key的标准要点咱们设计Redis的key的时候,要留神以下这几个点: 以业务名为key前缀,用冒号隔开,以避免key抵触笼罩。如,live:rank:1确保key的语义清晰的状况下,key的长度尽量小于30个字符。key禁止蕴含特殊字符,如空格、换行、单双引号以及其余转义字符。Redis的key尽量设置ttl,以保障不应用的Key能被及时清理或淘汰。1.2、value的标准要点Redis的value值不能够随便设置的哦。 第一点,如果大量存储bigKey是会有问题的,会导致慢查问,内存增长过快等等。 如果是String类型,单个value大小管制10k以内。如果是hash、list、set、zset类型,元素个数个别不超过5000。第二点,要抉择适宜的数据类型。不少小伙伴只用Redis的String类型,上来就是set和get。实际上,Redis 提供了丰盛的数据结构类型,有些业务场景,更适宜hash、zset等其余数据后果。 反例: set user:666:name jayset user:666:age 18复制代码正例 hmset user:666 name jay age 18 复制代码1.3. 给Key设置过期工夫,同时留神不同业务的key,尽量过期工夫扩散一点因为Redis的数据是存在内存中的,而内存资源是很贵重的。咱们个别是把Redis当做缓存来用,而不是数据库,所以key的生命周期就不宜太长久啦。因而,你的key,个别倡议用expire设置过期工夫。如果大量的key在某个工夫点集中过期,到过期的那个工夫点,Redis可能会存在卡顿,甚至呈现缓存雪崩景象,因而个别不同业务的key,过期工夫应该扩散一些。有时候,同业务的,也能够在工夫上加一个随机值,让过期工夫扩散一些。 1.4.倡议应用批量操作提高效率咱们日常写SQL的时候,都晓得,批量操作效率会更高,一次更新50条,比循环50次,每次更新一条效率更高。其实Redis操作命令也是这个情理。 Redis客户端执行一次命令可分为4个过程:1.发送命令-> 2.命令排队-> 3.命令执行-> 4. 返回后果。1和4 称为RRT(命令执行往返工夫)。 Redis提供了批量操作命令,如mget、mset等,可无效节约RRT。然而呢,大部分的命令,是不反对批量操作的,比方hgetall,并没有mhgetall存在。Pipeline 则能够解决这个问题。 Pipeline是什么呢?它能将一组Redis命令进行组装,通过一次RTT传输给Redis,再将这组Redis命令的执行后果按程序返回给客户端.咱们先来看下没有应用Pipeline执行了n条命令的模型: 应用Pipeline执行了n次命令,整个过程须要1次RTT,模型如下: 2、Redis 有坑的那些命令2.1. 慎用O(n)复杂度命令,如hgetall、smember,lrange等因为Redis是单线程执行命令的。hgetall、smember等命令工夫复杂度为O(n),当n继续减少时,会导致 Redis CPU 继续飙高,阻塞其余命令的执行。 hgetall、smember,lrange等这些命令不是肯定不能应用,须要综合评估数据量,明确n的值,再去决定。 比方hgetall,如果哈希元素n比拟多的话,能够优先思考应用hscan。2.2 慎用Redis的monitor命令Redis Monitor 命令用于实时打印出Redis服务器接管到的命令,如果咱们想晓得客户端对redis服务端做了哪些命令操作,就能够用Monitor 命令查看,然而它个别调试用而已,尽量不要在生产上用!因为monitor命令可能导致redis的内存继续飙升。 monitor的模型是酱紫的,它会将所有在Redis服务器执行的命令进行输入,一般来讲Redis服务器的QPS是很高的,也就是如果执行了monitor命令,Redis服务器在Monitor这个客户端的输入缓冲区又会有大量“存货”,也就占用了大量Redis内存。 2.3、生产环境不能应用 keys指令Redis Keys 命令用于查找所有合乎给定模式pattern的key。如果想查看Redis 某类型的key有多少个,不少小伙伴想到用keys命令,如下: keys key前缀*复制代码然而,redis的keys是遍历匹配的,复杂度是O(n),数据库数据越多就越慢。咱们晓得,redis是单线程的,如果数据比拟多的话,keys指令就会导致redis线程阻塞,线上服务也会进展了,直到指令执行完,服务才会复原。因而,个别在生产环境,不要应用keys指令。官网文档也有申明: Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases. This command is intended for debugging and special operations, such as changing your keyspace layout. Don't use KEYS in your regular application code. If you're looking for a way to find keys in a subset of your keyspace, consider using sets.其实,能够应用scan指令,它同keys命令一样提供模式匹配性能。它的复杂度也是 O(n),然而它通过游标分步进行,不会阻塞redis线程;然而会有肯定的反复概率,须要在客户端做一次去重。 ...

March 23, 2021 · 2 min · jiezi

关于redis:并不复杂只需4步搞定Shiro集成redis实现会话共享

我的公众号:MarkerHub,Java网站:https://markerhub.com更多精选文章请点击:Java笔记大全.md 小Hub领读:集群的分布式场景中,咱们须要把泛滥服务的会话状态保持一致,常见的就是把会话信息保留到redis中实现共享,那么你晓得shiro集成redis实现会话共享有多简略吗?真的只须要4步! 在一些分布式场景中,比方一个简略负载平衡场景,一个nginx,反向代理到两个tomcat,tomcat运行这同样的我的项目,那么这时候,服务的会话须要共享,因为咱们曾经应用了shiro来实现咱们的认证受权逻辑,那么shiro实现登录之后,如何让另外一个服务同时也是登录状态呢? 咱们延用上篇文章的我的项目代码,应用两个端口8080、8081别离启动我的项目。 http://localhost:8080http://localhost:8081有些同学不晓得怎么用idea同一个我的项目别离启动两个端口,其实很简略,只须要在Run/Debug Configurations的VM options上,指定启动端口-Dserver.port=8081即可! ok,别离启动8080和8081我的项目之后,登录8080我的项目,而后拜访8081,发现8081未登录!图示如下: 那么,如何能力8080登录之后,8081也同时实现登录呢? 非凡解决形式其实在负载平衡集群中,有些人是这样解决问题,给ip指定服务,比方某个用户申请通过nginx反向代理到8080服务,那么nginx上指定ip_hash:根据ip调配形式,那么这个用户就始终拜访同一个服务,不会拜访到8081服务,所以用户就始终是拜访对立服务,所以在用户看来,他就始终是登录状态的。 然而,这是有缺点的,因为ip和服务绑定了,退出这个服务挂了之后,是不会转发到其余服务,所以对这用户来说,就拜访异样。 所以咱们须要应用更罕用的负载平衡策略,比方轮询、权重等。 回顾shiro的架构与组件ok,进入正题,shiro做会话共享,会话信息能够存储到内存,数据库,或者缓存中间件中,这里咱们应用一个罕用的缓存中间件Redis来保留咱们的会话信息,那么,咱们就须要shiro集成redis。 能够回顾一下之前咱们介绍过的shiro的整体架构: 下面与会话或缓存相干的组件有: Session Manager 会话管理器Session DAO 会话 DAO,将session保留到数据库、缓存等Cache Manager 缓存管理器,权限认证的缓存、用户及权限信息的缓存等如果只是做会话共享,只是改写Session DAO如同也是能够的,我之前试过,不过既然shiro曾经集成redis,那么数据啥的最好也一起共享吧,防止出现缓存不统一的状况。依照这个逻辑,其实就是重写这3个组件就行了。 shiro-redis整合步骤那么,有什么曾经写好的shiro集成redis整合我的项目嘛? 这里给大家介绍一个 https://github.com/alexxiyang/shiro-redis/# 文档https://github.com/alexxiyang/shiro-redis/blob/master/docs/README.md# 或者http://alexxiyang.github.io/shiro-redis/readme.md上有具体的教程,这里咱们间接应用Spring boot starter形式,因为须要写的代码少,间接写写配置就好。 第一步:导入shiro-redis的starter包 <dependency> <groupId>org.crazycake</groupId> <artifactId>shiro-redis-spring-boot-starter</artifactId> <version>3.2.1</version></dependency>能够看下shiro-redis-spring-boot-starter源码: 能够看出,曾经蕴含了shiro-spring-boot-web-starter与shiro-redis整合包了,所以之前我的项目中整合进来的shiro-spring-boot-web-starter能够正文掉了。 第二步,依据阐明,readme外面说,如果你没有自定义创立SessionManager or SessionsSecurityManager,那么会主动给你创立,集成实现。然而咱们自定义了realm,所以SecurityManager还是必须要自定义的。 com.markerhub.config.ShiroConfig@Configurationpublic class ShiroConfig { @Autowired RedisSessionDAO redisSessionDAO; @Autowired RedisCacheManager redisCacheManager; @Bean AccountRealm accountRealm() { return new AccountRealm(); } @Bean public SessionManager sessionManager() { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); // inject redisSessionDAO sessionManager.setSessionDAO(redisSessionDAO); return sessionManager; } @Bean public DefaultWebSecurityManager securityManager(AccountRealm accountRealm, SessionManager sessionManager) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(accountRealm); //inject sessionManager securityManager.setSessionManager(sessionManager); // inject redisCacheManager securityManager.setCacheManager(redisCacheManager); return securityManager; } @Bean public ShiroFilterChainDefinition shiroFilterChainDefinition() { DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition(); // logged in users with the 'admin' role chainDefinition.addPathDefinition("/admin/**", "authc, roles[admin]"); // logged in users with the 'document:read' permission chainDefinition.addPathDefinition("/docs/**", "authc, perms[document:read]"); chainDefinition.addPathDefinition("/login", "anon"); chainDefinition.addPathDefinition("/doLogin", "anon"); // all other paths require a logged in user chainDefinition.addPathDefinition("/**", "authc"); return chainDefinition; }}相比之前的配置,多了配置了个SessionManager,而后对应配置中注入sessionManager和redisCacheManager。如同我的项目就曾经能够运行啦。 ...

March 23, 2021 · 1 min · jiezi

关于java:实战问题-缓存穿透缓存击穿和缓存雪崩的区别以及解决方案

平时咱们应用缓存的计划,个别是在数据库中存储一份,在缓存中同步存储一份。当申请过去的视乎,能够先从缓存中取数据,如果有数据,间接返回缓存中的后果。如果缓存中没有数据,那么去数据库中取出数据,同时更新到缓存中,返回后果。如果数据库中也没有数据,能够间接返回空。 对于缓存,个别会有以下几个常见的问题 缓存穿透缓存穿透是指,缓存和数据库都没有的数据,被大量申请,比方订单号不可能为-1,然而用户申请了大量订单号为-1的数据,因为数据不存在,缓存就也不会存在该数据,所有的申请都会间接穿透到数据库。如果被歹意用户利用,疯狂申请不存在的数据,就会导致数据库压力过大,甚至垮掉。 留神:穿透的意思是,都没有,间接一路打到数据库。 那对于这种状况,咱们该如何解决呢? 接口减少业务层级的Filter,进行非法校验,这能够无效拦挡大部分不非法的申请。作为第一点的补充,最常见的是应用布隆过滤器,针对一个或者多个维度,把可能存在的数据值hash到bitmap中,bitmap证实该数据不存在则该数据肯定不存在,然而bitmap证实该数据存在也只能是可能存在,因为不同的数值hash到的bit位很有可能是一样的,hash抵触会导致误判,多个hash办法也只能是升高抵触的概率,无奈做到防止。另外一个常见的办法,则是针对数据库与缓存都没有的数据,对空的后果进行缓存,然而过期工夫设置得较短,个别五分钟内。而这种数据,如果数据库有写入,或者更新,必须同时刷新缓存,否则会导致不统一的问题存在。缓存击穿缓存击穿是指数据库本来有得数据,然而缓存中没有,个别是缓存忽然生效了,这时候如果有大量用户申请该数据,缓存没有则会去数据库申请,会引发数据库压力增大,可能会霎时打垮。 针对这类问题,个别有以下做法: 如果是热点数据,那么能够思考设置永远不过期。如果数据肯定会过期,那么就须要在数据为空的时候,设置一个互斥的锁,只让一个申请通过,只有一个申请去数据库拉取数据,取完数据,不论如何都须要开释锁,异样的时候也须要开释锁,要不其余线程会始终拿不到锁。上面是缓存击穿的时候互斥锁的写法,留神:获取锁之后操作,不论胜利或者失败,都应该开释锁,而其余的申请,如果没有获取到锁,应该期待,再重试。当然,如果是须要更加全面一点,应该加上一个期待次数,比方1s中,那么也就是睡眠五次,达到这个阈值,则间接返回空,不应该适度耗费机器,免得当个不可用的场景把整个利用的服务器带挂了。 public static String getProductDescById(String id) { String desc = redis.get(id); // 缓存为空,过期了 if (desc == null) { // 互斥锁,只有一个申请能够胜利 if (redis.setnx(lock_id, 1, 60) == 1) { try { // 从数据库取出数据 desc = getFromDB(id); redis.set(id, desc, 60 * 60 * 24); } catch (Exception ex) { LogHelper.error(ex); } finally { // 确保最初删除,开释锁 redis.del(lock_id); return desc; } } else { // 否则睡眠200ms,接着获取锁 Thread.sleep(200); return getProductDescById(id); } } }缓存雪崩缓存雪崩是指缓存中有大量的数据,在同一个工夫点,或者较短的时间段内,全副过期了,这个时候申请过去,缓存没有数据,都会申请数据库,则数据库的压力就会突增,扛不住就会宕机。 ...

March 22, 2021 · 1 min · jiezi

关于redis:我是如何用-redis-做实时订阅推送的

我的公众号:MarkerHub,Java网站:https://markerhub.com更多精选文章请点击:Java笔记大全.md 小Hub领读:20w+的推送用户,如何做到秒级并发实现,文中别离介绍了MQ、传统定时工作以及Redis的SortSet队列三种计划,一一剖析可行性,并且最初给出了Redis的逻辑与局部代码实现。你学会了吗? 作者:我是林林https://www.cnblogs.com/linli...前阵子开发了公司领劵核心的我的项目,这个我的项目是以 redis 作为关键技术落地的。 先说一下领劵核心的我的项目吧,这个我的项目就相似京东 app 的领劵核心,当然图是截取京东的,公司的就不截了。。。 其中有一个性能叫做领劵的订阅推送。 什么是领劵的订阅推送? 就是用户订阅了该劵的推送,在可支付前的一分钟就要把揭示信息推送到用户的 app 中。 原本这个订阅性能应该是音讯核心那边做的,但他们说这个短时间内做不了。所以让我这个负责优惠劵的做了 -.-!。具体计划就是到具体的推送工夫点了,coupon 零碎调用音讯核心的推送接口,把信息推送进来。 下们咱们剖析一下这个性能的业务情景。公司目前注册用户 6000W+,是哪家就不要打听了。。。比方有一张无门槛的优惠劵下单立减 20 元,那么抢这张劵的人就会比拟多,咱们激进预计 10W+,百万级别不好说。咱们初定为 20W 万人,那么这 20W 条推送信息要在一分钟推送实现!并且一个用户是能够订阅多张劵的。所以咱们晓得了这个订阅性能的有两个突出的难点: 推送的实效性:推送慢了,用户会埋怨没有及时告诉他们错过了开抢机会。推送的体量大:爆款的神劵,人人都想抢!然而推送体量又会影响到推送的实效性。这真是一个让人头疼的问题! 那就让咱们把问题一个个解决掉吧! 推送的实效性的问题:当用户在领劵核心订阅了某个劵的支付揭示后,在后盾就会生成一条用户的订阅揭示记录,外面记录了在哪个工夫点给用户发送推送信息。所以问题就变成了零碎如何疾速实时选出哪些要推送的记录! 计划 1: MQ 的提早投递。MQ 尽管反对音讯的提早投递但尺度太大 1s 5s 10s 30s 1m,用来做准确工夫点投递不行!并且用户执行订阅之后又勾销订阅的话,要把收回去的 MQ 音讯 delete 掉这个操作有拍板大,短时间内难以落地!并且用户能够勾销之后再订阅,这又波及到去重的问题。所以 MQ 的计划否掉。 计划 2: 传统定时工作。这个相对来说就简略一点,用定时工作是去 db 外面 load 用户的订阅揭示记录,从中选出以后能够推送的记录。但有句话说得好任何脱离实际业务的设计都是耍流氓~。上面咱们就剖析一下传统的定时工作到底适不适宜咱们的这个业务! 是否反对多机同时跑个别不能,同一时刻只能单机跑。存储数据源个别是 mysql 或者其它传统数据库,并且是单表存储频率反对秒、分、时、天,个别不能太快综上所述咱们就晓得了个别传统的定时工作存在以下毛病:1. 性能瓶颈。只有一台机在解决,在大体量数据背后力不从心! 2. 实效性差。定时工作的频率不能太高,太高会业务数据库造成很大的压力! 3. 单点故障。万一跑的那台机挂了,那整个业务不可用了 -。- 这是一个很可怕的事件! 所以传统定时工作也不太适宜这个业务。。。 那咱们是不是就大刀阔斧了呢?其实不是的! 咱们只有对传统的定时工作做一个简略的革新!就能够把它变成能够同时多机跑, 并且实效性能够准确到秒级,并且回绝单点故障的定时工作集群!这其中就要借助咱们的弱小的 redis 了。计划 3:定时工作集群首先咱们要定义定时工作集群要解决的三个问题!     1、实效性要高     2、吞吐量要大     3、服务要稳固,不能有单点故障 上面是整个定时工作集群的架构图。  架构很简略:咱们把用户的订阅推送记录存储到 redis 集群的 sortedSet 队列外面, 并且以揭示用户揭示工夫戳作为 score 值,而后在咱们个每业务 server 外面起一个定时器频率是秒级,我的设定就是 1s,而后通过负载平衡之后从某个队列外面获取要推送的用户记录进行推送。上面咱们剖析以下这个架构。    1、性能:除去带宽等其它因素,根本与机器数成线性相关。机器数量越多吞吐量越大,机器数量少时绝对的吞吐量就缩小。    2、实效性:进步到了秒级,成果还能够承受。    3、单点故障?不存在的!除非 redis 集群或者所有 server 全挂了。。。。这里解析一下为什么用 redis?第一 redis 能够作为一个高性能的存储 db,性能要比 MySQL 好很多,并且反对长久化,稳定性好。第二 redis SortedSet 队列人造反对以工夫作为条件排序,完满满足咱们选出要推送的记录。ok~ 既然计划曾经有了那如何在一天工夫内把这个计划落地呢?是的我设计出这个计划到根本编码实现,工夫就是一天。。。 因为工夫太赶鸟。首先咱们以 user_id 作为 key,而后 mod 队列数 hash 到 redis SortedSet 队列外面。为什么要这样呢,因为如果用户同时订阅了两张劵并且推送工夫很近,这样的两条推送就能够合并成一条~,并且这样 hash 也绝对平均。上面是局部代码的截图:  而后要决定队列的数量,个别失常来说咱们有多少台解决的服务器就定义多少条队列。因为队列太少,会造成队列竞争,太多可能会导致记录得不到及时处理。然而最佳实际是队列数量应该是可动静配置化的,因为线上的集群机器数是会常常变的。大促的时候咱们会加机器是不是,并且业务量增长了,机器数也是会减少是不是~。所以我是借用了淘宝的 diamond 进行队列数的动静配置。 咱们每次从队列外面取多少条记录也是能够动静配置的 这样就能够随时依据理论的生产状况调整整个集群的吞吐量~。  所以咱们的定时工作集群还是具备一个个性就是反对动静调整~。最初一个要害组件就是负载平衡了。这个是十分重要的!因为这个做得不好就会可能导致多台机竞争同时解决一个队列,影响整个集群的效率!在工夫很紧的状况下我就用了一个简略实用的利用 redis 一个自增 key 而后 mod 队列数量算法。这样就很大水平上就保障不会有两台机器同时去竞争一条队列~.最初咱们算一下整个集群的吞吐量10(机器数) * 2000(一次拉取数) = 20000。而后以 MQ 的模式把音讯推送到音讯核心,发 MQ 是异步的,算上其它解决 0.5s。其实发送 20W 的推送也就是 10 几 s 的事件。ok~ 到这里咱们整个定时工作集群就差不多根本落地好了。如果你问我前面还有什么能够欠缺的话那就是:* 加监控, 集群怎么能够木有监控呢,万一出问题有工作沉积怎么办~ * 加上可视化界面。 * 最好有智能调度,减少工作优先级。优先级高的工作先运行嘛。 * 资源调度,万一机器数量不够,力不从心,优先保障重要工作执行。 目前我的项目已上火线,运行安稳~。### 举荐浏览Java笔记大全.md太赞了,这个Java网站,什么我的项目都有!https://markerhub.com这个B站的UP主,讲的java真不错!

March 20, 2021 · 1 min · jiezi

关于java:开源电商宝塔宝塔使用和站点创建

【开源电商宝塔】宝塔应用和站点创立 Hello 大家好 我是大粽子。 持续咱们开源电商系列-今日次要聊些宝塔的应用和站点的根本创立。 开篇宝塔,哈哈,一个有争议的工具,有的大佬用的行云流水,有的大佬却一点也不愿用,因为自身就占用资源。所以他还是违心在黑框框中敲命令,查看cpu和过程做剖析,当然这也是最极客的做法。至于这个争议咱们前面列出一篇来持续聊。 宝塔装置和下载 :https://www.bt.cn/?invite\_code=MV90c2l1cmY=浏览器新建标签页,输出服务器公网地址ip,前面加:8888,例如 1.2.3.4:8888 (服务器公网地址IP可在云服务器ECS → 实例 查看) 2.删除默认用户名,创立设置你的用户名和明码,确定,登陆。 3.左上角注册宝塔帐号,登陆。 4.点击左侧菜单软件治理 5.宝塔装置系统软件: 宝塔终端 ---> 启动Java子项目须要应用 2. Redis5+ ---> Java子项目缓存 3. Mysql5.7 ---> 数据存储 4. Nginx1.17 ---> web服务 期待软件全副装置完结,进入下步。 创立站点 以宝塔为例:解析域名,详情依据不同云服务提供商操作即可,只有解析行将要创立的域名即可,个别解析后10分钟左右失效。在宝塔上新创建4个动态站点进入宝塔点击左侧网站,点击右侧增加站点,会弹出窗口,请按下图设置ftp此处可不创立,如果须要前面能够在ftp模块创立,留神ftp须要开启21端口按照上图创立4个站点站点里填写的域名是下面解析的4个域名,别离要对应好我的项目文件夹,(图片拜访非凡解决)设置https证书,宝塔有收费证书可设置,在网站列表点击申请后会弹出窗口,有申请流程揭示,申请胜利之后如下图操作,站点https证书设置实现Mysql数据库创立(如果对代码足够相熟,也能够在上一步间接创立数据库)抉择权限阐明本地服务器 ---> 只有线上我的项目能够拜访所有人(不平安) ---> 此设置不平安,尽量不要设置 【首次倡议设置,须要导入数据,导入完之后可依据本人须要设置】指定IP ---> 只有指定IP才能够拜访如果须要批改数据库相干信息,可看下图ftp创立点击左侧ftp,点击右侧增加,会弹出窗口,请按下图设置根目录指以后ftp账号可拜访此目录下的所有文件夹以及文件redis软件商店搜寻,惯例装置步骤。端口放行点击左侧平安,点击右侧增加,会弹出窗口,请按下图设置图片中每个人可依据本人的理论状况开启端口必须开的端口21 ---> ftp端口22 ---> ssh端口,终端连贯服务器应用 【如果关上这个端口,ftp能够不须要关上,很多ssh终端工具自带上传性能,ftp抉择ssh连贯也能够应用】80 ---> web服务拜访端口443 ---> https拜访应用端口,也是微信开放平台要求应用,当然https也平安,举荐大家应用3306 ---> 数据库Mysql端口6379 ---> Redis端口20000 ---> Java Api我的项目监听端口今天咱们聊部署到服务器!欢送关注微信公众号:“东南大粽子” 每周至多3篇原创文章有道无术术尚可求,有术无道止于术。

March 19, 2021 · 1 min · jiezi

关于redis:redis入门教程2

查看redis相干信息INFO [section] # 间接输出info将返回以后redis所有相干信息127.0.0.1:6379> info当只须要显示其中局部信息的时候,info前面加对应须要查看的信息。例如须要查看redis客户端信息应用 info clients 127.0.0.1:6379> info clients# Clientsconnected_clients:1client_longest_output_list:0client_biggest_input_buf:0# keyspace 提供每个数据库的主字典统计,包含key总数,过期key总数127.0.0.1:6379> info keyspace# Keyspacedb0:keys=8,expires=0,avg_ttl=0db3:keys=2,expires=0,avg_ttl=0参考: http://redis.cn/commands/info...https://redis.io/commands/info连贯相干AUTH为redis服务申请设置一个明码 SELECT index切换数据库,下标从0开始 127.0.0.1:6379> select 2(error) NOAUTH Authentication required.127.0.0.1:6379> auth 123456OK# 通过select命令切换数据库127.0.0.1:6379> select 1OK127.0.0.1:6379[1]> get 111(nil)参考: http://redis.cn/commands.html...客户端相干CLIENT LIST返回所有客户端数据 127.0.0.1:6379[1]> CLIENT LISTid=19 addr=127.0.0.1:33639 fd=8 name= age=593 idle=0 flags=N db=1 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client参考: http://redis.cn/commands/clie... CONFIG GET parameterCONFIG SET parameter value用户在运行期间设置和读取配置。通过CONFIG GET *能够查看所有可设置的配置 参考 http://redis.cn/commands/conf...CLIENT KILL kill链接具体信息查看文档即可 对于redis的三种模式standalone 单机模式Sentinel 哨兵模式cluster 集群模式

March 18, 2021 · 1 min · jiezi

关于python:Django电商网站订单设计

1、订单页面总共分为3个局部 一、订单筹备页面:新建两个数据库表,一个是订单表 一个是订单商品表,一对多的关系,不便对订单数据进行存储和治理,须要依据用户信息(request.user)从后盾获取用户的地址信息(未删除的),展现到前端;而后须要获取用户的购物车信息(已勾选的商品和件数),也就是上文中构建的new_cart_dict = {},依据sku获取商品价格,而后乘以商品总价加上运费即可获取订单总金额;此外须要用户选中收货地址和领取形式响应给下一个页面,即订单展现页面; 二、订单展现页面:2.1接管前端传来的两个数据,即收货地址和领取形式,获取用户信息。2.2生成订单id(日期+工夫+用户id);2.3初始化订单数量0订单金额0;2.4组织订单状态(如果是货到付款,则订单状态为待发货,如果是支付宝,则显示为待付款);2.5.订单商品信息(咱们从redis中获取选中的商品信息) 2.5.1 连贯redis 2.5.2 获取hash 2.5.3 获取set 2.5.4 类型转换,转换过程中从新组织数据 选中的数据 {sku_id:count,sku_id:count} 2.5.5 获取选中的商品id [1,2,3] 2.5.6 遍历id 2.5.7 查问count 2.5.8 判断库存是否少于订单,如果没少则持续,如果少了则反馈库存有余 2.5.9 缩小MySQL中该sku的库存值,减少spu和sku的销量值 2.5.10 保留商品信息,示例如下: OrderGoods.objects.create( order=order, sku=sku, count=count, price=sku.price ) 2.5.11 累加计算 总金额和总数量 2.6. 保留订单信息的批改三、订单胜利页面:响应信息如下:context = { 'order_id': order_id, 'payment_amount': payment_amount, 'pay_method': pay_method }

March 18, 2021 · 1 min · jiezi

关于redis:Redis遇到的那些坑

本文首发于微信公众号【WriteOnRead】,欢送关注。前言Redis 作为以后最风行的 NoSQL 之一,想必很多人都用过。 Redis 有五种常见的数据类型:string、list、hash、set、zset。讲真,我以前只用过 Redis 的 string 类型。 因为业务需要,用到了 Redis 的汇合 set。这不,一上来就踩到坑了。 前几天有个需要提测,测试小哥提了个 bug,并给了我一个日志截图: 问题排查从堆栈信息定位到了我的项目的代码,大抵如下: public class CityService private void setStatus(CityRequest request) { // 依据城市码查问城市信息 Set<String> cityList = cityService.findByCityCode(request.getCityCode()); if (CollectionUtils.isEmpty(cityList)) { return; } // 遍历,做一些操作(报错就在这这一行) for (String city : cityList) { // ... } } // 一些无关的代码...}报错的代码就在 for 循环那一行。 这一行看起来仿佛没什么谬误,跟 HashSet 和 String 转换有什么关系呢?往前翻一翻 cityList 是怎么来的。 cityList 会依据城市码查问城市信息,这个办法有如下三步: 从本地缓存查问,若存在则间接返回;否则进行第二步。从 Redis 查问,若存在,存入本地缓存并返回;否则进行第三步。从 MySQL 查问,若存在,存入本地缓存和 Redis(set 类型)并返回;若不存在返回空。分割报错信息,再看这几步的代码,1、3 可能性较小;第二步因为之前没有间接用过 set 这种数据结构,嫌疑较大。 ...

March 18, 2021 · 2 min · jiezi

关于github:这款相见恨晚的开源问卷系统我粉了

 大家好,我是为宽广程序员兄弟操碎了心的小编,每天举荐一个小工具/源码,装满你的收藏夹,每天分享一个小技巧,让你轻松节俭开发效率,实现不加班不熬夜不掉头发,是我的指标! 明天小编举荐一款开源表单问卷零碎——Tduck,Tduck-填鸭收集器是一款开源的表单问卷在线收集零碎,后台基SpringBoot+MybatisPlus+MySql+Redis,前端基于Vue ElementUI开发,功能强大,界面好看。 利用场景 次要利用与泛批发、电商、金融、调研、材料收集等行业用户,提供多种工具、多渠道、多形式收集无效信息,更好的晋升客户服务,减少客户满意度。 性能个性界面好看,全新element-ui反对,应用晦涩以一种全新的设计体验,辞别繁琐的设计流程通过简略乏味的形式,轻轻松松实现问卷设计反对问卷款式模板抉择,只为浮现更精美的表单问卷三大模块助力企业能力降级:新建表单:自定义可拖拽式表单设计表单设置:反对多种收集形式设置反馈统计:多维度统计收集的反馈数据开源协定 应用 Apache License 2.0 协定,源代码齐全开源,无商业限度 链接地址 公众号【Github导航站】回复关键词【tdu】获取git地址 截图预览 结尾 本期就分享到这里,我是小编南风吹,专一分享好玩乏味、离奇、实用的开源我的项目及开发者工具、学习资源!心愿能与大家独特学习交换,欢送关注我的公众号【Github导航站】。

March 18, 2021 · 1 min · jiezi

关于数据库:都在讲Redis主从复制原理我来讲实践总结

摘要:本文将演示主从复制如何配置、实现以及实现原理,Redis主从复制三大策略,全量复制、局部复制和立刻复制。本文分享自华为云社区《Redis主从复制实际总结》,原文作者:A梦多啦A 。 复制简介Redis 作为一门非关系型数据库,其复制性能和关系型数据库(MySQL)来说,性能其实都是差不多,无外乎就是实现的原理不同。Redis 的复制性能也是绝对于其余的内存性数据库(memcached)所具备特有的性能。 Redis 复制性能次要的作用,是集群、分片性能实现的根底;同时也是 Redis 实现高可用的一种策略,例如解决单机并发问题、数据安全性等等问题。 服务介绍在本文环境演示中,有一台主机,启动了两个 Redis 示例。 实现形式Redis 复制实现形式分为上面三种形式: 1. 服务启动时配置该形式通过在启动 Redis 服务时,通过命令行参数,进行启动主从复制性能。该形式的弊病是不能实现配置长久化,当服务停掉之后,启动服务时,须要增加雷同的命令参数。 1.1 master 服务器当时在 redis.confg 减少 requirepass 项。 requirepass 63791.2 启动从服务器。 redis-server --port 6380 --replicaof 192.168.2.102 63792. 命令行配置该形式通过应用 redis-cli 进入操作行界面,进行配置。该形式的弊病是不能实现配置长久化,当服务停掉之后,启动服务须要执行同样的命令。 2.1 master 服务器执行。 127.0.0.1:6379> config set requirepass 6379OK2.2 从服务器执行。 127.0.0.1:6380> replicaof 192.168.2.102 6379OK127.0.0.1:6380> config set masterauth 6379OK3. 配置文件配置该形式是通过 redis.conf 配置文件进行设置,可能实现配置的长久化,是一种举荐应用的形式。 3.1 配置主服务器,redis.config。 requirepass 63793.2 配置从服务器,redis.config。 masterauth 6379replicaof 192.168.2.102 63794.配置阐明1.masterauth:设置 redis.confi 连贯明码,如果设置了该值。其余客户端在连贯该服务器时,须要增加明码才能够拜访。 2.requirepass:设置主服务器的连贯明码,和 1 中 masterauth 统一。 ...

March 18, 2021 · 1 min · jiezi

关于华为云:华为云PB级数据库GaussDBfor-Redis揭秘第五期高斯-Redis-在IM场景中的应用

摘要:揭秘高斯 Redis 在IM场景中的利用。本文分享自华为云社区《华为云PB级数据库GaussDB(for Redis)揭秘第五期:高斯 Redis 在IM场景中的利用》,原文作者:神思胖 。 一、背景即时通讯(Instant Messaging,简称IM)是一个实时通信零碎,容许两人或多人应用网络实时的传递文字音讯、文件、语音与视频。微信、QQ等IM类产品在这个高度信息化的互联网时代已成为生存必备品,IM零碎中最外围的局部是音讯零碎,音讯零碎中最外围的性能是音讯的同步、存储和检索。 音讯同步:将音讯残缺的、疾速的从发送方发送至接管方。音讯同步零碎最重要的掂量指标是消息传递的实时性、完整性、程序性以及撑持的音讯规模。音讯存储:即音讯的长久化,传统音讯零碎通常反对音讯在接收端的本地存储,数据根本不具备可靠性。古代音讯零碎反对音讯在云端存储,从而实现音讯异地查问:账号可在任意客户端登陆查看所有历史音讯。音讯检索:音讯个别是文本,所以反对全文检索也是必备的能力之一。传统音讯零碎通常来说基于本地存储的音讯数据来构建索引,反对音讯的本地检索。而古代音讯零碎反对音讯的在线存储以及存储过程中构建索引,提供全面的音讯检索性能。二、IM零碎架构设计 上图为IM零碎的利用场景,可用于聊天,游戏、智能客服等诸多行业。不同行业对IM零碎的老本、性能、可靠性、时延等指标的需要是不同的,架构设计须要进行均衡。接下来将介绍IM零碎架构设计所波及到的一些基本概念。 2.1 传统架构 vs 古代架构 传统架构Ø 先同步后存储。 Ø 在线音讯同步和离线音讯缓存。 Ø 服务端不会对音讯进行长久化,无奈反对音讯异地查问。 古代架构Ø 先存储后同步。 Ø 划分音讯存储库与音讯同步库。音讯存储库用于全量保留所有会话音讯,次要用于反对音讯异地查问。音讯同步库,次要用于接管方的多端同步。 Ø 提供音讯全文检索能力。 2.2 读扩散vs 写扩散《2020微信数据报告》指出,截至2020年9月,微信月沉闷用户数为10.825亿,日音讯发送次数450亿次,日音视频呼叫胜利次数4.1亿次。面临这么多的音讯,如何保障消息传递的可靠性、一致性并且无效的升高服务器或者客户端的压力是非常具备技术挑战的。其中,采纳何种读写模型对IM零碎至关重要,这里介绍两种模型:读扩散和写扩散。 如上图所示,用户B与每个聊天的人(A1,A2,A3)都有一个信箱(一种数据结构的形象,用于存储音讯),B在查看聊天信息时需读取所有有新音讯的信箱。IM零碎里的读扩散通常是每两个相关联的人就有一个信箱。 读扩散的长处: 写操作(发消息)轻量,不论是单聊还是群聊,只须要往相应的信箱写一次即可。每一个信箱人造就是两个人的聊天记录,能够不便查看和搜寻聊天记录。读扩散的毛病: 读操作(读音讯)很重,存在读放大效应。 如上图,在写扩散中,用户(B1,B2,B3)都只从本人的信箱里读取音讯,但写(发消息)的时候,对于单聊跟群聊解决如下: 单聊:往本人的信箱跟对方的信箱都写一份音讯;同时,如果须要查看两个人的聊天历史记录的话还须要再写一份。群聊:发信息时须要针对所有群成员的信箱都写一份音讯。群聊应用的是写扩散模型,而写扩散很耗费资源,因而微信群有人数下限(目前是500)。写扩散长处: 读操作很轻量,只须要读取本人的邮箱。能够很不便实现音讯的多终端同步。写扩散毛病: 写操作很重,尤其是对于群聊来说。2.3 推模式 vs 拉模式 vs 推拉联合模式 在IM零碎中,音讯的获取通常有三种模式: 推模式(Push):新音讯达到时由服务器被动推送给所有客户端;须要客户端和服务器建设长连贯,实时性很高,对客户端来说只须要接管解决音讯即可;毛病是服务端不晓得客户端解决音讯的能力,可能会导致数据积压。拉模式(Pull):由前端被动发动拉取音讯的申请,为了保障音讯的实时性,个别采纳推模式,拉模式个别用于获取历史音讯;因客户端拉取新音讯的工夫距离不好预设,太短可能会导致大量的连贯拉取不到数据,太长导致数据接管不及时。 推拉联合模式:兼顾push和pull两种模式的长处。新音讯来长期服务器会先推送一个新音讯达到的告诉给前端,前端接管到告诉后就向服务器拉取音讯。三、IM技术挑战 上图为IM零碎的总体架构图,Client单方通信会通过Server转发来实现消息传递。其外围为音讯存储库和音讯同步库。这两种库对存储层的性能有极高的要求。 撑持海量数据存储:对于音讯存储库来说,如果须要音讯永恒存储,则随着工夫的积攒,数据规模会越来越大,需存储库反对容量有限扩大以应答日益增长的音讯数据。低存储老本:音讯数据具备显著的冷热特色,大部分查问集中在热数据,冷数据须要一个低成本的存储形式,否则随着工夫的积攒,数据量一直收缩,存储老本会一直回升。数据生命周期治理:不论是对于音讯数据的存储还是同步,数据都须要定义生命周期。存储库是用于在线存储音讯数据自身,通常须要设定一个较长周期的保留工夫。而同步库 是用于写扩散模式的在线或离线推送,通常设定一个较短的保留工夫。极高的写入吞吐:绝大部分IM类场景,通常是采纳写扩散模型,写扩散要求底层存储具备极高的写入吞吐能力,从而应答音讯洪峰。低提早的读:音讯零碎通常利用于在线场景,具备较高的实时性,读取提早应尽可能低。四、高斯Redis在IM场景中的劣势IM零碎的外围是存储层,其性能差别将间接影响IM零碎的用户体验。目前存储层可抉择的数据库产品有很多,如HBase、开源Redis等等。抉择何种数据库,需依据业务规模、老本、性能等指标来进行综合抉择。这里介绍一种NoSQL数据库:高斯Redis,在性能和规模上,能够满足IM系统对存储层的严格要求:海量数据存储、低存储老本、生命周期治理、写入吞吐大、读取时延低。 4.1高斯Redis简介高斯Redis是华为云数据库团队自主研发且兼容Redis5.0协定的云原生数据库,采纳计算存储拆散架构。存储侧应用自研的存储系统,容量有限扩大、强统一、高牢靠。计算侧基于 LSM 存储引擎实现,通过将大量的随机写转换为程序写,从而极大的晋升了数据写入性能,同时也通过读缓存、bloom filter 等极大优化了读取性能。下图是高斯Redis在IM场景的劣势介绍。 4.2基于高斯Redis的IM利用案例:下图是基于高斯Redis的IM零碎模型图,这里咱们应用stream作为根本数据结构。Redis stream不仅能够作为音讯存储容器,还实现了生产者、消费者等根本模型,具备IM零碎的基本功能,如音讯订阅,散发、减少消费者等,用户可基于高斯Redis疾速构建一套IM零碎。创立一个群聊时,在Redis中对应地为该群聊创立一个stream队列。在发送音讯时,每个用户都将音讯依照工夫程序增加到stream队列中,保障了音讯的有序性。stream是一个长久化的队列,可保障信息不失落。 五、总结高斯Redis通过一系列技术创新实现了读写性能程度扩大,秒级扩容,低成本以及主动备份等性能, 可作为IM零碎的存储层,其优异的读写性能和高级个性将会极大助力IM利用.同时,高斯Redis在开源Redis的根底之上,较好均衡了性能和老本,可能广泛应用在智慧医疗、流量削峰、计数器等畛域。 六、完结本文作者:华为云高斯Redis团队。 杭州西安深圳简历投递:yuwenlong4@huawei.com 更多技术文章,关注高斯Redis官网博客:https://bbs.huaweicloud.com/community/usersnew/id_1614151726110813 七、参考资料1.《GaussDB(for Redis)官方主页》 https://www.huaweicloud.com/product/gaussdbforredis.html 2.《华为云GaussDB(for Redis)与自建开源Redis的老本比照》 https://www.modb.pro/db/42739 ...

March 18, 2021 · 1 min · jiezi

关于redis:VisualNMP升级redis和nginx版本

下载nginx版本,解压到bin目录下 **将旧版的bin\Nginx_old\conf\nginx.conf复制到新版的bin\Nginx\conf\下并替换掉原来的;将旧版的bin\Nginx_old\Nginx_Serv.exe,bin\Nginx_old\Nginx_Serv.ini 还有out.log复制到新版的bin\Nginx\下即可 (留神改文件夹名称)** 下载redis 地址:Redis 5.0.10 for Windows 解压到bin\Redis上面,批改Redis_Serv.ini 的RedisVersion [Redis Serv]check_interval=15[Generate for Redis Serv]RedisVersion=Redis5.0.10OSVersion=Microsoft Windows NT 6.2.9200.0下载的redis没有redis.conf能够把旧我的项目的复制过去 就能够了

March 17, 2021 · 1 min · jiezi

关于redis:看故事学Redis再不懂我怀疑你是假个开发

摘要:还不懂Redis?看完这个故事就明确了!本文转载自博客园社区《还不懂Redis?看完这个故事就明确了!》,作者:轩辕之风 我是Redis你好,我是Redis,一个叫Antirez的男人把我带到了这个世界上。 说起我的诞生,跟关系数据库MySQL还挺有渊源的。 在我还没来到这个世界上的时候,MySQL过的很辛苦,互联网倒退的越来越快,它包容的数据也越来越多,用户申请也随之暴涨,而每一个用户申请都变成了对它的一个又一个读写操作,MySQL是苦不堪言。尤其是到“双11”、“618“这种全民购物狂欢的日子,都是MySQL受苦受难的日子。 据起初MySQL通知我说,其实有一大半的用户申请都是读操作,而且常常都是反复查问一个货色,节约它很多工夫去进行磁盘I/O。 起初有人就推敲,是不是能够学学CPU,给数据库也加一个缓存呢?于是我就诞生了! 出世不久,我就和MySQL成为了好敌人,咱们俩经常携手呈现在后端服务器中。 应用程序们从MySQL查问到的数据,在我这里注销一下,前面再须要用到的时候,就先找我要,我这里没有再找MySQL要。 为了方便使用,我反对好几种数据结构的存储: StringHashListSetSortedSetBitmap······因为我把注销的数据都记录在内存中,不必去执行慢如蜗牛的I/O操作,所以找我要比找MySQL要省去了不少的工夫呢。 可别小瞧这简略的一个扭转,我可为MySQL加重了不小的累赘!随着程序的运行,我缓存的数据越来越多,有相当局部工夫我都给它挡住了用户申请,这一下它可乐得清闲自在了! 有了我的退出,网络服务的性能晋升了不少,这都归功于我为数据库挨了不少枪子儿。 缓存过期 && 缓存淘汰不过很快我发现事件不妙了,我缓存的数据都是在内存中,可是就算是在服务器上,内存的空间资源还是很无限的,不能无节制的这么存上来,我得想个办法,不然吃枣药丸。 不久,我想到了一个方法:给缓存内容设置一个超时工夫,具体设置多长交给应用程序们去设置,我要做的就是把过期了的内容从我外面删除掉,及时腾出空间就行了。 超时工夫有了,我该在什么时候去干这个清理的活呢? 最简略的就是定期删除,我决定100ms就做一次,一秒钟就是10次! 我清理的时候也不能一口气把所有过期的都给删除掉,我这外面存了大量的数据,要全面扫一遍的话那不晓得要花多久工夫,会重大影响我接待新的客户申请的! 工夫紧工作重,我只好随机抉择一部分来清理,能缓解内存压力就行了。 就这样过了一段日子,我发现有些个键值运气比拟好,每次都没有被我的随机算法选中,每次都能幸免于难,这可不行,这些长时间过期的数据始终霸占着不少的内存空间!气抖冷! 我眼里可揉不得沙子!于是在原来定期删除的根底上,又加了一招: 那些原来逃脱我随机抉择算法的键值,一旦遇到查问申请,被我发现曾经超期了,那我就绝不客气,立刻删除。 这种形式因为是被动式触发的,不查问就不会产生,所以也叫惰性删除! 可是,还是有局部键值,既逃脱了我的随机抉择算法,又始终没有被查问,导致它们始终绳之以法!而于此同时,能够应用的内存空间却越来越少。 而且就算退一步讲,我可能把过期的数据都删除掉,那万一过期工夫设置的很长,还没等到我去清理,内存就吃满了,一样要吃枣药丸,所以我还得想个办法。 我苦思好久,终于憋出了个大招:内存淘汰策略,这一次我要彻底解决问题! 我提供了8种策略供应用程序抉择,用于我遇到内存不足时该如何决策: noeviction:返回谬误,不会删除任何键值allkeys-lru:应用LRU算法删除最近起码应用的键值volatile-lru:应用LRU算法从设置了过期工夫的键汇合中删除最近起码应用的键值allkeys-random:从所有key随机删除volatile-random:从设置了过期工夫的键的汇合中随机删除volatile-ttl:从设置了过期工夫的键中删除剩余时间最短的键volatile-lfu:从配置了过期工夫的键中删除应用频率起码的键allkeys-lfu:从所有键中删除应用频率起码的键有了下面几套组合拳,我再也不必放心过期数据多了把空间撑满的问题了~ 缓存穿透 && 布隆过滤器我的日子过的还挺舒坦,不过MySQL大哥就没我这么舒坦了,有时候遇到些烦人的申请,查问的数据不存在,MySQL就要白忙活一场!不仅如此,因为不存在,我也没法缓存啊,导致同样的申请来了每次都要去让MySQL白忙活一场。我作为缓存的价值就没失去体现啦!这就是人们常说的缓存穿透。 这一来二去,MySQL大哥忍不住了:“唉,兄弟,能不能帮忙想个办法,把那些明晓得不会有后果的查问申请给我挡一下” 这时我想到了我的另外一个好敌人:布隆过滤器 我这位敌人别的本事没有,就善于从超大的数据集中疾速通知你查找的数据存不存在(轻轻通知你,我的这位敌人有一点不靠谱,它通知你存在的话不能全信,其实有可能是不存在的,不过它他要是通知你不存在的话,那就肯定不存在)。 如果你对我这位敌人感兴趣的话,能够看看这里《文言布隆过滤器BloomFilter》。 我把这位敌人介绍给了应用程序,不存在的数据就不用去叨扰MySQL了,轻松帮忙解决了缓存穿透的问题。 缓存击穿 && 缓存雪崩这之后过了一段时间太平日子,直到那一天··· 有一次,MySQL那家伙正优哉游哉的摸鱼,忽然一大堆申请给他怼了过来,给他打了一个措手不及。 一阵忙活之后,MySQL火冒三丈的找到了我,“兄弟,咋回事啊,怎么一下子来的这么猛” 我查看了日志,连忙解释到:“大哥,切实不好意思,刚刚有一个热点数据到了过期工夫,被我删掉了,不巧的是随后就有对这个数据的大量查问申请来了,我这里曾经删了,所以申请都发到你那里来了” “你这干的叫啥事,下次留神点啊”,MySQL大哥一脸不快乐的来到了。 这一件小事我也没怎么放在心上,随后就抛之脑后了,却没曾想几天之后竟捅了更大的篓子。 那一天,又呈现了大量的网络申请发到了MySQL那边,比上一次的规模大得多,MySQL大哥一会儿功夫就给干趴下了好几次! 等了好半天这一波流量才算过来,MySQL才缓过神来。 “老弟,这一次又是什么起因?”,MySQL大哥累的没了力量。 “这一次比上一次更不巧,这一次是一大批数据简直同时过了有效期,而后又产生了很多对这些数据的申请,所以比起上一次这规模更大了” MySQL大哥听了眉头一皱,“那你倒是想个办法啊,三天两头折磨我,这谁顶得住啊?” “其实我也很无奈,这个工夫也不是我设置的,要不我去找应用程序说说,让他把缓存过期工夫设置的平均一些?至多别让大量数据个体生效” “走,咱俩一起去” 起初,我俩去找应用程序磋商了,不仅把键值的过期工夫随机了一下,还设置了热点数据永不过期,这个问题缓解了不少。哦对了,咱们还把这两次产生的问题别离取了个名字:缓存击穿和缓存雪崩。 咱们终于又过上了舒服的日子··· 点击关注,第一工夫理解华为云陈腐技术~

March 17, 2021 · 1 min · jiezi

关于redis:一份完整的阿里云-Redis-开发规范值得收藏

我的公众号:MarkerHub,网站:https://markerhub.com更多精选文章请点击:Java笔记大全.md 作者:付磊-起扬yq.aliyun.com/articles/531067本文次要介绍在应用阿里云 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。 ...

March 17, 2021 · 2 min · jiezi

关于redis:我所理解的-Redis-AOF-持久化

介绍Redis 是内存型数据库,一旦主过程退出就会造成数据失落。它的长久化次要有两大机制,即 AOF 日志和 RDB 快照,本文次要关怀 AOF 日志。 过程 Redis 执行完一个写命令后,将写命令以协定文本的模式追加到 AOF 缓冲区开端,再通过同步策略来决定是否将 AOF 缓冲区中的内容写入 & 同步到 AOF 日志。 同步策略AOF 机制提供了三个抉择,也就是配置项 appendfsync 的三个可选值: always:将 AOF 缓冲区中的所有内容写入并同步到 AOF 日志。everysec:将 AOF 缓冲区中的所有内容写入到 AOF 日志,如果上次同步 AOF 日志的工夫间隔当初超过 1 秒钟,那么对 AOF 日志进行同步。no:将 AOF 缓冲区中的所有内容写入到 AOF 日志,但并不对 AOF 日志进行同步, 何时同步由操作系统来决定。三种策略的优缺点也不言而喻了,always 可靠性高性能低、no 可靠性低性能高,everysec 取两者折中。 重写机制AOF 日志是以文件的模式记录接管到的所有写命令。随着接管的写命令越来越多,文件体积会越来越大。这也就意味着会带来一些问题。 操作系统对文件体积有限度,不能保留过大的文件。对体积比拟大的文件进行追加写入,效率会升高。AOF 日志体积过大,故障复原过程迟缓。为了解决下面的问题,Redis 提供了重写性能。通过该性能,Redis 能够创立一份新的 AOF 日志来代替现有的 AOF 日志。 两份 AOF 日志所保留的数据库状态雷同。新 AOF 日志不会蕴含节约空间的冗余命令。新 AOF 日志体积小于等于原 AOF 日志。 重写过程 为什么要放在子过程里执行?不会造成主线程阻塞,子过程进行 AOF 重写期间,主线程能够持续解决命令申请。 ...

March 16, 2021 · 1 min · jiezi

关于redis:Django电商网站购物车设计

1、购物车因为是高频刷新局部,同时对数据关系构造的要求并非很简单,因而选取nosql作为存储工具;2、前后端须要对接4个参数,别离是用户id,商品编码即sku_id,多少件商品count以及是否勾选 selected;3、Redis有5种数据类型,别离为string、list、hash、set、zset。而本次的4个参数,数量超过了单一种数据结构的管制范畴,因而选用2个数据结构进行独特保护;4、用户id,skuid以及count采纳hash构造,即:cart_user_id:{sku_id1:count,sku_id2:count,sku_id3:count....}5、用户id和选中的商品应用set保护,因为购物车不要求先后顺序,且set构造可主动去重,select_user_id:[sku_id1,sku_id3.....]6、前期保护购物车数据时,2个表同时进行,例如删掉hash外面sku_id1的时候,selected外面的也要同时删掉。7、在hash中每次增加商品时,先遍历购物车中的商品是否已有,如果已有,则累加count,如果没有再加新的。应用hincrby函数

March 16, 2021 · 1 min · jiezi

关于java:面试Java字节面经已获Offer

前言要么字节跳动,要么心脏跳动,你选哪个?哈哈哈,为大家筹备的字节三面面经,前面有总结面试教训,以及相干面试技巧,请自行浏览。怕你忘了找不到,举荐先珍藏,再浏览。一面在校我的项目后端是怎么搭建的答:tomcat,springboot, mybatis备注:这里没答好,应该扩大一下,说过后大三程度无限没有做高可用,如果当初做会用VIP+双ng+双服务做简略高可用 “小程序不反对缓存二进制,因而将小图片BASE64编码后缓存到本地”,还有没有其余优化计划答:优化计划是CDN,讲了CDN大略原理备注:还能够答图片压缩 联合我的项目讲下加解密计划答:讲了非对称加密(两种利用场景)、数字摘要、数字签名、对称加密、SSL,讲了很久报表接口怎么写的,怎么反对免部署灵便批改答:各种CASE WHEN、IFNULL,把sql存数据库,从db取出sql再执行,有治理后盾随时改es怎么聚合计算答:不会es怎么做range查问答:讲了es的分片、路由,暴力range计划es分词原理答:答了分词过程、倒排索引等new一个对象的生命周期答:讲了jmm,答了很久老年代除了空间不够,还有什么时候会触发fgc答:System.gc()也会触发,生产环境个别加DisableExplicitGC禁用System.gc()新生代的对象年龄达到15的时候,会降职到老年代,为什么是15?答:应该是经验值,如果定的太小,可能对象到了老年代之后很容易死亡,如果太大,可能对象在新生代始终复制,减少开销备注正确答案,应该是因为对象头的markword局部,存分代年龄的age字段的二进制长度是4,所以最大值是15 mysql为什么要有最左前缀原理答:是B+树的构造决定了最左前缀,答了mysql的页构造(闲暇区,用户记录区,页目录..)、索引构造、聚簇索引、二级索引,答了很久算法题父串里找子串,即indexOf 答:没写出KMP,写了暴力备注: 面试时,有发问“子串不存在时返回什么”,“子串呈现屡次是否返回第一个”,还有一个非凡状况没有思考到:子串为空字符时返回什么还有比KMP更快的字符串匹配算法: BM(Boyer-Moore)算法 暴力代码运行通过后,让我回顾KMP,没回顾起来,只说了有个next数组...二面联合我的项目问我的项目里F5怎么实现会话放弃答:加cookie诘问ISO七层模型,F5加cookie在哪一层,ip hash在哪一层备注:cookie是http协定才有的,所以在应用层ip hash有可能在应用层,也可能在网络层,如果是client->lb lb->server这种模式,就是应用层,因为须要从新发动http申请,如果是通过DNAT协定批改指标地址实现的,那就是网络层 F5跟Ha区别,为什么F5性能比Ha好,硬件配置雷同的状况下,F5还比Ha好吗备注:“为什么F5性能比Ha好”过后没答出来,正确答案应该是个别状况下,F5是四层负载平衡,Ha是七层。然而F5也能够七层负载平衡,这个时候性能应该不会差太多 lvs的dr模式keepalived的VIP漂移原理备注:没答出来,答案是VRRP协定 讲本人比拟善于的技术讲了innodb页构造、索引原理sql调优教训我的项目整个数据库的最大的表有多大微服务框架相熟哪个看过哪些源码答hashmap,问hashmap的容量为什么是2的n次方最近在学什么,为什么学怎么了解高可用面试官:你有什么要问我的吗问:有哪些方面须要补强面试官:我的项目比拟传统,其余还好三面介绍我的项目难点零拷贝FGC的几张状况,怎么排查问题手机刷抖音的时候,视频忽然卡住,有哪些起因为什么到职没有算法,总共半小时差不多总结筹备好一些高频问题,蕴含技术类和非技术类技术类:看过哪些源码对哪个技术比拟相熟最近在学什么,为什么我的项目有哪些地方须要改良我的项目有哪些难点怎么应答突发流量非技术类:平时怎么学习的,新常识怎么学习本人有哪些优缺点共事怎么评估本人为什么到职还有什么要问的介绍我的项目技巧讲我的项目肯定要谨慎,讲太深的话,任何一个名词,面试官都可能深刻发问,导致本人答不上来;讲太浅的话,面试官会感觉我的项目难度不够,没趣味听;说我的项目的时候,说完痛点,而后说解决方案一二三,以及各自的优缺点,最初生产选了什么计划,面试时,逻辑是否清晰也是很重要的考查指标;突出对业务的深刻理解;用具体的数字阐明状况,如qps、db数据量等;把八股文交叉到我的项目里算法题技巧留神代码标准,比方正文后行(先写正文再写代码)、对非凡状况的返回值写好正文(比方入参为空时返回什么)长于向面试官发问,体现本人的逻辑能力,以“从父串寻找子串为例(即实现indexOf办法)”,能够提的问题有: 子串在父串中没有呈现,返回什么子串为空,返回什么子串呈现屡次,是否只返回第一个地位如果工夫足够,按下面的来,如果工夫不够,就不要思考太多边界状况啥的,能过一个case就行其余技巧语速不要太快,不然面试官了解不了;至多要有一个性能足够牛逼,能够吹很久很久,问我的项目难点等时候才能够吹;至多要有一项技术足够深刻学习,redis、mysql、jvm...都行,吹上了就大大加分;答复问题的时候,先说论断,再说过程,晓得论断的前提下,听你讲过程,容易了解;不要一开始就投一堆公司,很可能面完一两场发现简历须要批改;大厂hr面不要扯谎,hr相当业余,很容易看进去;面试其实就是八股文、我的项目、算法三个方面,三方面都没问题,那就稳了。八股文能够背,我的项目能够包装,但算法只能靠积攒。想进大厂,先刷题,半年起步。常见问题示例还有什么要问的答: hr面:造就体系和降职机制技术面:有哪些方面须要增强,或者向面试官求教一些职场教训备注:人类最须要的货色是认可,向面试官求教职场教训,他说完后,你示意非常认可,他就失去了人类最须要的货色。为什么到职 想到更好的平台,做更有挑战性的工作,同时也心愿身边有更多优良的人怎么学习的 通过看书进步深度,通过公众号、专栏、博客等碎片化形式进步广度;看得懂/听得懂不肯定真的懂,讲的进去才是真的懂,所以学习一个知识点后要自问自答;看书选经典书籍;学习时要长于提出问题,依据问题深究细节,没有问题才是最大的问题参考资料修行者12138——程序员面试教训(https://www.jianshu.com/p/c23... 絮叨非常感谢你能看到这里,如果感觉文章写得不错 求关注 求点赞 求分享 (对我十分十分有用)。 如果你感觉文章有待进步,我非常期待你对我的倡议,求留言。 如果你心愿看到什么内容,我非常期待你的留言。 各位的捧场和反对,是我创作的最大能源!

March 16, 2021 · 1 min · jiezi

关于redis:Redis-是如何实现点赞取消点赞的

我的公众号:MarkerHub,网站:https://markerhub.com小Hub领读:点赞是个频率比拟高的事件,也不是特地重要的记录,应用缓存来存储还是比拟正当的,另外像排行榜、热议等都能够应用缓存,先来看看点赞是如何实现的吧,具体代码能够clone看下哈,跟紧脚步,学技术~ 作者:solocoderjuejin.im/post/5bdc257e6fb9a049ba410098代码出自开源我的项目 CodeRiver,欢送围观: https://github.com/cachecats/...本文基于 SpringCloud, 用户发动点赞、勾销点赞后先存入 Redis 中,再每隔两小时从 Redis 读取点赞数据写入数据库中做长久化存储。 点赞性能在很多零碎中都有,但别看性能小,想要做好须要思考的货色还挺多的。 点赞、勾销点赞是高频次的操作,若每次都读写数据库,大量的操作会影响数据库性能,所以须要做缓存。 至于多久从 Redis 取一次数据存到数据库中,依据我的项目的理论状况定吧,我是临时设了两个小时。 我的项目需要须要查看都谁点赞了,所以要存储每个点赞的点赞人、被点赞人,不能简略的做计数。 文章分四局部介绍: Redis 缓存设计及实现数据库设计数据库操作开启定时工作长久化存储到数据库一、Redis 缓存设计及实现1.1 Redis 装置及运行Redis 装置请自行查阅相干教程。说下 Docker 装置运行 Redis docker run -d -p 6379:6379 redis:4.0.8如果曾经装置了 Redis,关上命令行,输出启动 Redis 的命令 redis-server1.2 Redis 与 SpringBoot 我的项目的整合在 pom.xml 中引入依赖<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-redis</artifactId></dependency>在启动类上增加正文 @EnableCaching@SpringBootApplication@EnableDiscoveryClient@EnableSwagger2@EnableFeignClients(basePackages = "com.solo.coderiver.project.client")@EnableCachingpublic class UserApplication {    public static void main(String[] args) {        SpringApplication.run(UserApplication.class, args);    }}编写 Redis 配置类 RedisConfigimport com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import java.net.UnknownHostException;@Configurationpublic class RedisConfig {    @Bean    @ConditionalOnMissingBean(name = "redisTemplate")    public RedisTemplate<String, Object> redisTemplate(            RedisConnectionFactory redisConnectionFactory)            throws UnknownHostException {        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);        ObjectMapper om = new ObjectMapper();        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);        jackson2JsonRedisSerializer.setObjectMapper(om);        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();        template.setConnectionFactory(redisConnectionFactory);        template.setKeySerializer(jackson2JsonRedisSerializer);        template.setValueSerializer(jackson2JsonRedisSerializer);        template.setHashKeySerializer(jackson2JsonRedisSerializer);        template.setHashValueSerializer(jackson2JsonRedisSerializer);        template.afterPropertiesSet();        return template;    }    @Bean    @ConditionalOnMissingBean(StringRedisTemplate.class)    public StringRedisTemplate stringRedisTemplate(            RedisConnectionFactory redisConnectionFactory)            throws UnknownHostException {        StringRedisTemplate template = new StringRedisTemplate();        template.setConnectionFactory(redisConnectionFactory);        return template;    }}至此 Redis 在 SpringBoot 我的项目中的配置曾经实现,能够欢快的应用了。 1.3 Redis 的数据结构类型Redis 能够存储键与 5 种不同数据结构类型之间的映射,这 5 种数据结构类型别离为 String(字符串)、List(列表)、Set(汇合)、Hash(散列)和 Zset(有序汇合)。 上面来对这 5 种数据结构类型作简略的介绍: 1.4 点赞数据在 Redis 中的存储格局用 Redis 存储两种数据,一种是记录点赞人、被点赞人、点赞状态的数据,另一种是每个用户被点赞了多少次,做个简略的计数。 因为须要记录点赞人和被点赞人,还有点赞状态(点赞、勾销点赞),还要固定工夫距离取出 Redis 中所有点赞数据,剖析了下 Redis 数据格式中 Hash 最合适。 ...

March 14, 2021 · 1 min · jiezi

关于大数据:四款面向高并发海量级分布式存储的分布式架构对比

一、Redis的分布式构造解读首先redis采纳去中心化的设计这个了解是不到位的。redis分布式的模式,具备主从和集群两种,redis社区的集群计划redis cluster采纳的是去中心化设计。咱们先看看redis的演化过程: 上图是规范的Redis主从模式,只有Master接管写入申请,并将写入的数据复制给一个或多个Slave,这就造成了良好的读写拆散机制,多个Slave就能够分担读操作。所以redis主从是规范的分布式中心化思维。 因为redis的利用场景大多是极高并发的内存I/O,因而上图的主从模式下Master既要承当写入,又要承当对内各个节点复制,Master的资源耗费很大,而且随着slave节点越多,这个问题越显著,因而,redis又造成主从的一个变种模式: 上图是redis主从拓扑构造的一种树形构造,这个拓扑构造的益处在于Master不须要给有数多的slave节点进行复制数据了,交给处于下一层节点的Slave来解决。这样就能将Master的工作耗费尽量从复制中抽身。 可问题是像这种高并发的业务场景,Master始终是一个隐患,因为它接受着所有的写操作,一旦解体,若没有HA解决方案,集群整体就不可用了。因而redis社区推出的集群计划,其实就是解决主的压力,很天然地就思考到应用集群的分布式无核心模式。 上图中,右边是集群的核心模式,左边就是redis cluster应用的无核心模式。 redis cluster一些细节:redis无核心采纳虚构槽概念,这是独立于物理节点的,往往很容易将这块混同,虚构槽有0~16383个,redis的数据进行key的hash计算(具体公式网上很多),确定这笔数据是进入哪个槽位,而物理节点负责哪些虚构槽,这是由咱们指定的。 例如:当1个G的数据依照一条条带有key的记录写入redis cluster的时候,那么集群的各个节点只有承受到数据,就计算此条记录应该归哪个槽哪个节点,归本节点就写入与槽位映射的数据,不归本人的,就反馈客户端真正须要写入的节点,客户端再向记录所属节点发动二次申请,这就实现了1个G的数据在集群中的分片。 咱们先不管redis cluster更多的优劣问题,单从下面的演变能够看到redis的主从构造向cluster演变的过程,其实就是去核心的过程,就是为了让多客户端多业务申请并发性能能够失去更好负载。另外为了高牢靠HA,每个节点也能够在演变成master/slave的主从模式部署,即使是主节点宕掉,salve也会顶替上来。HA的毛病是节点数量又减少了一倍。 redis与rocketmq最大的不同,redis更并重在线联机业务的高并发解决,而后者是海量积压数据流的大吞吐接管和生产。因而其抉择分布式架构的目标也不同。当然这不代表着肯定是中心化就不适宜高并发,例如LSM-Tree代表的oceanbase作为集中式解决的特点,就很好的做到了在线联机业务的高并发写入,以及高速的热点数据(最近工夫)查找。 另外,因为redis cluster作为分布式中每个节点都是对等的,那么就肯定会存在集群治理上的一致性危险,因为在生产环境中各种异常情况都很特地,就会导致不同节点对集群的认可状态不统一,所以这时候手动染指调整每个节点在集群中状态状况就会增多。 二、Kafka和RocketMQ的分布式解读咱们先看看比rocketmq更让人熟知的大师兄Kafka,解读一下Kafka集群的分布式特点。 Kafka的集群治理来自zookeeper集群,Broker的注册发现,Broker Controller的选举都是由zookeeper来帮助实现,然而Controller其实也不在音讯解决时做什么事件,只是在创立分区、分区再均衡等方面对其余节点做领导性工作。 Kafka真正起作用的还是分区leader和分区follower。例如:一个topic会被分成4个分区,3个正本,那么一共4*3=12个分区正本,若有4个broker,那么每个broker就会以一主两从,搁置三个分区的模式均匀分布。 Kafka的分区关系就是上图这个通信模式,生产者(Product)从任意节点获取Meta信息,找到broker中的leader分区正本,会向外面写调配好的数据,leader会向集群中其余broker的follower分区正本复制一份。 在这种分区构造关系下,其实每个broker都具备了topic分区数据申请拜访以及正本复制的Master能力。所以你问我kafka是不是核心模式,下来再说。 咱们再看看kafka的阿里兄弟rocketmq rocketmq的架构曾经不应用zookeeper集群作为服务的注册发现了 rocketmq队列模式很大水平上与kafka十分像,然而具体操作细节上有本人的特点,更合乎高并发的,更多topic的,有程序要求的业务音讯解决,例如Topic进行了多个分片划分,分区又进行了多个Queue的划分,每个Queue只能对应一个消费者,来实现更高并发的生产端平衡负载。具体细节这就不赘述了。咱们次要还是看看rocketmq的分布式特色。 其实NameServer也就是做了一个broker的注册表,新注册broker或者异样退出broker都向对应的NameSever汇报或感知,NameServer之间是无核心的,大家通过锁注册表的形式共享信息,NameServer减少/删除所辖broker到这个注册表,并定时读取最新的集群所有broker信息。 生产者(Producet)连贯上一个NameServer,就能获取到想要的发送分区数据的brokers,消费者同理,发送生产的这个过程很相似Kafka操作topic,只是更粗疏到topic下的queue这个级别。 rocketmq还有一个特点是每个borker能够再分成主从模式,master进行队列操作,slave只做数据同步,期待master呈现故障进行替换。 rocketmq的namesever绝对于zookeeper具备更简略的构造,生产者和消费者对broker以及分区的获取必须来自namesever,只管namesever集群自身是无核心的,但整个rocketmq的brokers就是被namesever中心化治理的,但整体上product、consumer、brokers集群对这种集中管理的依赖水平其实不高,只是提供了很简略的broker元信息服务,真正的数据流还是交给各个broker本人去解决。 kafka的broker分区信息是散布在每一台broker的meta缓存外面,生产者和消费者能够在任意一台borker上获取须要操作的leader分区信息,kafka这就有点去核心的意思。然而这些meta缓存信息本质是来自zookeeper,zookeeper是必须依赖的,所以实质上Kafka仍然是中心化治理。 oceanbase分布式架构oceanbase是LSM-Tree的一个典型实现,对于LSM-Tree能够看我的另一篇针对TiDB的答复文章中,次要对RocksDB的LSM-Tree的特色做了形容:为什么分布式数据库这么喜爱用kv store? 作为oceanbase的架构,这次就不说太多了,就是想简略总结一下,oceanbase架构十分奇妙地融入了Lambda架构思维,但又和Lambda架构思维的关注点不同,Lambda架构关注的是计算,而oceanbase是存储。 oceanbase往往rootServer、updateServer部署在一个节点,独特承当了分布式核心的作用。 rootServer用于治理集群。updateServer用于增量数据更新,尽量在内存中实现增量,造成最高效的近期增量数据查问,往往是当天数据。 chunkServer用于基线数据存储,理论状况往往是隔天历史数据。 mergeServer,承受客户端的SQL进行解释,并且对updateServer查问后果、不同chunkServer节点查问后果数据合并,往往是当天增量数据和隔天历史数据的查问与合并。 这与Lambda架构的速度层、批量层、服务层的思维十分相似。当客户发动查问统计申请,updateServer满足当天增量数据的实时查问统计,chunkServer节点提供基线数据的分布式查问,最终由mergeServer对updateServer当日后果和各chunkServer基线后果进行合并后,反馈给客户端,总之oceanbase架构设计是个艺术品。 总结这篇文章次要是介绍了分布式中redis cluster去中心化治理,kafka与rocketmq中心化治理的架构特点,顺便提了一些oceanbase的架构特色。 音讯队列架构对于集中模式的依赖很轻,rocketmq也只是简略粗犷地应用了nameserver,用于broker注册发现,我认为kafka齐全能够在未来的设计勾销zookeeper,用更为去中心化的思路来设计注册和发现。 反观redis最成熟的计划还是主从,redis cluster带来的性能劣势无奈对消去中心化带来的不成熟和不牢靠问题,导致人工运维的复杂度和难度。所以redis cluster慎用! oceanbase的架构很优雅也很艺术,抽时间好好再了解实际写一篇,oceanbase相似Google的Bigtable,Hadoop的Hbase,只是在其之上融入了Lambda架构的思维。让零碎体现得更符合实际需要,也更为灵便牢靠。但集群对资源需要不少。 我是“读字节”创作者,深刻大数据技术、解读分布式架构 返回读字节的知乎——理解更多对于大数据的常识公众号“读字节” 分布式,大数据,软件架构的深度,业余解读

March 14, 2021 · 1 min · jiezi

关于redis:redis入门教程

redis是基于C语言开发的一个开源非关系型内存数据库(key/value型数据库) 特点反对数据长久化存储构造反对多种数据结构 String list Set ZSet Hash反对数据备份 master-slave 模式数据备份劣势高性能丰盛的数据结构原子性,反对事务丰盛的个性 (publish/subscribe, 告诉, key 过期)利用缓存,数据库,消息中间件等 装置并启动如下图所示 客户端redis-cli 应用 redis-cli -h 查看帮忙信息 参考网站https://redis.io/http://redis.cn/数据结构-Strings 字符串类型redis中最根本的数据类型,一个key对应一个value 二进制平安 能够蕴含 数字 字符串 图片 序列化对象等 string类型能够用来存储缓存,session,计数器(redis单线程模式,一个命令执行完 后才会执行下一个命令)等 常用命令 set get del 127.0.0.1:6379> set name 123OK127.0.0.1:6379> get name"123"127.0.0.1:6379> del name(integer) 1127.0.0.1:6379> get name(nil)INCR(递增1) INCRBY(递增一个范畴) DECR(递加1) DECRBY(递加一个范畴) 127.0.0.1:6379> get counter(nil)127.0.0.1:6379> INCR conter(integer) 1127.0.0.1:6379> INCR conter(integer) 2127.0.0.1:6379> INCR conter(integer) 3127.0.0.1:6379> INCR conter(integer) 4127.0.0.1:6379> get conter"4"127.0.0.1:6379> INCRBY conter 10(integer) 14127.0.0.1:6379> get counter(nil)127.0.0.1:6379> get couter(nil)127.0.0.1:6379> get conter"14"127.0.0.1:6379> DECR conter(integer) 13127.0.0.1:6379> DECRBY Conter 3(integer) -3127.0.0.1:6379> DECRBY conter 3(integer) 10ps:命令不辨别大小写,key辨别大小写 ...

March 14, 2021 · 2 min · jiezi

关于redis:Redis安装

title: Redis装置categories: [Redis]tags: [数据库]date: 2021/01/04 作者:hackett 微信公众号:加班猿 一、Linux源码装置去官网下载最新的版本6.0.9,下载地址:https://redis.io/download Download, extract and compile Redis with:  wget https://download.redis.io/releases/redis-6.0.9.tar.gz  tar xzf redis-6.0.9.tar.gz //解压 cd redis-6.0.9 //进入源码目录 make //间接make装置在make过程中可能存在以下报错的状况  make: *** [server.o] Error 1 //make装置报错起因是: gcc版本过低,centos yum装置的gcc是4.8.5的。因而须要降级gcc,降级过程如下:  yum -y install centos-release-scl yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils scl enable devtoolset-9 bash echo "source /opt/rh/devtoolset-9/enable" >> /etc/profile gcc -v二、Ubuntu apt命令装置应用apt命令装置  sudo apt-get update sudo apt-get install redis-server三、启动服务并测试进入src目录并后盾启动redis服务  cd src ./redis-server & //后盾运行应用客户端程序redis-cli和redis服务交互  ./redis-cli //启动redis客户端上面咱们来测试一下(127.0.0.1是本机IP,6397是redis的服务端口号)  [root@VM-0-11-centos src]# ./redis-cli 127.0.0.1:6379> 127.0.0.1:6379> set foo bar OK 127.0.0.1:6379> get foo "bar" 127.0.0.1:6379>redis的配置(通过批改 redis.conf 文件或应用 CONFIG set 命令来批改配置,CONFIG get 命令查看设置配置项) ...

March 13, 2021 · 1 min · jiezi

关于redis:Java面试美团面经三面

前言美团三面面经,一面没记录,凑合着看吧哈哈哈哈二面为什么要到职? 我的项目太欠缺了,我想去一些没那么欠缺的项目组,体验我的项目逐步欠缺的过程.....本人对我的项目的理解状况,给本人打个分 满分100,我给本人60。 “说下起因”,,讲完之后, “也就是你本人还没了解透你的零碎,为什么不深刻学习,要到职” ?????说一下我的项目我想说的是我的项目意义,我的项目模块,业务线过程,数据流转。后果他问我输出是什么输入是什么,输出是什么字段,输入内容有什么字段~~ (这个讲我的项目的思路不错,能够学习)你负责的是这么多业务中的哪个我的项目,讲一下你做代表性的事件qps多少,讲一下性能瓶颈(我说没瓶颈)如果10000倍流量来了,服务扛得住吗,瓶颈是啥,你服务会怎么样,? 那你还说没瓶颈服务可用性怎么算,你们可用性是多少? 几个9?怎么做压测的,压测看什么指标,。。。。。压测看cpu跟内存,具体怎么看,cpu的什么值?怎么判断内存是否良好?如果你服务有10倍流量来了,你要怎么做限流怎么做,为什么你们用令牌桶算法分布式系统中怎么失去一个惟一的id,你们零碎有用到吗我的项目中讲到了redis,说一下redis怎么用的(本义了一下,原来是依据我的项目的业务问怎么做,而后我就说用redis实现)为什么redis快为什么不必其余nosql 数据库?RDB,AOF是啥,你们怎么用的你们redis是怎么部署的,双机房多节点,机房外面是怎么部署的(我说集群+哨兵,然而我没讲明确,只是讲个概念),他感觉我是讲概念,没真正理解过为什么要双机房容灾备份,什么时候会整个集群都挂掉Kafka 用吗,你们用kafka来干嘛的,kafka怎么保障音讯不失落的如果10倍流量来了,你们redis扛得住吗?为什么要双机房死锁遇到过吗,讲一下多线程理解吗, 说一下synchronized 跟 reentrentLock的区别写消费者生产者模型三面为啥到职你心愿的工作是怎么的说一下你做过的事件说一下你了解一个零碎怎么才算好Mysql dateTime跟timeStamp的区别外部类跟动态外部类的区别频繁gc怎么办tcp晓得吧http的header有哪些浮点数求立方根总结对面试者次要有以下这些点要留神: 不要连着面试,最好面完后,如果能够抉择的话,即便过了,也不要连着面。因为很累。不要说老东家好话,否则会被面试官怼的。不要不筹备就来面试,我遇到过一些面试者,答复到一半,而后就说不下去了,而后说工作忙,没工夫温习。作为面试官,不会因为你没筹备面试的工夫,就给你放水。根底要扎实,如果你想进大厂或者技术气氛好的公司,你肯定要器重根底,即便你对框架源码很熟,但个别电话面或者一面,是不会问框架的。跳槽频繁,有一个候选人处于不上不下的时候,老大一看简历,发现上一份工作经验是7个月,就间接不要了。有一个候选人工作教训8年,但每份工作经验都刚好多一年多点,好在根底扎实,才让过的。如果你实力很好,跳槽多一些,不会有太大影响。如果你个别,千万别常常跳,最好在一个公司积淀积淀。絮叨非常感谢你能看到这里,如果感觉文章写得不错 求关注 求点赞 求分享 (对我十分十分有用)。 如果你感觉文章有待进步,我非常期待你对我的倡议,求留言。 如果你心愿看到什么内容,我非常期待你的留言。 各位的捧场和反对,是我创作的最大能源!

March 13, 2021 · 1 min · jiezi

关于redis:一款在线编辑组件

开源一款在线编辑组件,兼容各种浏览器,反对一维、二维模板绘制,反对导入、导出Excel,可将模板保留json、xml文件格式,单元格权限设计、数据源获取、数据汇总、撑持加减乘除根本单元格算法。软件架构SpringBoot、shrio、redis、thymleaf、layui装置教程本地须要redis服务,数据库在represources下应用阐明Springboot版本2.2.6.RELEASE,前端编辑只基于jquery-2.0.3.js,兼容各种浏览器版本gitee:https://gitee.com/arch777/mer...展现成果

March 12, 2021 · 1 min · jiezi

关于redis:面试Redis缓存并发-缓存雪崩-缓存穿透

本文次要叙述缓存并发,缓存雪崩,缓存穿透的问题以及解决方案。缓存并发什么是缓存并发场景:在你每天刷抖音,看微信短视频时,都会有一个评论列表,在评论列表中,查问评论的时候,会先去查问Redis缓存,如果有,就立刻返回;如果没,就去数据库查问数据,接着更新缓存,返回数据。这时候,如果访问量十分多,有多个C端同时查问评论,Redis缓存又恰好没缓存数据,此时,多个C端就会同时去查询数据库。上述这种景象,就被称为缓存并发。 话说回来,缓存并发会带来什么危害让数据库的压力剧增,因为数据库抗不了高并发,流量再大一点,能够间接被打垮,对用户极其不敌对,在现在互联网上,App利用的被代替率是很高的,稍有不慎,用户就会被其余App抢走,这对企业来说是灾难性的。咱们能够晓得,Redis这玩意儿,要么不出问题,一出问题,必定是大问题。这也就是为什么要强调知其然知其所以然的起因。既然咱们曾经晓得缓存并发的的严重性,那如何解决要解决问题前,咱们得剖析问题为何会产生。絮叨一下,很多人无论是在面试时或者工作时,遇到问题,就立马改,或者说依照百度给的办法就套上去试,这个不行,试那个。这种解决问题的形式是不正确的。个别解决问题的方法论是:遇到报错——定位问题——剖析问题——设计解决方案——解决问题。回到缓存并发问题上,咱们剖析一下“为什么呈现缓存并发”。为什么会缓存并发起因一:在高并发场景下,机器刚刚启动,且没预热缓存,缓存都为空,又没用分布式锁起因二:在高并发场景下,机器运行已运行一段时间,但缓存刚好生效,又没用分布式锁起因三:在高并发场景下,Redis宕机了以上3种起因都会产生缓存并发,如有脱漏其余起因,欢送各位同学在留言区补充。 晓得起因后,咱们能够对照起因来设计解决方案了。 解决方案针对起因一和起因二,计划 :分布式锁。这个容许一个线程去申请数据库,其余线程挂起,线程查完数据库后,更新缓存,其余线程去拜访缓存,返回数据。至于分布式锁如何应用和其底层实现,其实有比拟多的细节留神的,但这里不过多解说,后续会陆续出对应的文章,如果你安耐不住寂寞,能够去谷歌一下。针对起因三,计划:Redis的高可用。说到高可用,无非就是主从构造+哨兵模式,或者Redis集群。(加链接)分布式锁和Redis高可用,其实是预防措施,这些应该是事先工作。如果当初缓存并发的确曾经产生了,能做的就是把这个模块服务的流量入口放大,免得因这个模块服务流量过大把MySQL间接打死,从而导致其余模块服务受到影响。如果是Redis宕机了,先把流量入口放大,而后连忙重启机器。 当然,最好是事先做好Hystrix的限流、降级、拒绝服务等工作。限流和降级,限流,顾名思义就是限度流量,容许多少流量能够通过,比方每秒最多1000。超过1000后的申请,就走降级,比方返回一些默认值或者情谊提醒:目前零碎忙碌,稍后重试。拒绝服务,则是最初一道防线,如果流量继续一段时间后,依然很大,就间接拒绝服务,拒绝服务是为了爱护Redis间接被流量一波带走,如果Redis服务被打死后,复原是比拟消耗工夫的,而且也会因为流量始终很大,刚重启,流量一波又间接带走Redis,实现双杀,Double Kill。拒绝服务,会等流量小后,较快复原回失常服务状态。拒绝服务是无可奈何之举。 当初大头菜初入互联网行业时,老马识途,什么也不懂,用Redis前,只晓得Redis很厉害,很适宜做缓存,对于Redis的注意事项,除了晓得在生产环境不能用keys *命令外,其余一律不懂。过后的评论我的项目,因为流量特地大,并发贼高,查问评论接口就呈现了缓存并发问题,幸好提前做了默认值回复和限流+降级措施。上面是用分布式锁解决缓存并发的要害代码: @Autowired private DistributionLock locker; //没缓存,查数据库,获取评论 if (comment == null) { //加分布式锁,只容许一个线程去回源 if(locker.trylock(Constants.QUERYCOMMENT+moduleType+resourceId)){ try { comment = getDataFromRedis(moduleType, resourceId); if(comment == null){ //缓存没数据,去数据库查 comment = getDataFromMongoDB(moduleType, resourceId); } }finally { locker.unlock(Constants.QUERYCOMMENT+moduleType+resourceId); } } 接下来,持续讲缓存穿透 缓存穿透什么是缓存穿透场景:查问评论的时候,如果间接查问id=-1的数据,那么在缓存中,没命中,又去数据库中查找,又没命中。上述这种状况,被称为缓存穿透。用通俗易懂的话来概括:就是查找一个肯定不存在数据库的数据,就叫缓存穿透。 那缓存穿透有什么害处呢如果流量大时,会间接打趴服务,造成服务不可用。依照方法论的套路持续走 为什么会呈现缓存穿透起因一,非正常申请,比方:黑客攻击,专门结构一些非凡格局的数据来申请,给零碎造成微小压力。起因二,失常申请,用户输错了数据。解决方案计划一:缓存空对象:在申请时,先拜访缓存,查不到数据,再去数据库查问,数据库也查不到对应的数据,返回null给客户端。且异步更新缓存(key,“null”),并退出短暂的过期工夫。 计划二:计划一其实有一个显著的毛病,就是如果申请的数据肯定不存在时,那么这个时候,缓存就缓存一大堆无用的(key1,"null"),(key2,"null")。节约内存。这个时候能够联合数据校验和布隆过滤器。 说到数据校验,这个事儿是特地重要的。尤其是在一些间接波及到钱的服务中,数据校验是巨重要的。如果不进行数据校验,大公司的老板就少一台宾利。小公司,就可能间接破产了。上面是大头菜的同学所在公司的案例 不论如何,造就良好的开发习惯,能让你受害一生。 缓存雪崩什么是缓存雪崩场景:在评论列表中,如果有一批评论成为了热点评论,但可怜,此时这批条评论,在Redis缓存中,都生效了,因为没命中缓存,加上大量申请,都去数据库查问评论,从而给数据库造成极大压力,甚至解体。这种状况,被称为缓存雪崩。 缓存雪崩的害处给数据库极大压力,甚至打垮数据库,从而造成零碎不能失常提供服务。 为什么会缓存雪崩起因一,redis宕机,相当于多个key同一时刻生效。起因二,redis没宕机,多个key失常到时就生效。总结:如何你面试的时候,遇到这个问题,最好分状况答复,就是redis是否宕机。给面试官留下脑子清晰的印象。解决方案计划一,解决起因一,既然宕机了,那就想到高可用,redis集群,哨兵模式,故障转移和故障复原,同时还应该做好监控和报警。如果没法主动实现故障转移,那就人工干预。计划二,过期工夫=生效工夫+随机工夫,解决起因二。计划三,永不过期,既然你是因为过期工夫到了导致的雪崩,那就罗唆让你不过期就完事了。有人会问,那缓存一致性怎么保障?后盾被动更新:就是通过mysql更新的时候,让mq监听Binlog,回调更新缓存。使其缓存和数据库数据保持一致。计划四,能够从利用架构角度登程,通过限流,降级,熔断伎俩来升高影响,除此之外来防止多级缓存来防止这种劫难。如果你应用的微服务架构是SpringCloud,那你能够间接应用Hystrix,来实现限流,降级,熔断,批改一下配置文件即可。补充缓存击穿,就是只有一个key过期的缓存雪崩。总结全篇下来,简直都是依照遇到报错——定位问题——剖析问题——设计解决方案——解决问题方法论来写的。文中介绍了缓存并发,缓存穿透,缓存雪崩的定义,危险,起因,解决方案。大头菜心愿你读完这篇文章后,不仅能学会常识,更能把握定位问题——剖析问题——解决问题的方法论。知识点,这些当前可能会忘,但办法把握好后,方能见招拆招。 非常感谢你能看到这里,如果感觉文章写得不错 求关注 求点赞 求分享 (对我十分十分有用)。如果你感觉文章有待进步,我非常期待你对我的倡议,求留言。如果你心愿看到什么内容,我非常期待你的留言。各位的捧场和反对,是我创作的最大能源!

March 11, 2021 · 1 min · jiezi

关于redis:玩转java8-Lambda表达式一

Lambda表达式是对象,是一个函数式接口的实例,一般接口不能应用Lambda表达式。若想理解Lambda表达式及函数式接口介绍,请移步进行学习Java8 lambda表达式及自定义函数式接口入门。 Lambda 表达式语法 (lambda paramters) -> lambda expression;小括号():代表办法签名,当只有一个参数的时候,()能够省略lambda paramters:代表具体形参,参数能够指定类型也能够省略类型,因为Lambda表达式会主动推断出参数类型->:代表lambda操作符lambda expression:代表lambda表达式body体,具体的函数式接口惟一办法实现逻辑。当body体只有一行代码的时候,{}和return都能够省略Lambda 表达式练习 要点:一看参数,二看返回值\`谬误示例: 参数类型要么全副省略,不能省略局部,如 (x, int y) -> x+y;参数不能应用final润饰,如(final a)->a;函数表达式接口不能返回一个Object对象,如Object obj = () -> "lambda";不容许应用throws语句来申明它可能会抛出的异样,只能在办法上抛出异样,如@Testpublic void testCallable() throws Exception{Callable callable = ()->{return 1;};callable.call();}\`无参无返回值/** * 无参无返回值 */@Testpublic void testNoArgsNoReturn(){ /** * 当大括号{}包含多行执行语句,则{}不能省略 */ Runnable t1 = () -> { System.out.println("t1 running..."); System.out.println("t1 run ended."); }; /** * 当大括号{}只有一行执行语句,则{}能够省略,如下写法都正确 */ Runnable t2 = () -> {System.out.println("t2 running...");}; Runnable t3 = () -> System.out.println("t3 running..."); /** * 当没有任何实现语句时,{}须要保留 */ Runnable t4 = () -> {}; new Thread(t1).start(); new Thread(t2).start(); new Thread(t3).start(); try { Thread.sleep(1000); } catch (InterruptedException e) { }}无参,有返回值/** * 测试无参,有返回值 */@Testpublic void testNoArgsReturn() { /** * 当大括号{}包含多行执行语句,则{}不能省略 */ Supplier<String> s1 = () -> { System.out.println("invoke get method"); return "lambda"; }; /** * 当大括号{}只有一行执行语句,则{}能够省略,如下写法都正确 */ Supplier<String> s2 = () -> { return "lambda"; }; Supplier<String> s3 = () -> "lambda"; /** * 也能够返回null */ Supplier<String> s4 = () -> null; System.out.println(s1.get()); System.out.println(s2.get()); System.out.println(s3.get()); System.out.println(s4.get());}有一个参数,无返回值/** * 测试只有一个参数,无返回值 */@Testpublic void testArgsNoReturnValue(){ /** *指定参数str 类型为String */ Consumer<String> c0 = (String str)->{System.out.println("c0:"+str);}; /** * 也能够不指定参数类型,会依据Consumer<String> 泛型主动推断接管的参数类型。 * 当只有一个参数时,参数局部的小括号能够省略,如下c1/c2写法都正确 */ Consumer<String> c1 = (str)->{System.out.println("c1:"+str);}; Consumer<String> c2 = str->{System.out.println("c2:"+str);}; c0.accept("lambda"); c1.accept("lambda"); c2.accept("lambda");}有一个参数,有返回值/** * 测试只有一个参数,有返回值场景 */@Testpublic void testArgsReturnValue() { /** * Function<Integer, String>用于接管一个参数,输入一个返回值 * 其中Integer示意输出参数类型,String示意返回值类型 */ Function<Integer, String> f1 = (Integer str) -> { return "f1:"+String.valueOf(str); }; /** * 能够省略参数类型,省略大括号{}和return */ Function<Integer, String> f2 = (str) -> { return "f2:"+String.valueOf(str); }; Function<Integer, String> f3 = (str) -> "f3:"+String.valueOf(str); /** * 因为只有一个参数,也能够省略小括号() */ Function<Integer, String> f4 = str -> "f4:"+String.valueOf(str); System.out.println(f1.apply(123)); System.out.println(f2.apply(124)); System.out.println(f3.apply(125)); System.out.println(f4.apply(126));}多个参数,无返回值/** * 测试多个参数,无返回值场景 */ @Test public void testMultiArgsNoReturn(){ /** * BiConsumer<String,Integer> 用于接管2个不同类型的参数,泛型指定了两个参数的类型 * 因为参数多余1个,则小括号()不能省略 */ BiConsumer<String,Integer> b1 = (String str, Integer num)->{System.out.println("b1:"+str+num);}; /** * 参数类型能够省略,要么全副省略参数类型,如(str, num)是能够的, * 然而不能只省略一个类型则不能够,如(String str, num)或(str, Integer num) */ BiConsumer<String,Integer> b2 = (str, num)->{System.out.println("b2:"+str+num);};// BiConsumer<String,String> b3 = (str, num)->{System.out.println("b3:"+str+num);}; b1.accept("lambda",666); b2.accept("lambda",666); }多个参数,有返回值/** * 测试多个参数,有返回值场景 */@Testpublic void testMultiArgsReturnValue(){ /** * BiFunction<String,String,Integer> 用于接管2个输出参数,输入一个返回值,输出和输入是不同类型 */ BiFunction<String,String,Integer> f1 = (String str1,String str2)->{return str1.length()+str2.length();}; /** * BinaryOperator<Integer> 用于接管2个输出参数,输入一个返回值,输出和输入是雷同类型,是BiFunction的非凡状况 */ BinaryOperator<Integer> f11 = (Integer num1,Integer num2)->{return num1+num2;}; /** * 省略参数类型 */ BiFunction<String,String,Integer> f2 = (str1, str2)->{return str1.length()+str2.length();}; BinaryOperator<Integer> f22 = (num1, num2)->{return num1+num2;}; /** * 省略大括号{}和return ,必须同时省略 */ BiFunction<String,String,Integer> f3 = (str1,str2)->str1.length()+str2.length(); BinaryOperator<Integer> f33 = (num1, num2)->num1+num2; System.out.println(f1.apply("java"," lambda")); System.out.println(f2.apply("java"," lambda")); System.out.println(f3.apply("java"," lambda")); System.out.println(f11.apply(11,22)); System.out.println(f22.apply(11,22)); System.out.println(f33.apply(11,22));}因为自己程度无限,如有谬误,欢送拍砖 ...

March 11, 2021 · 2 min · jiezi

关于redis:Redis工具收费后新的开源已出现

作者:三十三重天博客: zhouhuibo.club 引言Redis工具哪家强,中国山东找蓝翔。哎呀,串台了。 家喻户晓,开源的最终还是免费。 Reids Desktop 秉承了这一理念,苦逼的程序员和运维最初只能应用免费前的开源版本进行应用。想要领会商业性能吗?那就给钱吧。惋惜大部分的公司的要求是可用即可,开源的版本足够应用,更高级的性能咱也用不到,花那个冤枉钱做什么。 然而随着应用的日日夜夜,我终于还是对RedisDesktopManager感到不难受。 说说吐槽的点: 搜寻性能的坑爹性当你想到检索一个key,而你的hashset中却有很多的内容时,你必须一个一个的分页,通过眼睛看的形式找到内容。难道一次性找到就这么难吗,肯定要搞个散布? console控制台控制台常识记录历史,不反对联想输出 弹出窗因为开源,所以版本必定提旧的,就会提醒你须要更新。每一次关上都有弹出,这是真的好受。 有什么代替计划吗有人免费,就会催生出新的开源。这是一场持久性的和平。 Another Redis Desktop ManagerGithub地址 一个更快,更好,更稳固的redis桌面管理器,兼容Linux, windows, mac。更重要的是,它不会在加载大量的键时解体。截止写文章时 GitHub Star12.3K ???????????? 亲测应用,爽的飞起。大家能够通过几张截图对这个工具的性能有一个大略的理解,通过本文给出的链接大家能够下载,如果github速度太慢,能够通过这个地址进行下载。 https://download.csdn.net/dow... 最初关注公众号 程序员工具集 ???????? 致力于分享优良的开源我的项目、学习资源 、常用工具回复关键词“关注礼包”,送你一份最全的程序员技能图谱。

March 11, 2021 · 1 min · jiezi

关于redis:Go-语言开发设计指北

情谊提醒:此篇文章大概须要浏览 20分钟33秒,不足之处请多指教,感激你的浏览。 订阅本站此文章首发于 Debug客栈 |https://www.debuginn.cn Go 语言是一种强类型、编译型的语言,在开发过程中,代码标准是尤为重要的,一个小小的失误可能会带来重大的事变,领有一个良好的 Go 语言开发习惯是尤为重要的,恪守开发标准便于保护、便于浏览了解和减少零碎的健壮性。 以下是咱们项目组开发标准加上本人开发遇到的问题及补充,心愿对你有所帮忙:注:咱们将以下束缚分为三个等级,别离是:【强制】、【举荐】、【参考】。 Go 编码相干【强制】代码格调标准遵循 go 官网规范:CodeReviewComments,请应用官网golint lint 进行格调动态剖析; 【强制】代码格局标准按照gofmt,请装置相干 IDE 插件,在保留代码或者编译时,主动将源码通过gofmt做格式化解决,保障团队代码格局统一(比方空格,递进等) 【强制】业务解决代码中不能开goroutine,此举会导致goroutine数量不可控,容易引起零碎雪崩,如果须要启用goroutine做异步解决,请在初始化时启用固定数量goroutine,通过channel和业务解决代码交互,初始化goroutine的函数,原则上应该从main函数入口处明确的调用: func crond() { defer func() { if err := recover(); err != nil { // dump stack & log } }() // do something}func main() { // init system go crond() go crond2() // handlers } 【强制】异步开启goroutine的中央(如各种cronder),须要在最顶层减少recover(),捕获panic,防止个别cronder出错导致整体退出: func globalCrond() { for _ := ticker.C { projectCrond() itemCrond() userCrond() }}func projectCrond() { defer func() { if err := recover(); err != nil { // 打日志,并预警 } } // do }【强制】当有并发读写map的操作,必须加上读写锁RWMutex,否则go runtime会因为并发读写报panic,或者应用sync.Map代替; ...

March 10, 2021 · 3 min · jiezi

关于redis:华为云PB级数据库GaussDBfor-Redis介绍第四期高斯-Geo的介绍与应用

摘要:高斯Redis的大规模地理位置信息存储的解决方案。1、背景LBS(Location Based Service,基于地位的服务)有十分宽泛的利用场景,最常见的利用就是POI(Point of Interest)的查问,例如用户查找左近的人,左近的餐厅,左近的外卖商家等等。LBS的实现须要数据库存储地理位置信息,开源Redis是一个性能强、效率高、使用方便的缓存数据库,实现了地理位置存储的性能,能够用于LBS的数据存储。 开源Redis 3.2以上版本的Geo性能反对了地理位置信息存储管理,然而内存限度导致没有大规模利用。GaussDB(for Redis)(下文简称高斯Redis)兼容开源Redis的Geo性能,应用磁盘代替内存,冲破了开源Redis的内存限度,能够完满解决Geo的大规模利用问题。 2、开源Redis Geo介绍Redis的Geo性能反对如下 6 个 Geo 的相干操作: geoadd:增加某个地理位置的坐标。 geopos:获取某个地理位置的坐标。 geodist:获取两个地理位置的间隔。 geohash:获取某个地理位置的geohash值。 georadius:依据给定地理位置坐标获取指定范畴内的地理位置汇合。 georadiusbymember:依据给定地理位置获取指定范畴内的地理位置汇合。 Redis Geo性能的空间索引采纳 GeoHash 原理,配合zset汇合存储,查问效率靠近 log(N)。 3、为什么开源Redis Geo没有广泛应用?存储地理位置信息的利用十分宽泛,而开源Redis Geo性能也能够存储地理位置信息,并且查问效率高,为什么没有失去大规模的利用呢? 剖析存储地理位置信息的场景,都有如下特点: 数据量大大部分场景存储地理位置信息的数据量都是TB级以上的,开源Redis的数据全副寄存在内存中,节点的内存大小固定,要反对大数据量的地理位置信息存储,必须减少节点数,这会造成老本过高、大集群保护艰难等问题。 数据持续增长随着用户的增长,地理位置信息的数据也在持续增长,要求底层存储可能无损扩容。但开源Redis扩容须要从新划分hash槽进行数据迁徙,必定会影响业务。 高并发读写开源Redis主从模式下只有主节点可写,主节点高并发数据写入、高并发数据读出,写入速度过高容易造成主从沉积,数据失落。 除此之外,还须要思考备份复原,数据一致性,扩容,高可用等数据库系统能力。 备份复原开源Redis提供RDB和AOF形式备份数据,但当数据规模大时,RDB形式复原的数据一致性和完整性较差,AOF形式数据恢复的效率低。 数据一致性开源Redis的主从采纳异步复制,会呈现数据不统一的状况。 高可用开源Redis如果同时挂掉一对主从节点,局部数据将不可用,容错能力弱。 4、高斯Redis为什么适合?高斯Redis基于华为自研分布式存储系统DFV,反对PB级大规模的数据存储。解决了开源Redis高老本、存储数据量小、数据不统一等问题,具备秒扩容、超可用、强统一、低成本、主动备份、抗写能力强的劣势。 5、实用场景高斯Redis Geo性能实用于数据量大、读写频繁的场景。在外卖平台、点评平台、找房平台中,餐馆的数据、外卖骑手的数据、用户的数据、房源的数据这些数据随着用户增长,数据量过亿,对应的地理位置信息的数据量可到数TB级别,正是高斯Redis实用的场景。上面介绍在不同场景中Geo性能的利用。 5.1外卖场景:(1)用户下完外卖订单后,应用geoadd命令退出骑手的地位。 (2)应用geopos命令,用户可取得骑手的具体位置。 (3)应用georadius/ georadiusbymember命令骑手查看左近可配送的订单。 (4)应用geodist命令用户可取得骑手的间隔。 5.2点评场景:(1)新的店铺退出点评平台,应用geoadd命令,增加新店铺的地位。 (2)应用geopos命令,用户取得店铺的具体位置。 (3)应用geodist命令,用户可取得与店铺的间隔。 (4)应用georadius/ georadiusbymember,用户可查找间隔500米范畴的店铺。 5.3找房场景:(1)新的房源退出房源平台中,应用geoadd命令,增加新房源的地位。 (2)应用geopos命令,用户可取得房源的具体位置。 (3)应用geodist命令,用户可取得与房源的间隔。 (4)应用georadius/ georadiusbymember命令,用户查找左近1km范畴内的房源。 6、总结开源Redis的Geo性能查问效率高,但存在存储容量小、抗写能力弱、可用性差等显著毛病,导致了其Geo性能始终没有广泛应用。高斯Redis冲破了开源Redis的内存限度,以高性能磁盘存储数据,具备秒扩容、超可用、强统一、低成本、主动备份、抗写能力强的特点,因而高斯Redis实用于大量地理位置信息存储的场景。 7、完结本文作者:华为云高斯Redis团队。 杭州西安深圳简历投递:yuwenlong4@huawei.com 更多技术文章,关注高斯Redis官网博客:https://bbs.huaweicloud.com/community/usersnew/id_1614151726110813 PS:值此开年洽购季之际,企业新用户购买GaussDB (for Redis)4U16G任意存储规格,内存可享3个月3折。另外还有多款云数据库包年低至2.7折,0门槛抽千元大奖、新购满额送华为手机P40 Pro 5G等多重福利,链接:https://activity.huaweicloud.com/dbs_Promotion/index.html ...

March 10, 2021 · 1 min · jiezi

关于redis:配置中心apollo入门一

分布式配置核心apollo入门,欢送拍砖!!!

March 9, 2021 · 1 min · jiezi

关于redis:Redis知识点整理

Redis介绍Redis是一个应用C语言开发的数据库,Redis数据存储在内存中,所以读写速度十分快。 利用场景数据(热点)⾼并发的读写海量数据的读写对扩展性要求⾼的数据分布式缓存和本地缓存的区别分布式缓存 本地缓存 缓存一致性 较好 较弱,每个实例都有本人的缓存 堆内存占用 不占用 占用,影响垃圾回收 速度 较慢,因为须要网络传输和序列化 较快 应用场景 要求数据一致性,访问量大的场景 对数据一致性没有特地高的要求,且拜访次数多的场景 本地缓存的实现: 应用特定数据结构,比方ConcurrentHashMap使⽤开源的缓存框架 Ehcache,Ehcache 封装了对于内存操作的性能Guava Cache 是 Google 开源的⼯具集, 提供了缓存的边界操作⼯具、Redis和Memcache的区别Redis Memcache 存储形式 长久化 断电失落 反对数据类型不同 String,hash,list,set,zset 只反对key-value 速度 快 慢 缓存解决流程 常见数据结构String(字符串)最大容量为 512M list(列表)list 是字符串列表,依照插⼊程序排序。元素能够在列表的头部(右边)或者尾部(左边)进⾏增加。最大容量为 2^32-1 个。能够做音讯队列。 hash(哈希)Re­dis hash 是⼀个键值对(key-value)汇合。Re­dis hash 是⼀个 String 类型的 field 和 value 的映射表,hash 特地适宜⽤于存储对象。最大容量为 2^32-1 个。 set(汇合)Re­dis 的 set 是 String 类型的⽆序汇合。最大容量为 2^32-1 个。 zset(sorted set:有序汇合)Re­dis zset 和 set ⼀样也是 String 类型元素的汇合,且 不容许反复的成员。不同的 zset 是每个元素都会关联⼀个 dou­ble 类型的分数。zset 通过这个分数来为汇合中所有元素进⾏从⼩到⼤的排序。zset 的成员是唯⼀的,但分数(score)却能够反复。最大容量为 2^32-1 个。适宜做排行榜。 ...

March 9, 2021 · 1 min · jiezi

关于redis:我想进大厂之分布式锁夺命连环9问-大理版人在囧途

开个头,这是篇技术文章,然而昨天一天太恶心了,忍不住还是简略说下昨天的事件。 昨天早上11点飞大理,后果9点钟要出门的时候发现密码锁坏了,不必明码都能关上,一边司机徒弟在催着走,一边连忙打电话给房东和客服找人培修,这是第一。 而后飞机晚点,11点20飞到4点钟才要落地,降落的过程那叫一个平稳,我认为都要没了,这也是第一次晕飞机,几乎快吐了,这是第二。 而后快4点了,飞机总算快要起飞了,轮子都快着地了,后果愣是拔起来又腾飞了,最初晓得是大理8级大风,机长不敢落地。。。这是第三。 最初告诉腾飞不晓得什么时候,要等大理那边告诉,没有方法,咱们只好下飞机转高铁,急急忙忙的一路转,总算赶上了最初7点前的高铁,否则就要等到9点当前了,最初一路周转,9点多总算到了酒店,好在酒店还算行,没有让我太过于悲观。 这一天搞下来,整个一人在囧途,太累了。好吧,废话就这么多,文章开始。 说说分布式锁吧?对于一个单机的零碎,咱们能够通过synchronized或者ReentrantLock等这些惯例的加锁形式来实现,然而对于一个分布式集群的零碎而言,单纯的本地锁曾经无奈解决问题,所以就须要用到分布式锁了,通常咱们都会引入三方组件或者服务来解决这个问题,比方数据库、Redis、Zookeeper等。 通常来说,分布式锁要保障互斥性、不死锁、可重入等特点。 互斥性指的是对于同一个资源,任意时刻,都只有一个客户端能持有锁。 不死锁指的是必须要有锁超时这种机制,保障在呈现问题的时候开释锁,不会呈现死锁的问题。 可重入指的是对于同一个线程,能够多次重复加锁。 那你别离说说应用数据库、Redis和Zookeeper的实现原理?数据库的话能够应用乐观锁或者乐观锁的实现形式。 乐观锁通常就是数据库中咱们会有一个版本号,更新数据的时候通过版本号来更新,这样的话效率会比拟高,乐观锁则是通过for update的形式,然而会带来很多问题,因为他是一个行级锁,高并发的状况下可能会导致死锁、客户端连贯超时等问题,个别不举荐应用这种形式。 Redis是通过set命令来实现,在2.6.2版本之前,实现形式可能是这样: setNX命令代表当key不存在时返回胜利,否则返回失败。 然而这种实现形式把加锁和设置过期工夫的步骤分成两步,他们并不是原子操作,如果加锁胜利之后程序解体、服务宕机等异常情况,导致没有设置过期工夫,那么就会导致死锁的问题,其余线程永远都无奈获取这个锁。 之后的版本中,Redis提供了原生的set命令,相当于两命令合二为一,不存在原子性的问题,当然也能够通过lua脚本来解决。 set命令如下格局: key 为分布式锁的keyvalue 为分布式锁的值,个别为不同的客户端设置不同的值 NX 代表如果要设置的key存在返回胜利,否则返回失败 EX 代表过期工夫为秒,PX则为毫秒,比方下面示例中为10秒过期 Zookeeper是通过创立长期程序节点的形式来实现。 当须要对资源进行加锁时,实际上就是在父节点之下创立一个长期程序节点。客户端A来对资源加锁,首先判断以后创立的节点是否为最小节点,如果是,那么加锁胜利,后续加锁线程阻塞期待此时,客户端B也来尝试加锁,因为客户端A曾经加锁胜利,所以客户端B发现自己的节点并不是最小节点,就会去取到上一个节点,并且对上一节点注册监听当客户端A操作实现,开释锁的操作就是删除这个节点,这样就能够触发监听事件,客户端B就会失去告诉,同样,客户端B判断本人是否为最小节点,如果是,那么则加锁胜利你说改为set命令之后就解决了问题?那么还会不会有其余的问题呢?尽管set解决了原子性的问题,然而还是会存在两个问题。 锁超时问题 比方客户端A加锁同时设置超时工夫是3秒,后果3s之后程序逻辑还没有执行实现,锁曾经开释。客户端B此时也来尝试加锁,那么客户端B也会加锁胜利。 这样的话,就导致了并发的问题,如果代码幂等性没有解决好,就会导致问题产生。 锁误删除 还是相似的问题,客户端A加锁同时设置超时工夫3秒,后果3s之后程序逻辑还没有执行实现,锁曾经开释。客户端B此时也来尝试加锁,这时客户端A代码执行实现,执行开释锁,后果开释了客户端B的锁。 那下面两个问题你有什么好的解决方案吗?锁超时 这个有两个解决方案。 针对锁超时的问题,咱们能够依据平时业务执行工夫做大抵的评估,而后依据评估的工夫设置一个较为正当的超时工夫,这样能一大部分水平上防止问题。主动续租,通过其余的线程为将要过期的锁缩短持有工夫锁误删除 每个客户端的锁只能本人解锁,个别咱们能够在应用set命令的时候生成随机的value,解锁应用lua脚本判断以后锁是否本人持有的,是本人的锁能力开释。 #加锁SET key random_value NX EX 10#解锁if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1])else return 0end理解RedLock算法吗?因为在Redis的主从架构下,主从同步是异步的,如果在Master节点加锁胜利后,指令还没有同步到Slave节点,此时Master挂掉,Slave被晋升为Master,新的Master上并没有锁的数据,其余的客户端依然能够加锁胜利。 对于这种问题,Redis作者提出了RedLock红锁的概念。 RedLock的理念下须要至多2个Master节点,多个Master节点之间齐全相互独立,彼此之间不存在主从同步和数据复制。 次要步骤如下: 获取以后Unix工夫依照程序顺次尝试从多个节点锁,如果获取锁的工夫小于超时工夫,并且超过半数的节点获取胜利,那么加锁胜利。这样做的目标就是为了防止某些节点曾经宕机的状况下,客户端还在始终期待响应后果。举个例子,假如当初有5个节点,过期工夫=100ms,第一个节点获取锁破费10ms,第二个节点破费20ms,第三个节点破费30ms,那么最初锁的过期工夫就是100-(10+20+30),这样就是加锁胜利,反之如果最初工夫<0,那么加锁失败如果加锁失败,那么要开释所有节点上的锁那么RedLock有什么问题吗?其实RedLock存在不少问题,所以当初其实个别不举荐应用这种形式,而是举荐应用Redission的计划,他的问题次要如下几点。 性能、资源 因为须要对多个节点别离加锁和解锁,而个别分布式锁的利用场景都是在高并发的状况下,所以耗时较长,对性能有肯定的影响。此外因为须要多个节点,应用的资源也比拟多,简略来说就是费钱。 节点解体重启 比方有1~5号五个节点,并且没有开启长久化,客户端A在1,2,3号节点加锁胜利,此时3号节点解体宕机后产生重启,就失落了加锁信息,客户端B在3,4,5号节点加锁胜利。 那么,两个客户端A\B同时获取到了同一个锁,问题产生了,怎么解决? Redis作者倡议的形式就是延时重启,比方3号节点宕机之后不要立即重启,而是期待一段时间后再重启,这个工夫必须大于锁的无效工夫,也就是锁生效后再重启,这种人为干涉的措施真正施行起来就比拟艰难了第二个计划那么就是开启长久化,然而这样对性能又造成了影响。比方如果开启AOF默认每秒一次刷盘,那么最多失落一秒的数据,如果想齐全不失落的话就对性能造成较大的影响。GC、网络提早 对于RedLock,Martin Kleppmann提出了很多质疑,我就只举这样一个GC或者网络导致的例子。(这个问题比拟多,我就不一一举例了,心里有一个概念就行了,文章地址:https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html) ...

March 8, 2021 · 1 min · jiezi

关于redis:Redis持久化机制

因为Redis的数据都保留在内存中,所以它能提供高性能的缓存服务。但内存中的数据是非常容易失落的,所以Redis提供了长久化机制来保障数据的平安 Redis长久化有2钟形式:快照(RDB)和日志(AOF) RDB快照RDB(Redis DataBase)是指Redis应用save或bgsave命令保留Redis在某一时刻的数据,在呈现故障复原后通过导入RDB文件来实现原有数据的复原 开启形式命令行中启动应用save或bgsave生成RDB文件save与bgsave的区别: save会阻塞过程,在RDB文件没有生成完结前,会影响应用程序对Redis的写操作执行bgsave时,主过程会fork出一个子过程用来生成RDB文件,所以不会阻塞主过程配置文件关上redis.conf配置文件,找到上图所示配置项。save选项配置了触发快照生成RDB文件的条件,dbfilename设置了RDB的文件名save选项的含意: save 900 1 : 900秒内至多有1次的数据更改操作save 300 10 : 300秒内至多有10次的数据更改操作save 60 10000 : 60秒内至多有10000次的数据更改操作只有达到3个条件中的任何一个,都会触发RDB的生成 RDB文件默认是通过LZF算法压缩的二进制文件,保留是间接的数据。在没有很大数据量的状况下,文件通常很小,有利于导入复原数据 AOF日志下面简略理解了RDB形式,在Redis主机宕机后,咱们能够导入之前生成的RDB文件来实现数据的复原。然而RDB也有它的毛病,使得在生产环境下,不能只依附这一种形式。 AOF(AppendOnlyFile)日志是记录Redis client的每一次操作命令,并以肯定的策略将命令追加到磁盘文件中。在Redis主机呈现故障复原后,逐条执行日志中的每一条记录,来实现数据的复原。 开启形式在redis.conf文件中,能够找到上述配置项。将选项appendonly设为yes即可开启AOF日志,appendfilename设置了日志文件名称。appendfsync配置了以何种策略来记录日志,有3个选项: always: 每执行一条记录,就记录到aof文件中everysec: 每1秒记录一次no: 不被动去记录,依附操作系统来进行always会来带资源的耗费,尤其在业务高峰期,写操作过多的状况下对性能有较大的影响;no对性能的影响最小,但如果Redis主机宕机,而操作系统还没有对命令刷盘的状况下,失落的数据想比拟会最多;everysec每秒操作一次,所以即便服务呈现故障也只会失落1s的数据,是对性能和数据可靠性的一种均衡,所以举荐选用此种策略。 文件内容AOF日志保留的是一条条操作命令,而不是间接的数据。文件以上图中的格局来进行命令的追加: *2:示意此条命令有2局部组成$6:示意有6个字节应用AOF形式能够在Redis宕机后,通过逐条执行命令达到数据的复原。但随着命令越来越多,文件会越来越大。追加操作会耗费肯定的磁盘IO,同时复原数据时也会须要更多的工夫。因为是记录每一条记录,所以针对同一个数据会有很多冗余的操作,这时就须要一种机制来对日志进行优化,升高文件的大小,减速数据的复原。

March 8, 2021 · 1 min · jiezi

关于redis:分布式缓存Redis

为什么这么快?纯内存单线程,防止了多线程上下文切换IO多路复用 利用场景setnx实现分布式锁 zset实现延时队列如订单超时未领取,勾销订单,复原库存。生产者:新下的订单放入延时队列,score为到期解决工夫。消费者:用一个线程轮询延时队列,判断以后工夫是否超过到期工夫,若超出,则从队列中删除订单。 过期策略定时定期惰性redis:定期+惰性 内存淘汰机制noevictionallkeys-lruallkeys-randomvolatile-lruvolatile-randomvotatile-ttl 长久化底层数据结构渐进式rehash传统的hash表在扩容迁徙数据(rehash)时,如果hash表数据量很大,一次性拷贝到新表中,务必消耗很长时间。何为渐进式rehash?就是把拷贝节点数据的过程平摊到后续的操作中,而不是一次性拷贝。 缓存雪崩、缓存穿透、缓存击穿

March 7, 2021 · 1 min · jiezi

关于redis:Redis-持久化之-rdb

1、rdb 解决了什么问题?rdb 是 redis 长久化其中的一种计划,通过快照的形式,可将内存的数据 dump 到磁盘上。 2、如何应用 rdb2.1、save 与 bgsave当客户端执行 save or bgsave 时, 服务端会将以后内存中的数据 dump 到文件上。 save 会回绝客户端所有的命令,直到服务端执行完 save 后,能力响应客户端命令。 bgsave 命令不会阻塞客户端的读写命令。 2.2、主动触发 bgsave2.2.1、开启主动触发 bgsave在 redis 中默认是开启 rdb。例如上面的 redis 配置文件,格局如下:save <second> <changes> save 900 1save 300 10save 60 10000以上配置文件的意思为: 900s 内有一次批改、300s 内有 10次 批改、60s 内有 10000 次批改就会触发 bgsave 命令,将内存数据写入 dump.rdb 文件 2.2.1、敞开主动触发 bgsave配置文件中保留 save "" 即可敞开该性能 2.3、配置文件中 rdb 相干配置# rdb 文件寄存目录dir ./# rdb 文件名称dbfilename dump.rdb# 备份时,是否压缩 rdb 文件rdbcompression yes# 重启redis时从rdb导入到内存中时检测rdb是否实现,文件有没有被损坏,版本兼容性等rdbchecksum yes#长久化失败后, 是否持续工作stop-writes-on-bgsave-error yes #rdb文件是否删除同步锁rdb-del-sync-files no3、bgsave 原理绝大部分状况下,咱们不可能手动去执行 save or bgsave,个别会依赖配置文件主动触发的 bgsave 进行数据快照。因而这里次要说 bgsave 的原理 ...

March 7, 2021 · 1 min · jiezi

关于redis:Redis单机安装生产环境配置

1、装置单机版Redis1、下载安装包 cd /usr/local/wget http://download.redis.io/releases/redis-6.0.6.tar.gz2、解压 tar -xzvf redis-6.0.6.tar.gz3、装置 cd redis-6.0.6/make && make test && make install留神:redis 6.0 以上版本须要 gcc >= 5.3, tcl > 8.5 降级步骤看文末、大家在装置过程中如果呈现问题可自行到网上查找2、生产环境启动计划生产环境要把Redis作为一个零碎的deamon过程去运行,每次系统启动,Redis过程随之一起启动 redis utils 目录下redis_init_script脚本将redis_init_script脚本拷贝到linux的 /etc/init.d目录中,并将redis_init_script重命名为redis_6379,6379是咱们心愿这个redis实例监听的端口号。批改redis_6379脚本的第六行REDISPOR设置为雷同的端口号(默认为6379,没有扭转就不须要批改了)。创立俩个目录:/etc/redis (寄存redis的配置文件),/var/redis/6379 (寄存redis的长久焕文件)批改redis的配置文件,将redis.conf(默认在根目录下 redis.conf)拷贝到/ect/redis目录中并重命名为6379.conf批改6379.conf(redis.conf)中的局部配置为生产环境> daemonize yes 让redis以daemon过程运行> pidfile /var/run/redis_6379.pid 设置redis的pid文件地位> port 6379 设置redis的端口号> dir /var/redis/6379 设置长久化文件存储的地位> bind * (或者间接正文或者填写绑定的IP) 设置外网能够拜访redis> #protected-mode yes 去掉正文 开启保护模式> requirepass youpassword 设置拜访明码7.启动redis cd /ect/init.d./redis.6379 start8.确认redis是否启动 ps -ef | grep redis9.让redis 追随系统启动自启动配置在redis_6379脚本的最下面增加如下两行内容 # chkconfig: 2345 90 10# description: Redis is a persistent key-value database保留退出执行 ...

March 5, 2021 · 1 min · jiezi

关于redis:Spring-boot-集成Redis

Redis装置Redis的装置网上文档很多,官网也有十分具体的装置文档,这里就不再赘述,如果是集体开发,倡议应用Docker进行装置,只需以下一行命令即可实现残缺 docker run -itd --name redis -p 6379:6379 redis执行以下命令查看是否运行胜利 ➜ docker exec -it redis redis-cli 127.0.0.1:6379> pingPONGSpring boot集成Redis引入依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId></dependency>配置spring.redis.host=127.0.0.1spring.redis.port=6379#客户端超时spring.redis.timeout=10000#最大连接数spring.redis.lettuce.pool.max-active=20#最小闲暇spring.redis.lettuce.pool.min-idle=5#连贯超时spring.redis.lettuce.pool.max-wait=5000ms#最大闲暇spring.redis.lettuce.pool.max-idle=20启动类增加注解@EnableCaching@SpringBootApplication@EnableCachingpublic class RedisApplication { public static void main(String[] args) { SpringApplication.run(RedisApplication.class, args); }}编写配置类,能够参考以下代码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.cache.RedisCacheWriter;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.*;import java.time.Duration;import java.util.HashMap;import java.util.Map;/** * @Description: * @author: jianfeng.zheng * @since: 2021/3/3 10:53 下午 * @history: 1.2021/3/3 created by jianfeng.zheng */@Configurationpublic class RedisConfig { @Bean RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; } @Bean public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) { RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); redisCacheConfiguration.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())); Map<String, RedisCacheConfiguration> redisExpireConfig = new HashMap<>(); //这里设置了一个一分钟的超时配置,如果须要减少更多超时配置参考这个新增即可 redisExpireConfig.put("1min", RedisCacheConfiguration.defaultCacheConfig() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) .entryTtl(Duration.ofMinutes(1)).disableCachingNullValues()); RedisCacheManager redisCacheManager = RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)) .cacheDefaults(redisCacheConfiguration) .withInitialCacheConfigurations(redisExpireConfig) .transactionAware() .build(); return redisCacheManager; }}Spring boot 1.x的redis配置和Spring boot 2.x的redis配置有很大差异,次要是2.x应用了lettuce客户端,所以网上看到的一些1.x的参考代码在2.x无奈应用一个简略的示例@RestController@RequestMapping(value = "/user")public class UserController { @GetMapping(value = "/info") @Cacheable(value = "user", key = "#uid") public User getUser(@RequestParam(value = "uid") String uid) { System.out.println("getUser====>" + uid); User user = new User(); user.setUid(uid); user.setEmail(uid + "@definesys.com"); user.setName(uid + ":" + System.currentTimeMillis()); return user; }}@Cacheable(value = "user", key = "#uid")注解将开启缓存,接口返回的数据将会被缓存,value是缓存的名称,key是缓存的健,能够应用SpEL表达式。 ...

March 5, 2021 · 2 min · jiezi

关于redis:上岸算法-I-LeetCode-Weekly-Contest-230解题报告

No.1 统计匹配检索规定的物品数量 解题思路 枚举、统计。 代码展现 class Solution { public int countMatches(List<List<String>> items, String ruleKey, String ruleValue) { int index = 0; if (ruleKey.equals("color")) { index = 1; } else if (ruleKey.equals("name")) { index = 2; } int count = 0; for (var item : items) { if (item.get(index).equals(ruleValue)) { count++; } } return count; }}No.2 最靠近指标价格的甜点老本 解题思路 递归搜寻即可,把所有的配比计划都枚举一遍。 代码展现 class Solution { int answer; public int closestCost(int[] baseCosts, int[] toppingCosts, int target) { answer = 0x3f3f3f3f; // INF for (int base : baseCosts) { dfs(base, 0, toppingCosts, target); } return answer; } private void dfs(int sum, int idx, int[] toppingCosts, int target) { if (sum - target > Math.abs(answer - target)) { return; } if (idx == toppingCosts.length) { int cur = Math.abs(sum - target); int min = Math.abs(answer - target); if (cur < min || (cur == min && sum < answer)) { answer = sum; } return; } for (int i = 0; i < 3; i++) { dfs(sum + toppingCosts[idx] * i, idx + 1, toppingCosts, target); } }}No.3 通过起码操作次数使数组的和相等 ...

March 1, 2021 · 3 min · jiezi

关于redis:Redis第十章节链表

目录数组和链表链表比照总结1、数组和链表数组: 数组会在内存中开拓一块间断的空间存储数据,这种存储形式无利也有弊病。当获取数据的时候,间接通过下标值就能够获取到对应的元素,工夫复杂度为O(1)。然而如果新增或者删除数据会挪动大量的数据,工夫复杂度为O(n)。数组的扩容机制是:如果数组空间有余,会先开拓一块新的空间地址,将原来的数组复制到新的数组中。 链表: 链表不须要开拓间断的内存空间,其通过指针将所有的数据连接起来。新增或者删除的时候只须要将指针指向的地址批改就行了,工夫复杂度为O(1)。然而查问的工夫复杂度为O(n)。 2、链表2.1、双向链表双向链表是各个节点之间的逻辑关系是双向的。 双向链表中节点的组成是:prior: 指向以后节点的前置节点,data:以后节点存储的数据。next:指向以后节点的后置节点。 2.2、压缩链表压缩链表是为了节约内存开发的。ziplist是一个特地的双向链表,没有保护双向指针prev next;反而是存储上一个entry的长度和以后entry长度,通过长度推算出下一个元素在什么中央。就义读取的性能,取得高效的存储空间,因为存储指针比存储entry长度更费内存,这就是典型的工夫换空间。2.3、quicklist链表官网介绍: A doubly linked list of ziplists A generic doubly linked quicklist implementation介绍:quicklist是一个双向链表,并且是一个ziplist的双向链表,ziplist自身是一个维持数据项先后顺序的列表,而且数据项保留在一个间断的内存块种。 3、比照3.1、双向链表双端链表便于在表的两端进行push和pop操作,然而它的内存开销比拟大。双端链表每个节点上除了要保留的数据之外,还要额定保留两个指针。双端链表的各个节点是独自的内存块,地址不间断,节点多了容易产生内存碎片。3.2、压缩列表ziplist因为是一块间断的内存,所以存储效率很高。ziplist不利于批改操作,每次数据变动都会引发一次内存的realloc。当ziplist长度很长的时候,一次realloc可能会导致大批量的数据拷贝,进一步升高性能。3.3、quicklist链表空间效率和工夫效率的折中。联合了双端链表和压缩列表的长处。4、总结在redis 3.2版本之前应用的是 双向链表和压缩链表 两种,因为双向链表占用的内存要比压缩链表高,所以创立链表时首先会创立压缩链表,在适合的时机会转化成双向链表。redis 3.2之后应用的是quicklist链表。

March 1, 2021 · 1 min · jiezi

关于redis:最全面的Redis缓存雪崩击穿穿透问题解决方案

缓存雪崩当某一时刻产生大规模的缓存生效的状况,会有大量的申请进来间接打到DB下面 解决缓存雪崩1.redis的key在同一时间大面积生效,可思考: 在批量往Redis存数据的时候,把每个Key的生效工夫都加个随机值,这样能够保证数据不会在同一时间大面积生效setRedis(Key,value,time + Math.random() * 10000);设置热点数据不设置过期工夫,有更新操作就更新缓存就好了2.redis挂了,可思考: 应用集群缓存,保障缓存服务的高可用 这种计划就是在产生雪崩前对缓存集群实现高可用,如果是应用 Redis,能够应用 主从+哨兵 ,Redis Cluster 来防止 Redis 全盘解体的状况。开启Redis长久化机制,尽快恢复缓存集群一旦重启,就能从磁盘上主动加载数据恢复内存中的数据。3.避免MySQL不挂,可思考: ehcache本地缓存 + Hystrix限流&降级,防止MySQL被打死 应用 ehcache 本地缓存的目标也是思考在 Redis Cluster 齐全不可用的时候,ehcache 本地缓存还可能撑持一阵。应用 Hystrix进行限流 & 降级 ,比方一秒来了5000个申请,咱们能够设置假如只能有一秒 2000个申请能通过这个组件,那么其 他残余的 3000 申请就会走限流逻辑。而后去调用咱们本人开发的降级组件(降级),比方设置的一些默认值呀之类的。以此来爱护最初的 MySQL 不会被大量的申请给打死。流程图: 缓存穿透用户一直发动申请缓存和数据库中都没有的数据。咱们数据库的 id 都是1开始自增下来的,如发动为id值为 -1 的数据或 id 为特地大不存在的数据。每次都能绕开Redis间接打到数据库,数据库也查不到,每次都这样,并发高点就容易崩掉了 解决缓存穿透1.接口层减少校验比方用户鉴权校验,参数做校验,不非法的参数间接代码Return,比方:id 做根底校验,id <=0的间接拦挡等。 2.缓存空值之所以会产生穿透,就是因为缓存中没有存储这些空数据的key。从而导致每次查问都到数据库去了。那么咱们就能够为这些key对应的值设置为null 丢到缓存外面去。前面再呈现查问这个key 的申请的时候,间接返回null。 3.布隆过滤器(Bloom Filter)Bloom Filter是用于判断某个元素(key)是否存在于某个汇合中。先把咱们数据库的数据都加载到咱们的过滤器中,在缓存之前在加一层BloomFilter,在查问的时候先去 BloomFilter 去查问 key 是否存在,如果不存在就间接返回,存在再走查缓存,而后查DB。 4.Nginx对单个IP每秒拜访次数超出阈值的IP都拉黑 流程图: 缓存击穿缓存击穿是指一个Key十分热点,在不停的扛着大并发,大并发集中对这一个点进行拜访,当这个Key在生效的霎时,继续的大并发就穿破缓存,间接申请数据库,就像在一个完整无缺的桶上凿开了一个洞。1.设置热点数据永远不过期 2.互斥锁咱们能够在第一个查问数据的申请上应用一个 互斥锁来锁住它。其余的线程走到这一步拿不到锁就等着,等第一个线程查问到了数据,而后做缓存。前面的线程进来发现曾经有缓存了,就间接走缓存。 参考两位大佬的文章作出的总结,大佬太强了:《咱们一起进大厂》系列-缓存雪崩、击穿、穿透阿里一面:对于【缓存穿透、缓存击穿、缓存雪崩、热点数据生效】问题的解决方案

February 28, 2021 · 1 min · jiezi

关于redis:Redis-性能测试工具介绍

之前,也和大家介绍过一些 redis 性能监控指标:Redis性能指标监控!,那么性能测试也是针对这些指标进行的。 Redis 蕴含一个名为 redis-benchmark 的性能测试工具,它能够模仿 N 个客户端同时向 Redis 发送 M 条查问命令的利用场景(相似于 Apache 的 ab 工具)。 语法格局Redis 性能测试的根本命令如下 留神:该命令是在 redis 的目录下执行的,而不是 redis 客户端的外部指令。留神:redis-benchmark 的测试后果和硬件关联比拟大,尤其是 CPU 主频的频率。# 工具应用格局$ redis-benchmark [option] [option value]参数解释Redis 性能测试工具可选参数如下所示 实例演示 以下实例来测试 Redis 性能 #同时执行 10000 个申请来检测性能$ redis-benchmark -n 10000  -qPING_INLINE: 141043.72 requests per secondPING_BULK: 142857.14 requests per secondSET: 141442.72 requests per secondGET: 145348.83 requests per secondINCR: 137362.64 requests per secondLPUSH: 145348.83 requests per secondLPOP: 146198.83 requests per secondSADD: 146198.83 requests per secondSPOP: 149253.73 requests per secondLPUSH (needed to benchmark LRANGE): 148588.42 requests per secondLRANGE_100 (first 100 elements): 58411.21 requests per secondLRANGE_300 (first 300 elements): 21195.42 requests per secondLRANGE_500 (first 450 elements): 14539.11 requests per secondLRANGE_600 (first 600 elements): 10504.20 requests per secondMSET (10 keys): 93283.58 requests per second#应用了多个参数来测试 Redis 性能# 主机为127.0.0.1;端口号为6379;执行的命令为set/lpush# 申请数为10000,通过 -q 参数让后果只显示每秒执行的申请数$ redis-benchmark -h 127.0.0.1 -p 6379 -t set,lpush -n 10000 -qSET: 146198.83 requests per secondLPUSH: 145560.41 requests per second作者: Escape 链接: https://www.escapelife.site/p...

February 27, 2021 · 1 min · jiezi

关于redis:springdataredis中同时使用setgetincrement的问题

spring-data-redis中同时应用set()、get()、increment()的问题1.问题形容最近开发代码,应用redis时,遇到一个有意思的问题,问题代码如下: class Test { /** * redis操作句柄 */ @Autowired private RedisTemplate redisTemplate; public void test() { // 先set key1,再get key1没有问题,然而再increment就会报错 redisTemplate.opsForValue().set("key1", 1); Integer val1 = redisTemplate.opsForValue().get("key1"); Long incr1 = redisTemplate.opsForValue().increment("key1"); // 先increment key2(key2之前不存在),再get key2就会报错 Long incr2 = redisTemplate.opsForValue().increment("key2"); Integer val2 = redisTemplate.opsForValue().get("key2"); }}如代码正文形容: 问题1:先set key1,再get key1没有问题,然而再increment就会报错,报错内容如下:org.springframework.dao.InvalidDataAccessApiUsageException: ERR value is not an integer or out of range; nested exception is redis.clients.jedis.exceptions.JedisDataException: ERR value is not an integer or out of range at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:69) ~[spring-data-redis-2.3.6.RELEASE.jar:2.3.6.RELEASE] at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:42) ~[spring-data-redis-2.3.6.RELEASE.jar:2.3.6.RELEASE] at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44) ~[spring-data-redis-2.3.6.RELEASE.jar:2.3.6.RELEASE] at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:42) ~[spring-data-redis-2.3.6.RELEASE.jar:2.3.6.RELEASE]问题2:先increment key2(key2之前不存在),再get key2就会报错,报错内容如下:org.springframework.data.redis.serializer.SerializationException: 反序列化对象失败; nested exception is com.caucho.hessian.io.HessianProtocolException: unknown code for readObject at 0x31 (1) at tech.joymo.framework.redis.sserializer.HessianSerializer.deserialize(HessianSerializer.java:61) ~[joymo-framework-redis-1.0-20210202.122946-5.jar:1.0-SNAPSHOT] at org.springframework.data.redis.core.AbstractOperations.deserializeValue(AbstractOperations.java:335) ~[spring-data-redis-2.3.6.RELEASE.jar:2.3.6.RELEASE] at org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:61) ~[spring-data-redis-2.3.6.RELEASE.jar:2.3.6.RELEASE] at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:228) ~[spring-data-redis-2.3.6.RELEASE.jar:2.3.6.RELEASE] at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:188) ~[spring-data-redis-2.3.6.RELEASE.jar:2.3.6.RELEASE] at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:96) ~[spring-data-redis-2.3.6.RELEASE.jar:2.3.6.RELEASE] at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:53) ~[spring-data-redis-2.3.6.RELEASE.jar:2.3.6.RELEASE]2.问题剖析剖析下面的报错内容可知,两个问题都是redis存储的数据格式有问题导致,然而为什么会有这种问题呢? ...

February 25, 2021 · 2 min · jiezi

关于redis:腾讯云大佬亲码redis深度笔记不讲一句废话全是精华

前言作为这个时代码代码的秃头人员,对Redis必定是不生疏的,如果连Redis都没用过,还真不好意思进来面试,指不定被面试官吊打多少次。 毕竟当初互联网公司和一些守业公司都要用到Redis,像亚马逊、谷歌、阿里、腾讯都要应用,可见精通Redis应用真的很有必要。 所以,明天则分享出腾讯云大神亲自码出的“redis深度笔记”,笔记内容没有讲一句废话,全篇看下来都是精髓! 须要Redis深度笔记PDF版的敌人,点击传送门即可获取到了(手速快的曾经上车了) PART1:Redis深度笔记开篇1.Redis能够用来做什么? 由Redis面试想到的Redis能够做什么? 2.Redis根底数据结构 Redis装置Redis根底的数据结构容器型数据结构的通用规定对于Redis应用的一些思考 PART2:Redis的利用总结1.分布式锁 分布式锁超时问题可重入性 2.延时队列 异步音讯队列?队列空了怎么办?队列提早闲暇连贯主动断开锁抵触解决延时队列的实现进一步优化 3.位图 根本应用统计和查找魔术指令 bitfield 4.HyperLogLog 应用办法pfadd这个pf是什么意思?pfmerge适宜什么场合用?注意事项HyperLogLog实现原理pf的内存占用为什么是12k? 5.布隆过滤器 布隆过滤器是什么?Redis中的布隆过滤器布隆过滤器的根本应用注意事项布隆过滤器的原理空间占用预计理论元素超出时,误判率会怎么变动?用不上Redis4.0怎么办?布隆过滤器的其余利用 6.简略限流 如何应用Redis来实现简略限流策略? 7.漏斗限流 Redis-Cell一些思考 8.GeoHash 用数据库来算左近的人GeoHash算法Redis的Geo指令根本应用 9.Scan scan根底应用字典的构造scan遍历程序字典扩容比照扩容缩容前后的遍历程序渐进式rehash更多的scan指令大Key扫描 PART3:Redis的原理1.线程IO模型 非阻塞IO事件轮询(多路复用)指令队列响应队列定时工作 2.通信协议 RESP(Redis Serialization Protocol)客户端->服务端服务端->客户端 3.长久化 快照原理fork(多过程)AOF原理AOF重写fsync运维Redis4.0混合长久化 4.管道 Redis的音讯交互管道压力测试深刻了解管道实质 5.事务 Redis事务的根本应用原子性discard(抛弃)优化Watch 6.PubSub 音讯多播PubSub模式订阅音讯构造PubSub毛病 7.小对象压缩 32bit vs 64bit小对象压缩存储(ziplist)内存回收机制内存调配算法 8.主从同步 CAP原理最终统一主从同步增量同步快照同步减少从节点无盘复制Wait指令 PART4:Redis集群1.Sentinel 音讯失落Sentinel根本应用 2.Codis Codis分片原理不同的Codis实例之间槽位关系如何同步?扩容主动平衡Codis的代价Codis的长处MGET指令的操作过程架构变迁Codis的难堪Codis的后盾治理 3.Cluster 槽位定位算法跳转迁徙容错网络抖动可能下线(PFAIL-Possibly Fail)与确定下线(Fail)Cluster根本应用槽位迁徙感知集群变更感知 PART5:Redis拓展1.Stream 音讯ID音讯内容增删改查独立生产创立生产组生产Stream音讯太多怎么办?音讯如果遗记ACK会怎么?PEL如何防止音讯失落?Stream的高可用分区Partition 2.Info指令 Redis每秒执行多少次指令?Redis连贯了多少客户端?Redisn内存占用多大?复制积压缓存区多大? 3.再谈分布式锁 Redlock算法Redlock应用场景 4.过期策略 过期的key汇合定时扫描策略从库的过期策略 5.LRU LRU算法近似LRU算法 6.懈怠删除 Redis为什么要懈怠删除(lazy free)?flush异步队列AOF Sync也很慢更多异步删除点 7.优雅地应用Jedis ...

February 24, 2021 · 1 min · jiezi

关于redis:Redis个人笔记二

要干嘛?redis存在内存中,内存是有大小的。满了怎么办?过期策略:redis外面有过期的数据扔掉淘汰策略:redis淘汰机制 过期策略:设置过期工夫,不见了怎么办。ttl key 能够查问它的无效工夫redis用了被动过期(惰性过期)和定期过期redis不必被动过期 被动过期(定时过期)须要定时器始终跑,过期了马上被删除对内存敌对,不会存在很多过期的key;对cpu不敌对 被动过期(惰性过期)只有拜访的时候才判断有没有过期对cpu敌对;对内存不敌对,没有及时删除过期的key 定期过期定期的去跑,去找有没有过期的,有过期的,删除过期的(相似散布式调度) 去哪里找?把所有设置过期工夫的放在一起找进去当前怎么去过期?从所有设置过期工夫的key一次性拿20个(hash桶)删除20个外面过期了的如果我这个20外面没有删除任何过期的,或者如果20个key外面删除的超过十分之一,我也会始终循环执行前两步去找过期值(删除一个,阐明没有什么过期的了,下次再来做。serverCron redis的定时事件 每100ms执行一次)每循环16次,我会查看有没有超时,超时了跳进去淘汰策略有过期策略为什么还要淘汰?所有key可能都没有设置过期工夫最大内存大小:maxmemory能够设置最大内存大小如果没有设置maxmemory的话:64位零碎为电脑内存,32位的是3G8大淘汰策略:xxx-mmm:xxx代表淘汰的范畴,mmm代表淘汰的形式redis默认用的是什么:noeviction(不采取任何措施,能取数据,不能写数据) volatile-lruallkeys-lruvolatile-lfuallkeys-lfuvolatile-randomallkeys-randomvolatile-ttlnoevictionLRU(最久未应用的)原始的LRU 依据工夫排序,淘汰最久未应用的redis原理是一样的对象有lru字段,每次拜访和创立的时候都会更新lru零碎工夫-对象lru工夫,值越大,越容易被淘汰总结: 1.每个数据对象有个lru字段,每次创立和拜访的时候都会更新lru字段,更新后的值为延后100ms的零碎工夫秒单位的最初24位。2.我会把延后100ms的零碎工夫的最初24位跟对象中的lru字段做比拟。3.发现零碎工夫比对象的lru大,那么零碎工夫减lru,相同lrulock+(LRU_CLOCK_MAX-0->lru)4.返回值越大越容易被淘汰 LFU(最不罕用的)依据次数(降序)工夫(排序)的排序实现开端淘汰redisObject.lru 字段 24位 16位工夫+8位次数 缓存场景剖析

February 24, 2021 · 1 min · jiezi

关于redis:Spring-Boot-demo系列十Redis缓存

1 概述本文演示了如何在Spring Boot中将Redis作为缓存应用,具体的内容包含: 环境搭建我的项目搭建测试2 环境RedisMySQLMyBatis Plus3 Redis装置Redis装置非常简单,以笔者的Manjaro为例,间接paru装置: paru -S redisUbuntu、CentOS之类的都提供了软件包装置: sudo apt install redissudo yum install redis如果想从源码编译装置: wget http://download.redis.io/redis-stable.tar.gztar xvzf redis-stable.tar.gzcd redis-stablemakeWindows以及其余零碎的装置能够参考此处。 4 新建我的项目新建我的项目,退出如下依赖: Maven: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope></dependency><dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional></dependency><dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version></dependency>Gradle: implementation("com.baomidou:mybatis-plus-boot-starter:3.4.2")implementation("mysql:mysql-connector-java:8.0.23")我的项目构造: 5 配置类MyBatis Plus+Redis配置类: @Configuration@MapperScan("com.example.demo.dao")public class MyBatisPlusConfig {}@Configuration@AutoConfigureAfter(RedisAutoConfiguration.class)@EnableCachingpublic class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setConnectionFactory(factory); return template; } @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith( RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()) ).serializeValuesWith( RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()) ); return RedisCacheManager.builder(factory).cacheDefaults(configuration).build(); }}重点说一下Redis配置类,这个类次要生成两个Bean: ...

February 24, 2021 · 2 min · jiezi

关于redis:Redis-Cluster-路由变更

Redis Cluster 采纳去中心化的路由计划,cluster 中的每个 node 都能够感知到残缺路由表,为了可能正确地拜访到数据,路由表的正确性保障至关重要。 在 cluster 节点数量肯定的状况下,有两种状况能够导致路由的变动,即主从关系变更和 slot resharding。同时,须要思考 server 重启和 partition 复原后如何去更新本地旧的路由信息。 本文将联合代码片段逐个剖析。 主从关系变更failover执行 failover 后,首先在本地做变更,而后通过 gossip 信息流传,使得路由在 cluster 内打平。 本节点变更不论是被动 failover 还是被动 failover,流程的最初一步都须要调用 clusterFailoverReplaceYourMaster 函数。 从代码能够看出,有以下 5 个步骤, 1)批改节点 flag 标识 /* 1) Turn this node into a master. */ clusterSetNodeAsMaster(myself); void clusterSetNodeAsMaster(clusterNode *n) { if (nodeIsMaster(n)) return; if (n->slaveof) { clusterNodeRemoveSlave(n->slaveof,n); if (n != myself) n->flags |= CLUSTER_NODE_MIGRATE_TO; } n->flags &= ~CLUSTER_NODE_SLAVE; n->flags |= CLUSTER_NODE_MASTER; n->slaveof = NULL; /* Update config and state. */ clusterDoBeforeSleep(CLUSTER_TODO_SAVE_CONFIG| CLUSTER_TODO_UPDATE_STATE);}去掉 CLUSTER_NODE_SLAVE 标识,变更为 CLUSTER_NODE_MASTER,勾销本地路由表中原有的主从关系。 ...

February 23, 2021 · 4 min · jiezi

关于redis:Redis第九章节动态字符串

目录概述SDS(动静字符串)SDS(动静字符串)与c语言字符串的区别1、概述String类型底层实现的简略动静字符串sds,是能够批改的字符串。它采纳预调配冗余空间的形式来缩小内存的频繁调配。 2、SDS动静字符串 动静字符串是以 \0 为分隔符。最大容量是redis被动调配的一块内存空间,理论存储内容是具体的存的数据。 3、SDS(动静字符串)与c语言字符串的区别1、获取存储长度不同c语言:c语言不记录长度信息,如果要获取字符串的长度,须要遍历所有的字符串,能力获取字符串的长度。获取长度的复杂度为 O(n)。 sds(动静字符串):sds存储了字符串的长度,获取长度的复杂度为 O(1)。 2、缓存溢出c语言:c语言不记录长度,在执行strcat函数时,假如调配了内存,存储的内容比曾经调配的内存多时,这个时候就会呈现缓冲区溢出景象。 sds(动静字符串):sds存储内容时,先查看内容的存储是否可能存储下理论的值,如果不能存储理论的值,就先扩大缓存区域,再将值存储到缓冲区域中。 3、内存的开拓和开释c语言:须要本人被动开释或者扩大内存,如果不可能被动开释或者扩大内存,就会呈现缓冲溢出或者泄露。 sds(动静字符串):sds采取上面的形式 1、空间预调配 // 先进行内存区域进行扩大,而后在执行上面的代码 public void test(){ if(len < 1M){ //程序调配和len属性一样的大小未应用的空间。 }else if(len > 1M){ //程序调配1M 未应用的空间。 } }2、惰性空间开释 在批改字符串时,如果理论的内容要比老的数据小,先不将缓冲区的闲暇内存开释掉,等下次存储内容时再进行空间的开释或者扩大。 4、二进制平安 c语言:C语言必须存储指定的格局数据。 sds(动静字符串):SDS不会对数据限度。 您好,我是一个Java小白,心愿和大家一起在技术的路线上一快高兴的学习。心愿与您在网络的世界上会面。

February 20, 2021 · 1 min · jiezi

关于redis:Redis-Cluster-availability-分析

本文档次要基于集体了解,剖析 Redis Cluster 设计中对于 Availability 的一些考量。 当 Redis 以 Cluster 模式启动时,对于一个 master 节点,只有当集群为 CLUSTER\_OK 状态时,能力失常承受拜访,这在之前的博客 《Redis Cluster write safety 剖析》探讨过。 Redis Cluster 设计的三个指标,最初一个才是可用性。 Redis Cluster is able to survive partitions where the majority of the master nodes are reachable and there is at least one reachable slave for every master node that is no longer reachable. Moreover using replicas migration, masters no longer replicated by any slave will receive one from a master which is covered by multiple slaves.上面次要探讨三种状况。 ...

February 19, 2021 · 3 min · jiezi

关于redis:2021Java后端工程师面试指南Redis

前言文本已收录至我的GitHub仓库,欢送Star:https://github.com/bin3923282... 种一棵树最好的工夫是十年前,其次是当初Tips面试指南系列,很多状况下不会去深挖细节,是小六六以被面试者的角色去回顾常识的一种形式,所以我默认大部分的货色,作为面试官的你,必定是懂的。 https://www.processon.com/vie...下面的是脑图地址 叨絮这个系列也写了几篇了,明天咱们来看看redis,后面的能够去github上看看。而后上面是后面的文章汇总 2021-Java后端工程师面试指南-(引言)2021-Java后端工程师面试指南-(Java根底篇)2021-Java后端工程师面试指南-(并发-多线程)2021-Java后端工程师面试指南-(JVM)2021-Java后端工程师面试指南-(MySQL)说说什么是redis吧Redis是一个凋谢源代码(BSD许可)的内存中数据结构存储,用作数据库,缓存和音讯代理。它反对数据结构,例如字符串,哈希,列表,汇合,带范畴查问的排序汇合,位图,超日志,带有半径查问和流的天文空间索引。Redis具备内置的复制,Lua脚本,LRU逐出,事务和不同级别的磁盘持久性,并通过Redis Sentinel和Redis Cluster主动分区提供了高可用性。 说说Redis有哪些优缺点长处 性能优异, Redis能读的速度是110000次/s,写的速度是81000次/s。数据长久化,反对AOF和RDB两种长久化形式。事务,Redis的所有操作都是原子性的,同时Redis还反对对几个操作合并后的原子性执行。构造丰盛,除了反对string类型的value外还反对hash、set、zset、list等数据结构。主从复制,主机会主动将数据同步到从机,能够进行读写拆散。毛病 库容量受到物理内存的限度,不能用作海量数据的高性能读写,因而Redis适宜的场景次要局限在较小数据量的高性能操作和运算上。宕机,宕机前有局部数据未能及时同步到从机,切换IP后还会引入数据不统一的问题,升高了零碎的可用性。redis 较难反对在线扩容,在集群容量达到下限时在线扩容会变得很简单。为防止这一问题,运维人员在零碎上线时必须确保有足够的空间,这对资源造成了很大的节约。说说为啥要用缓存次要是为了进步零碎的吞吐量,应答高并发,高性能场景 为什么要用 Redis 而不必 map/guava 做缓存?Java实现的Map是本地缓存,如果有多台实例(机器)的话,每个实例都须要各自保留一份缓存,缓存不具备一致性Redis实现的是分布式缓存,如果有多台实例(机器)的话,每个实例都共享一份缓存,缓存具备一致性。Java实现的Map不是业余做缓存的,JVM内存太大容易挂掉的。个别用做于容器来存储长期数据,缓存的数据随着JVM销毁而完结。Map所存储的数据结构,缓存过期机制等等是须要程序员本人手写的。Redis是业余做缓存的,能够用几十个G内存来做缓存。Redis个别用作于缓存,能够将缓存数据保留在硬盘中,Redis重启了后能够将其复原。原生提供丰盛的数据结构、缓存过期机制等等简略好用的性能。Redis为什么这么快1、齐全基于内存,绝大部分申请是纯正的内存操作,十分疾速。数据存在内存中,相似于HashMap,HashMap的劣势就是查找和操作的工夫复杂度都是O(1); 2、数据结构简略,对数据操作也简略,Redis中的数据结构是专门进行设计的; 3、采纳单线程,防止了不必要的上下文切换和竞争条件,也不存在多过程或者多线程导致的切换而耗费 CPU,不必去思考各种锁的问题,不存在加锁开释锁操作,没有因为可能呈现死锁而导致的性能耗费(绝大多数的瓶颈不在cpu) 4、应用多路I/O复用模型,非阻塞IO; 5、应用底层模型不同,它们之间底层实现形式以及与客户端之间通信的利用协定不一样,Redis间接本人构建了VM 机制 ,应用了resp协定 聊聊resp协定吧Redis是Redis序列化协定,Redis客户端RESP协定与Redis服务器通信。Redis协定在以下几点之间做出了折衷: 简略的实现疾速地被计算机解析简略得能够能被人工解析其实就是一个二进制的序列化协定,举几个简略的例子哈在RESP中,某些数据的类型取决于第一个字节: “+”代表简略字符串Simple Strings “+”代表谬误类型 “:”代表整数 基于这种协定的话,其实咱们能够本人去实现一个redis的客户端,当前有机会给大家写写。 如果万一CPU成为你的Redis瓶颈了,或者,你就是不想让服务器其余核闲置,那怎么办?那也很简略,你多起几个Redis过程就好了。Redis是key-value数据库,又不是关系数据库,数据之间没有束缚。只有客户端分清哪些key放在哪个Redis过程上就能够了。redis-cluster能够帮你做的更好。 说说 Redis的根本数据结构String 整数,浮点数或者字符串Set 汇合Zset 有序汇合Hash 散列表List 列表那说说有序汇合的实现形式是哪种数据结构?跳跃表。 当数据较少时,sorted set是由一个ziplist来实现的。当数据多的时候,sorted set是由一个dict + 一个skiplist来实现的。简略来讲,dict用来查问数据到分数的对应关系,而skiplist用来依据分数查问数据(可能是范畴查找)。说说redis的底层数据结构sdsRedis的字符串,不是 C 语言中的字符串(即以空字符’\0’结尾的字符数组),它是本人构建了一种名为 简略动静字符串(simple dynamic string,SDS)的形象类型,并将 SDS 作为 Redis的默认字符串示意。 1、len 保留了SDS保留字符串的长度 2、buf[] 数组用来保留字符串的每个元素 3、free j记录了 buf 数组中未应用的字节数量 链表链表是一种罕用的数据结构,C 语言外部是没有内置这种数据结构的实现,所以Redis本人构建了链表的实现 字典字典又称为符号表或者关联数组、或映射(map),是一种用于保留键值对的形象数据结构。字典中的每一个键 key 都是惟一的,通过 key 能够对值来进行查找或批改。C 语言中没有内置这种数据结构的实现,所以字典仍然是 Redis本人构建的。 ...

February 19, 2021 · 2 min · jiezi

关于redis:Redis数据类型及使用场景

Redis数据类型及应用场景Redis 次要有以下几种数据类型:StringsHashesListsSetsSorted SetsRedis 除了这 5 种数据类型之外,还有 Bitmaps、HyperLogLogs、Streams 等。Strings这是最简略的类型,就是一般的 set 和 get,做简略的 KV 缓存。 set college szu复制代码Hashes这个是相似 map 的一种构造,这个个别就是能够将结构化的数据,比方一个对象(前提是这个对象没嵌套其余的对象)给缓存在 Redis 里,而后每次读写缓存的时候,能够就操作 hash 里的某个字段。 hset person name bingohset person age 20hset person id 1hget person name(person = { "name": "bingo", "age": 20, "id": 1})复制代码ListsLists 是有序列表,这个能够玩儿出很多花色。 比方能够通过 list 存储一些列表型的数据结构,相似粉丝列表、文章的评论列表之类的货色。 比方能够通过 lrange 命令,读取某个闭区间内的元素,能够基于 list 实现分页查问,这个是很棒的一个性能,基于 Redis 实现简略的高性能分页,能够做相似微博那种下拉一直分页的货色,性能高,就一页一页走。 # 0开始地位,-1完结地位,完结地位为-1时,示意列表的最初一个地位,即查看所有。lrange mylist 0 -1复制代码比方能够搞个简略的音讯队列,从 list 头怼进去,从 list 尾巴那里弄出来。 lpush mylist 1lpush mylist 2lpush mylist 3 4 5# 1rpop mylist复制代码SetsSets 是无序汇合,主动去重。 ...

February 19, 2021 · 1 min · jiezi

关于redis:Redis-Cluster-write-safety-分析

redis cluster 是 redis 的分布式实现。 如同官网文档 cluster-spec 强调的那样,其设计优先思考高性能和线性扩大能力,并尽最大致力保障 write safety。 这里所说的 write 失落是指,回复 client ack 后,后续申请中呈现数据未做变更或失落的状况,次要有主从切换、实例重启、脑裂等三种状况可能导致该问题,上面顺次剖析。 case 1 主从切换failover 会带来路由的变更,被动/被动状况须要离开探讨。 被动 failover为表白不便,有以下假如,cluster 状态失常, node C 为 master,负责 slot 1-100,对应 slave 为 C'。 master C 挂掉后,slave C' 在最多 2 倍 cluster_node_timeout 的工夫内把 C 标记成 FAIL,进而触发 failover 逻辑。 在 slave C' 胜利切换为 master 前,1-100 slot 依然由 C 负责,拜访会报错。 C' 切为 master 后,gossip 播送路由变更,在这个过程中,client 拜访 C',仍能够失去失常的回应,而拜访其余持有老路由的 node,申请会被 MOVED 到挂掉的 C,拜访报错。 惟一可能呈现 write 失落的 case 由主从异步复制机制导致。 如果写到 master 上的数据还没有来得及同步到 slave 就挂掉了,那么这部分数据就会失落(重启后不存在 merge 操作)。master 回复 client ack 与同步 slave 简直是同时进行的,这种状况很少产生,但这是一个危险,工夫窗口很小。 ...

February 19, 2021 · 4 min · jiezi

关于redis:Redis-多线程网络模型全面揭秘

博客原文Redis 多线程网络模型全面揭秘 导言在目前的技术选型中,Redis 俨然曾经成为了零碎高性能缓存计划的事实标准,因而当初 Redis 也成为了后端开发的基本技能树之一,Redis 的底层原理也牵强附会地成为了必须学习的常识。 Redis 从实质上来讲是一个网络服务器,而对于一个网络服务器来说,网络模型是它的精髓,搞懂了一个网络服务器的网络模型,你也就搞懂了它的实质。 本文通过层层递进的形式,介绍了 Redis 网络模型的版本变更历程,分析了其从单线程进化到多线程的工作原理,此外,还一并剖析并解答了 Redis 的网络模型的很多抉择背地的思考,帮忙读者能更粗浅地了解 Redis 网络模型的设计。 Redis 有多快?依据官网的 benchmark,通常来说,在一台一般硬件配置的 Linux 机器上跑单个 Redis 实例,解决简略命令(工夫复杂度 O(N) 或者 O(log(N))),QPS 能够达到 8w+,而如果应用 pipeline 批处理性能,则 QPS 至高能达到 100w。 仅从性能层面进行评判,Redis 齐全能够被称之为高性能缓存计划。 Redis 为什么快?Redis 的高性能得益于以下几个根底: C 语言实现,尽管 C 对 Redis 的性能有助力,但语言并不是最外围因素。纯内存 I/O,相较于其余基于磁盘的 DB,Redis 的纯内存操作有着人造的性能劣势。I/O 多路复用,基于 epoll/select/kqueue 等 I/O 多路复用技术,实现高吞吐的网络 I/O。单线程模型,单线程无奈利用多核,然而从另一个层面来说则防止了多线程频繁上下文切换,以及同步机制如锁带来的开销。Redis 为何抉择单线程?Redis 的外围网络模型抉择用单线程来实现,这在一开始就引起了很多人的不解,Redis 官网的对于此的答复是: It's not very frequent that CPU becomes your bottleneck with Redis, as usually Redis is either memory or network bound. For instance, using pipelining Redis running on an average Linux system can deliver even 1 million requests per second, so if your application mainly uses O(N) or O(log(N)) commands, it is hardly going to use too much CPU.外围意思就是,对于一个 DB 来说,CPU 通常不会是瓶颈,因为大多数申请不会是 CPU 密集型的,而是 I/O 密集型。具体到 Redis 的话,如果不思考 RDB/AOF 等长久化计划,Redis 是齐全的纯内存操作,执行速度是十分快的,因而这部分操作通常不会是性能瓶颈,Redis 真正的性能瓶颈在于网络 I/O,也就是客户端和服务端之间的网络传输提早,因而 Redis 抉择了单线程的 I/O 多路复用来实现它的外围网络模型。 ...

February 18, 2021 · 10 min · jiezi

关于redis:Redis第八章节应用场景

目录概述详解1、概述Redis反对五种数据类型:String(字符串)、Hash(哈希)、List(列表)、Set(汇合)、Zset(有序汇合)。 2、详解1、String(字符串)定义: String 是 redis 最根本的类型,一个 key 对应一个 value。String 类型是二进制平安的。因为 string 底层的实现是简略动静字符串 sds,是能够批改字符串。 利用场景: 单值缓存、对象缓存、分布式锁、惯例计数(粉丝数量、评论数量)、分布式session共享、分布式全局序列号。 具体实现: 单值缓存: set key value get key对象缓存: set user:1 value(json格局数据) mset user:1:name tsingli user:1:balance 1888 mget user:1:name user:1:balance惯例计数器: incr article:readcount:{文章id} get article:readcount:{文章id}分布式系统全局序列号: incrby orderid 1000 # redis批量生成序列号晋升性能分布式锁: # 相干操作 线程1: setnx product:1001 true # 返回1代表获取锁胜利 线程2: setnx product:1001 true # 返回0代表获取锁失败 。。。执行业务操作 del product:1001 # 执行完业务开释锁 set product:1001 true ex 10 nx # 避免程序意外终止导致死锁 # 案例 setnx product:1001 true 1.查问商品1001的库存 2.减库存 3.从新把减完残余的库存更新回数据库 del product:1001setnx 如果插入的key一样不会对数据有任何操作,如果第二次对库存再进行减对的话就返回谬误。 ...

February 13, 2021 · 2 min · jiezi

关于redis:Redis专题万字长文详解持久化原理

微信搜寻公众号“码路印记”本文将从以下几个方面介绍Redis长久化机制: ## 写在后面 本文从整体上具体介绍Redis的两种长久化形式,蕴含工作原理、长久化流程及实际策略,以及背地的一些理论知识。上一篇文章仅介绍了RDB长久化,然而Redis长久化是一个整体,独自介绍不成体系,故重新整理。Redis是一个内存数据库,所有的数据将保留在内存中,这与传统的MySQL、Oracle、SqlServer等关系型数据库间接把数据保留到硬盘相比,Redis的读写效率十分高。然而保留在内存中也有一个很大的缺点,一旦断电或者宕机,内存数据库中的内容将会全副失落。为了补救这一缺点,Redis提供了把内存数据长久化到硬盘文件,以及通过备份文件来复原数据的性能,即Redis长久化机制。 Redis反对两种形式的长久化:RDB快照和AOF。 RDB长久化RDB快照用官网的话来说:RDB长久化计划是依照指定工夫距离对你的数据集生成的工夫点快照(point-to-time snapshot)。它以压缩的二进制文件保留Redis数据库某一时刻所有数据对象的内存快照,可用于Redis的数据备份、转移与复原。到目前为止,仍是官网的默认反对计划。 RDB工作原理既然说RDB是Redis中数据集的工夫点快照,那咱们先简略理解一下Redis内的数据对象在内存中是如何存储与组织的。 默认状况下,Redis中有16个数据库,编号从0-15,每个Redis数据库应用一个redisDb对象来示意,redisDb应用hashtable存储K-V对象。为不便了解,我以其中一个db为例绘制Redis外部数据的存储构造示意图。工夫点快照也就是某一时刻Redis内每个DB中每个数据对象的状态,先假如在这一时刻所有的数据对象不再扭转,咱们就能够依照上图中的数据结构关系,把这些数据对象顺次读取进去并写入到文件中,以此实现Redis的长久化。而后,当Redis重启时依照规定读取这个文件中的内容,再写入到Redis内存即可复原至长久化时的状态。 当然,这个前提时咱们下面的假如成立,否则面对一个时刻变动的数据集,咱们无从下手。咱们晓得Redis中客户端命令解决是单线程模型,如果把长久化作为一个命令解决,那数据集必定时处于静止状态。另外,操作系统提供的fork()函数创立的子过程可取得与父过程统一的内存数据,相当于获取了内存数据正本;fork实现后,父过程该干嘛干嘛,长久化状态的工作交给子过程就行了。 很显然,第一种状况不可取,长久化备份会导致短时间内Redis服务不可用,这对于高HA的零碎来讲是无奈容忍的。所以,第二种形式是RDB长久化的次要实际形式。因为fork子过程后,父过程数据始终在变动,子过程并不与父进程同步,RDB长久化必然无奈保障实时性;RDB长久化实现后产生断电或宕机,会导致局部数据失落;备份频率决定了失落数据量的大小,进步备份频率,意味着fork过程耗费较多的CPU资源,也会导致较大的磁盘I/O。 长久化流程在Redis内实现RDB长久化的办法有rdbSave和rdbSaveBackground两个函数办法(源码文件rdb.c中),先简略说下两者差异: rdbSave:是同步执行的,办法调用后就会立即启动长久化流程。因为Redis是单线程模型,长久化过程中会阻塞,Redis无奈对外提供服务;rdbSaveBackground:是后盾(异步)执行的,该办法会fork出子过程,真正的长久化过程是在子过程中执行的(调用rdbSave),主过程会持续提供服务;RDB长久化的触发必然离不开以上两个办法,触发的形式分为手动和主动。手动触发容易了解,是指咱们通过Redis客户端人为的对Redis服务端发动长久化备份指令,而后Redis服务端开始执行长久化流程,这里的指令有save和bgsave。主动触发是Redis依据本身运行要求,在满足预设条件时主动触发的长久化流程,主动触发的场景有如下几个(摘自这篇文章): serverCron中save m n配置规定主动触发;从节点全量复制时,主节点发送rdb文件给从节点实现复制操作,主节点会登程bgsave;执行debug reload命令从新加载redis时;默认状况下(未开启AOF)执行shutdown命令时,主动执行bgsave;联合源码及参考文章,我整顿了RDB长久化流程来帮忙大家有个整体的理解,而后再从一些细节进行阐明。从上图能够晓得: 主动触发的RDB长久化是通过rdbSaveBackground以子过程形式执行的长久化策略;手动触发是以客户端命令形式触发的,蕴含save和bgsave两个命令,其中save命令是在Redis的命令解决线程以阻塞的形式调用rdbSave办法实现的。主动触发流程是一个残缺的链路,涵盖了rdbSaveBackground、rdbSave等,接下来我以serverCron为例剖析一下整个流程。 save规定及查看serverCron是Redis内的一个周期性函数,每隔100毫秒执行一次,它的其中一项工作就是:依据配置文件中save规定来判断以后须要进行主动长久化流程,如果满足条件则尝试开始长久化。理解一下这部分的实现。 在redisServer中有几个与RDB长久化无关的字段,我从代码中摘出来,中英文对照着看下: struct redisServer { /* 省略其余字段 */ /* RDB persistence */ long long dirty; /* Changes to DB from the last save * 上次长久化后批改key的次数 */ struct saveparam *saveparams; /* Save points array for RDB, * 对应配置文件多个save参数 */ int saveparamslen; /* Number of saving points, * save参数的数量 */ time_t lastsave; /* Unix time of last successful save * 上次长久化工夫*/ /* 省略其余字段 */}/* 对应redis.conf中的save参数 */struct saveparam { time_t seconds; /* 统计工夫范畴 */ int changes; /* 数据批改次数 */};saveparams对应redis.conf下的save规定,save参数是Redis触发主动备份的触发策略,seconds为统计工夫(单位:秒), changes为在统计工夫内产生写入的次数。save m n的意思是:m秒内有n条写入就触发一次快照,即备份一次。save参数能够配置多组,满足在不同条件的备份要求。如果须要敞开RDB的主动备份策略,能够应用save ""。以下为几种配置的阐明: ...

February 13, 2021 · 3 min · jiezi

关于redis:Redis专题持久化方式之RDB

公众号搜寻“码路印记”写在后面Redis是一个内存数据库,也就是说所有的数据将保留在内存中,这与传统的MySQL、Oracle、SqlServer等关系型数据库间接把数据保留到硬盘相比,Redis的读写效率十分高。然而保留在内存中也有一个很大的缺点,一旦断电或者宕机,内存数据库中的内容将会全副失落。为了补救这一缺点,Redis提供了把内存数据长久化到硬盘文件,以及通过备份文件来复原数据的性能。 Redis反对两种形式的长久化:RDB快照文件和AOF。本文先介绍RDB快照形式的工作原理、优缺点等方面进行论述,写完AOF形式后再比照两者的优缺点,联合前辈总结给出生产实践,心愿可能对你了解Redis的长久化机制带来帮忙。通过本文你将理解到以下内容:~~RDB快照用官网的话来说:RDB长久化计划是依照指定工夫距离对你的数据集生成的工夫点快照。它是Redis数据库中数据的内存快照,它是一个二进制文件(默认名称为:dump.rdb,可批改),存储了文件生成时Redis数据库中所有的数据内容。可用于Redis的数据备份、转移与复原。 配置参数RDB快照的触发形式及运行行为受配置参数的影响,关上配置文件redis.conf查看“SNAPSHOTTING”章节,理解RDB快照的参数及作用。对于各个参数的含意进行了翻译,英语好的同学能够间接看英文。 save <seconds> <changes>################################ SNAPSHOTTING ################################## Save the DB on disk:## save <seconds> <changes>## Will save the DB if both the given number of seconds and the given# number of write operations against the DB occurred.## In the example below the behavior will be to save:# after 900 sec (15 min) if at least 1 key changed# after 300 sec (5 min) if at least 10 keys changed# after 60 sec if at least 10000 keys changed## Note: you can disable saving completely by commenting out all "save" lines.## It is also possible to remove all the previously configured save# points by adding a save directive with a single empty string argument# like in the following example:## save ""save 900 1save 300 10save 60 10000save参数是Redis触发主动备份的触发策略,seconds为统计工夫(单位:秒), changes为在统计工夫内产生写入的次数。save m n的意思是:m秒内有n条写入就触发一次快照,即备份一次。save参数能够配置多组,满足在不同条件的备份要求。如果须要敞开RDB的主动备份策略,能够应用save ""。以下为几种配置的阐明: ...

February 13, 2021 · 4 min · jiezi

关于redis:Redis专题基础知识点

微信搜寻公众号“码路印记”,点关注不迷路!从本文开始我将开启Redis专题,逐渐整顿一些Redis的常识要点并分享进去,目前整顿了以下要点。明天先分享第一篇,次要是Redis的一些根本知识点,也是通过这篇文章来开掘须要欠缺Redis的常识体系。 Redis是什么?Redis是当初最受欢迎的NoSQL数据库之一,Redis是一个应用ANSI C编写的开源、蕴含多种数据结构、反对网络、基于内存、可选持久性的键值对存储数据库,其具备如下个性:基于内存运行,性能高效;反对分布式,实践上能够有限扩大;key-value存储系统;开源的应用ANSI C语言编写、恪守BSD协定、反对网络、可基于内存亦可长久化的日志型、Key-Value数据库,并提供多种语言的API。 相比于其余数据库类型,Redis具备的特点是:C/S通信模型、单过程单线程模型、丰盛的数据类型、操作具备原子性、长久化、高并发读写、反对lua脚本。 因为Redis杰出的性能体现,全世界各大厂都在拥抱与应用,如github、twitter、阿里巴巴、百度,并且一些大厂在开源版本的根底上持续深度开发与定制。当然,Redis应用如此宽泛,它也成为了咱们开发者的必备技能,日常工作与面试曾经无奈忽视它的存在。 Redis数据类型及操作指令Redis罕用的数据类型有String、Hash、List、Set、SortedSet,一般来讲纯熟应用这些数据类型及操作指令能够满足咱们绝大多数的工作场景。除此之外,Redis还反对一些高级的类型,比方HyperLogLog、Geo、Pub/Sub等。 本文对罕用的五种数据类型及指令进行简略总结,若有未列出的指令,大家能够到https://redis.io/commands#进行查问。 String它是一个二进制平安的字符串,意味着它不仅可能存储字符串、还能存储图片、视频等多种类型, 最大长度反对512M。以下列举了String类型罕用的指令及应用示例。 指令用处SET key value设置指定 key 的值GET key获取指定 key 的值。GETSET key value将给定 key 的值设为 value ,并返回 key 的旧值(old value)。MGET key1 [key2..]获取所有(一个或多个)给定 key 的值。SETEX key seconds value将值 value 关联到 key ,并将 key 的过期工夫设为 seconds (以秒为单位)。SETNX key value只有在 key 不存在时设置 key 的值。MSET key value [key value...]同时设置一个或多个 key-value 对。INCR key将 key 中贮存的数字值增一。INCRBY key increment将 key 所贮存的值加上给定的增量值(increment) 。DECR key将 key 中贮存的数字值减一。DECRBY key decrementkey 所贮存的值减去给定的减量值(decrement) 。DEL key [key1..]删除给定的key,返回被删除的数量String类型是简洁的key-value构造,也是咱们开发中最罕用的一种类型,应用形式相似于Java中的Map类型。而且,Redis提供了对数值类型的自增、自减指令,能够应用它来实现计数器、发号器等性能。 ...

February 13, 2021 · 2 min · jiezi

关于redis:Redis-Sentinel-源码Redis的高可用模型分析

摘要:本文通过对Redis Sentinel源码的了解,具体阐明Sentinel的代码实现形式。Redis Sentinel 是Redis提供的高可用模型解决方案。Sentinel能够主动监测一个或多个Redis主备实例,并在主实例宕机的状况下主动履行主备倒换。本文通过对Redis Sentinel源码的了解,具体阐明Sentinel的代码实现形式。 Sentinel应用Redis内核雷同的事件驱动代码框架, 但Sentinel有本人独特的初始化步骤。在这篇文章里,会从Sentinel的初始化、Sentinel主工夫事件函数、Sentinel 网络连接和Tilt模式三局部进行解说。 Sentinel初始化咱们能够通过redis-sentinel <path-to-configfile> 或者 redis-server <path-to-configfile> --sentinel 这两种形式启动并运行Sentinel实例,这两种形式是等价的。在Redis server.c 的main函数中,咱们会看到Redis如何判断用户指定以Sentinel形式运行的逻辑: 其中checkForSentinelMode函数会监测以下两种条件: 程序应用redis-sentinel可执行文件执行。程序参数列表中有--sentinel 标记。以上任何一种条件成立则Redis会应用Sentinel的形式运行。 在Redis 判断是否以Sentinel的形式运行当前,咱们会看到如下代码段: 在initSentinelConfig函数中,会应用Sentinel特定的端口(默认为26379)来代替Redis的默认端口(6379)。另外,在Sentinel模式下,须要禁用服务器运行保护模式。 与此同时,initSentinel函数会做如下操作: 1.应用Sentinel自带的命令表去代替Redis服务器原生的命令. Sentinel 反对的命令表如下: 2.初始化Sentinel主状态构造,Sentinel主状态的定义及正文如下。 其中masters字典指针中的每个值都对应着一个Sentinel检测的主实例。 在读取配置信息后,Redis服务器主函数会调用sentinelIsRunning函数, 做以下几个工作: 查看配置文件是否被设置,并且检查程序对配置文件是否有写权限,因为如果Sentinel状态扭转的话,会一直将本人以后状态记录在配置文件中。如果在配置文件中指定运行ID,Sentinel 会应用这个ID作为运行ID,相同地,如果没有指定运行ID,Sentinel会生成一个ID用来作为Sentinel的运行ID。对所有的Sentinel监测实例产生初始监测事件。 Sentinel的主工夫事件函数Sentinel 应用和Redis服务器雷同的事件处理机制:分为文件事件和工夫事件。文件事件解决机制应用I/O 多路复用来解决服务器端的网络I/O 申请,例如客户端连贯,读写等操作。工夫解决机制则在主循环中周期性调用工夫函数来解决定时操作,例如服务器端的保护,定时更新,删除等操作。Redis服务器主工夫函数是在server.c中定义的serverCron函数,在默认状况下,serverCron会每100ms被调用一次。在这个函数中,咱们看到如下代码: 其中当服务器以sentinel模式运行的时候,serverCron会调用sentinelTimer函数,来运行Sentinel中的主逻辑,sentinelTimer函数在sentinel.c中的定义如下: Sentinel Timer函数会做如下几个操作: 查看Sentinel以后是否在Tilt 模式(Tilt模式将会在稍后章节介绍)。查看Sentinel与其监控主备实例,以及其余Sentinel实例的连贯,更新以后状态,并在主实例下线的时候主动做主备倒换操作。查看回调脚本状态,并做相应操作。更新服务器频率(调用serverCron函数的频率),加上一个随机因子,作用是避免监控雷同主节点的Sentinel在选举Leader的时候工夫抵触,导致选举无奈产生相对多的票数。其中SentinelHandleDictOfRedisInstances函数的定义如下:  SentinelHandleDictOfRedisInstances函数次要做的工作是: 1.调用sentinelHandleDictOfRedisInstance函数解决Sentinel与其它特定实例连贯,状态更 新,以及主备倒换工作。 如果以后解决实例为主实例,递归调用SentinelHandleDictOfRedisInstances函数解决其上司的从实例以及其余监控这个主实例的Sentinel。在主备倒换胜利的状况下,更新主实例为降级为主实例的从实例。其中在sentinelHandleRedisInstance的定义如下: 这个函数会做以下两局部操作: 1.查看Sentinel和其余实例(主备实例以及其余Sentinel)的连贯,如果连贯没有设置或曾经断开连接,Sentinel会重试绝对应的连贯,并定时发送响应命令。 须要留神的是:Sentinel和每个主备实例都有两个连贯,命令连贯和公布订阅连贯。然而与其余监听雷同主备实例的Sentinel只保留命令连贯,这部分细节会在网络章节独自介绍。 2.第二局部操作次要做的是监测主备及其他Sentinel实例,并监测其是否在主观下线状态,对于主实例来说,还要检测是否在主观下线状态,并进行相应的主备倒换操作。 须要留神的是第二局部操作如果Sentinel在Tilt模式下是疏忽的,上面咱们来看一下这个函数第二局部的的具体实现细节。 sentinelCheckSubjectivelyDown 函数会监测特定的Redis实例(主备实例以及其余Sentinel)是否处于主观下线状态,这部分函数代码如下: 主观下线状态意味着特定的Redis实例满足以下条件之一: 在实例配置的down_after_milliseconds工夫内没有收到Ping的回复。Sentinel认为实例是主实例,但收到实例为从实例的回复,并且上次实例角色回复工夫大于在实例配置的down_after_millisecon工夫加上2倍INFO命令距离。如果任何一个条件满足,Sentinel会关上实例的S_DOWN标记并认为实例进入主观下线状态。 主观下线状态意味着Sentinel主观认为实例下线,但此时Sentinel并没有询问其余监控此实例的其余Sentinel此实例的在线状态。 ...

February 8, 2021 · 1 min · jiezi

关于redis:闲扯Redis十一Redis-有序集合对象底层实现

一、前言Redis 提供了5种数据类型:String(字符串)、Hash(哈希)、List(列表)、Set(汇合)、Zset(有序汇合),了解每种数据类型的特点对于redis的开发和运维十分重要。原文解析 备注: 本节中波及到的跳跃表实现,曾经在上节《闲扯Redis十》Redis 跳跃表的构造实现一文中详情剖析过,本文中将间接援用,不再赘述。 二、命令实现 因为有序汇合键的值为有序汇合对象,所以用于有序汇合键的所有命令都是针对有序汇合对象来构建的。 命令ziplist 编码的实现办法zset 编码的实现办法ZADD调用 ziplistInsert 函数, 将成员和分值作为两个节点别离插入到压缩列表。先调用 zslInsert 函数, 将新元素增加到跳跃表, 而后调用 dictAdd 函数, 将新元素关联到字典。ZCARD调用 ziplistLen 函数, 取得压缩列表蕴含节点的数量, 将这个数量除以 2 得出汇合元素的数量。拜访跳跃表数据结构的 length 属性, 间接返回汇合元素的数量。ZCOUNT遍历压缩列表, 统计分值在给定范畴内的节点的数量。遍历跳跃表, 统计分值在给定范畴内的节点的数量。ZRANGE从表头向表尾遍历压缩列表, 返回给定索引范畴内的所有元素。从表头向表尾遍历跳跃表, 返回给定索引范畴内的所有元素。ZREVRANGE从表尾向表头遍历压缩列表, 返回给定索引范畴内的所有元素。从表尾向表头遍历跳跃表, 返回给定索引范畴内的所有元素。ZRANK从表头向表尾遍历压缩列表, 查找给定的成员, 沿途记录通过节点的数量, 当找到给定成员之后, 途经节点的数量就是该成员所对应元素的排名。从表头向表尾遍历跳跃表, 查找给定的成员, 沿途记录通过节点的数量, 当找到给定成员之后, 途经节点的数量就是该成员所对应元素的排名。ZREVRANK从表尾向表头遍历压缩列表, 查找给定的成员, 沿途记录通过节点的数量, 当找到给定成员之后, 途经节点的数量就是该成员所对应元素的排名。从表尾向表头遍历跳跃表, 查找给定的成员, 沿途记录通过节点的数量, 当找到给定成员之后, 途经节点的数量就是该成员所对应元素的排名。ZREM遍历压缩列表, 删除所有蕴含给定成员的节点, 以及被删除成员节点旁边的分值节点。遍历跳跃表, 删除所有蕴含了给定成员的跳跃表节点。 并在字典中解除被删除元素的成员和分值的关联。ZSCORE遍历压缩列表, 查找蕴含了给定成员的节点, 而后取出成员节点旁边的分值节点保留的元素分值。间接从字典中取出给定成员的分值。三、构造解析 由前文和上图可知,有序汇合的编码能够是 ziplist 或者 skiplist 。ziplist 编码的有序汇合对象应用压缩列表作为底层实现, 每个汇合元素应用两个紧挨在一起的压缩列表节点来保留, 第一个节点保留元素的成员(member), 而第二个元素则保留元素的分值(score)。 压缩列表形式压缩列表内的汇合元素按分值从小到大进行排序, 分值较小的元素被搁置在凑近表头的方向, 而分值较大的元素则被搁置在凑近表尾的方向。 ...

February 7, 2021 · 2 min · jiezi

关于redis:Redis第七章节持久化

目录概述RDBAOF如何抉择长久化机制1、概述Redis 是内存数据库,如果不能将内存中的数据保留到磁盘中,那么一旦服务器过程退出,服务器的数据库数据也会隐没,所以Redis提供了长久化的性能,redis分为两种长久化形式:RDB和AOF。有以下几个特点: 1.RDB长久化形式可能在指定的工夫距离能对你的数据进行快照存储。2.AOF长久化形式记录每次对服务器写的操作,当服务器重启的时候会从新执行这些命令来复原原始的数据,AOF命令以redis协定追加保留每次写的操作到文件开端。Redis还能对AOF文件后盾重写,使得AOF文件的体积不至于过大。3.如果你只心愿你的数据在服务器运行的时候存在,你也能够不应用任何长久化的形式。4.你也能够同时开启两种长久化形式,在这种状况下,当redis重启的时候会优先载入AOF文件来复原原始的数据。因为在通常状况下AOF文件保留的数据集要比RDB文件保留的数据集要残缺。2、RDB1、概念在指定的工夫距离内将内存中的数据集快照写入磁盘中,它复原的时候是将快照中的文件间接读取到内存中。 2、长久化机制-BGSAVE 通常,会立刻返回ok,Redis过程会执行fork操作创立子过程,Redis在fork时,父过程会持续为客户端提供服务,子过程会将数据长久化到硬盘上,而后退出。如果曾经在后盾执行保留或者正在运行另一个非后盾保留的过程,特地是正在进行AOF写入时,则会返回谬误。如果应用了bgsave工作,而正在进行AOF写入时,该命令将立刻返回ok,并打算在下一次机会运行后盾保留。阻塞只会在fork阶段。 客户端能够应用lastsave命令查看操作是否胜利。3、长久化机制-SAVE 不会承受客户端执行的操作命令,等长久化工作实现之后,会将新的文件替换旧的文件。4、长久化机制-主动触发 在redis.conf中能够配置,让用户自定义save属性,让服务器每一段时间内执行一次bgsave操作。 # 服务器在900秒内,对数据库进行了至多1次批改 save 900 1 # 服务器在300秒内,对数据库进行了至多10次批改 save 300 10 # 服务器在60秒内,对数据库进行了至多10000次批改 save 60 10000 # bgsave产生谬误时是否进行写入,个别为yes stop-writes-on-bgsave-error yes # 长久化时是否应用LZF压缩字符串对象? rdbcompression yes # 是否对rdb文件进行校验和测验,通常为yes rdbchecksum yes # RDB长久化文件名 dbfilename dump.rdb # 长久化文件存储目录 dir ./5、复原数据机制只须要将rdb文件放在咱们redis启动目录就能够了,redis启动的时候会主动查看文件并复原其中的数据。 6、长处RDB是一个十分紧凑的文件,它保留了某个工夫点得数据集,十分实用于数据集的备份,比方你能够在每个小时报保留一下过来24小时内的数据,同时每天保留过来30天的数据,这样即便出了问题你也能够依据需要复原到不同版本的数据集。RDB是一个紧凑的繁多文件,很不便传送到另一个远端数据中心或者亚马逊的S3(可能加密),十分实用于劫难复原。RDB在保留RDB文件时父过程惟一须要做的就是fork出一个子过程,接下来的工作全副由子过程来做,父过程不须要再做其余IO操作,所以RDB长久化形式能够最大化redis的性能。与AOF相比,在复原大的数据集的时候,RDB形式会更快一些。7、毛病如果你心愿在redis意外进行工作(例如电源中断)的状况下失落的数据起码的话,那么RDB不适宜你。尽管你能够配置不同的save工夫点(例如每隔5分钟并且对数据集有100个写的操作),是Redis要残缺的保留整个数据集是一个比拟沉重的工作,你通常会每隔5分钟或者更久做一次残缺的保留,万一在Redis意外宕机,你可能会失落几分钟的数据。RDB 须要常常fork子过程来保留数据集到硬盘上,当数据集比拟大的时候,fork的过程是十分耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的申请。如果数据集微小并且CPU性能不是很好的状况下,这种状况会继续1秒,AOF也须要fork,然而你能够调节重写日志文件的频率来进步数据集的耐久度。3、AOF1、概念以日志的模式来记录每个写操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不能够改写文件,Redis启动之初会读取该文件从新构建数据,换言之,Redis重启的话就会依据日志文件的内容将写的指令从前到后执行一次以实现数据的复原工作。 2、长久化原理所有操作的命令会追加在文件中。 3、开启AOF长久化 # 开启aof长久化形式,默认no appendonly no # aof 长久化生成的文件名称 appendfilename "appendonly.aof" # 三种长久化机制 # appendfsync always appendfsync everysec # appendfsync no4、三种触发长久化机制always同步长久化,每次产生数据变更会被立刻长久化到硬盘中,性能比拟差,然而数据完整性好。 everysec异步操作,每秒长久化数据到硬盘一次,可能会失落一秒的数据。 no从不长久化到硬盘。 ...

February 6, 2021 · 1 min · jiezi

关于redis:redis分布式锁的这些坑我怀疑你是假的开发

摘要:用锁遇到过哪些问题?一、文言分布式什么是分布式,用最简略的话来说,就是为了较低单个服务器的压力,将性能散布在不同的机器下面; 就比方: 原本一个程序员能够实现一个我的项目:需要->设计->编码->测试 然而我的项目多的时候,一个人也扛不住,这就须要不同的人进行分工合作了 这就是一个简略的分布式协同工作了; 二、分布式锁首先看一个问题,如果说某个环节被终止或者别强占,就会产生不可知的事件 这就会呈现,设计好的或者设计的半成品会被毁坏,导致前面环节出错; 这时候,咱们就须要引入分布式锁的概念; 何为分布式锁? 当在分布式模型下,数据只有一份(或有限度),此时须要利用锁的技术管制某一时刻批改数据的过程数。用一个状态值示意锁,对锁的占用和开释通过状态值来标识。分布式锁的条件: 能够保障在分布式部署的利用集群中,同一个办法在同一时间只能被一台机器上的一个线程执行。这把锁要是一把可重入锁(防止死锁)这把锁最好是一把阻塞锁这把锁最好是一把偏心锁有高可用的获取锁和开释锁性能获取锁和开释锁的性能要好分布式锁的实现: 分布式锁的实现由很多种,文件锁、数据库、redis等等,比拟多,在实践中,还是redis做分布式锁性能会高一些; 三、redis实现分布式锁首先看两个命令: setnx:将 key 的值设为 value,当且仅当 key 不存在。 若给定的 key 曾经存在,则 SETNX 不做任何动作。 SETNX 是SET if Not eXists的简写。 expire: EXPIRE key seconds 为给定 key 设置生存工夫,当 key 过期时(生存工夫为 0 ),它会被主动删除 基于分布式锁的流程: 这就是一个简略的分布式锁的实现流程,具体代码实现也很简略,就不赘述了; 四、redis实现分布式锁问题如果呈现了这么一个问题:如果setnx是胜利的,然而expire设置失败,那么前面如果呈现了开释锁失败的问题,那么这个锁永远也不会被失去,业务将被锁死? 解决的方法:应用set的命令,同时设置锁和过期工夫 set参数: 实际: 这样就完满的解决了分布式锁的原子性; 用锁遇到过哪些问题?又是如何解决的?未敞开资源因为以后线程 获取到redis 锁,解决完业务后未及时开释锁,导致其它线程会始终尝试获取锁阻塞,例如:用Jedis客户端会报如下的错误信息 1redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the poolredis线程池曾经没有闲暇线程来解决客户端命令。应用原生办法记得敞开! 解决的办法也很简略,只有咱们仔细一点,拿到锁的线程解决完业务及时开释锁 ...

February 5, 2021 · 1 min · jiezi

关于redis:Redis-源码之-cluster-初始化

Redis Cluster 是官网提出的 redis 分布式集群解决方案,在此之前,也有一些第三方的可选计划,如 codis、Twemproxy 等。cluster 外部应用了 gossip 协定进行通信,以达到数据的最终一致性。具体介绍可参考官网 Redis cluster tutorial。 当 redis server 以 cluster mode 启动时,即配置文件中的 cluster-enabled 选项设置为 true,会有一个 cluster 相干数据结构初始化的流程,在之前的文章 Redis 启动流程中提到过,即执行函数 clusterInit。 初始化 cluster 信息有 3 个数据结构很重要, clusterState 、 clusterNode 和 clusterLink。每个节点都有一个 clusterState,记录了在"我"的视角下,集群目前所处的状态。每个节点都会应用一个 clusterNode 来记录本人的状态, 并为集群中的所有其余节点都创立一个相应的 clusterNode 构造, 以此来记录其余节点的状态。clusterNode 构造的 link 是一个 clusterLink 构造体, 保留了连贯节点的相干信息, 比方套接字描述符,输出缓冲区和输入缓冲区。 更多细节也能够通过 redis 设计与实现 - 节点 进行理解。 首先创立一个 clusterState 构造,并初始化一些成员变量,大略如下: server.cluster = zmalloc(sizeof(clusterState));server.cluster->myself = NULL;server.cluster->currentEpoch = 0; // 新节点的 currentEpoch = 0server.cluster->state = CLUSTER_FAIL; // 初始状态置为 FAILserver.cluster->size = 1;server.cluster->todo_before_sleep = 0;server.cluster->nodes = dictCreate(&clusterNodesDictType,NULL);server.cluster->nodes_black_list = dictCreate(&clusterNodesBlackListDictType,NULL);server.cluster->failover_auth_time = 0;server.cluster->failover_auth_count = 0;server.cluster->failover_auth_rank = 0;server.cluster->failover_auth_epoch = 0;server.cluster->cant_failover_reason = CLUSTER_CANT_FAILOVER_NONE;server.cluster->lastVoteEpoch = 0;server.cluster->stats_bus_messages_sent = 0;server.cluster->stats_bus_messages_received = 0;memset(server.cluster->slots,0, sizeof(server.cluster->slots));clusterCloseAllSlots(); // Clear the migrating/importing state for all the slotscluster 相干构造体关系图大抵如下, ...

February 4, 2021 · 2 min · jiezi

关于redis:面试官请讲一下Redis主从复制的功能及实现原理

摘要:Redis在主从模式下会有许多问题须要思考,这里写了一些对于redis在多服务器下的一些问题剖析和总结。Redis单节点存在单点故障问题,为了解决单点问题,个别都须要对redis配置从节点,而后应用哨兵来监听主节点的存活状态,如果主节点挂掉,从节点能持续提供缓存性能。主从配置联合哨兵模式能解决单点故障问题,进步redis可用性。从节点仅提供读操作,主节点提供写操作。对于读多写少的情况,可给主节点配置多个从节点,从而进步响应效率。 主从复制过程: 从节点执行slaveofmasterIP,保留主节点信息从节点中的定时工作发现主节点信息,建设和主节点的socket连贯从节点发送Ping信号,主节点返回Pong,两边能相互通信连贯建设后,主节点将所有数据发送给从节点(数据同步)主节点把以后的数据同步给从节点后,便实现了复制的建设过程。接下来,主节点就会继续的把写命令发送给从节点,保障主从数据一致性。Redis的数据同步过程: redis2.8之前应用syncrunId同步命令,redis2.8之后应用psyncrunId命令。 两者不同在于,sync命令仅反对全量复制过程,psync反对全量和局部复制。 介绍同步之前,先介绍几个概念: runId:每个redis节点启动都会生成惟一的uuid,每次redis重启后,runId都会发生变化。 offset:主节点和从节点都各自保护本人的主从复制偏移量offset,当主节点有写入命令时,offset=offset+命令的字节长度。从节点在收到主节点发送的命令后,也会减少本人的offset,并把本人的offset发送给主节点。这样,主节点同时保留本人的offset和从节点的offset,通过比照offset来判断主从节点数据是否统一。 repl_backlog_size:保留在主节点上的一个固定长度的先进先出队列,默认大小是1MB。 主节点发送数据给从节点过程中,主节点还会进行一些写操作,这时候的数据存储在复制缓冲区中。从节点同步主节点数据实现后,主节点将缓冲区的数据持续发送给从节点,用于局部复制。 主节点响应写命令时,岂但会把命名发送给从节点,还会写入复制积压缓冲区,用于复制命令失落的数据补救。 下面是psync的执行流程: 从节点发送psyncrunId命令,主节点有三种响应: FULLRESYNC:第一次连贯,进行全量复制 CONTINUE:进行局部复制 ERR:不反对psync命令,进行全量复制 全量复制和局部复制的过程 下面是全量复制的流程。次要有以下几步: 从节点发送psync ? -1命令(因为第一次发送,不晓得主节点的runId,所以为?,因为是第一次复制,所以offset=-1)。 主节点发现从节点是第一次复制,返回FULLRESYNC {runId} {offset},runId是主节点的runId,offset是主节点目前的offset。 从节点接管主节点信息后,保留到info中。 主节点在发送FULLRESYNC后,启动bgsave命令,生成RDB文件(数据长久化)。 主节点发送RDB文件给从节点。到从节点加载数据实现这段期间主节点的写命令放入缓冲区。 从节点清理本人的数据库数据。 从节点加载RDB文件,将数据保留到本人的数据库中。 -如果从节点开启了AOF,从节点会异步重写AOF文件。 对于局部复制有以下几点阐明: 1、局部复制次要是Redis针对全量复制的过高开销做出的一种优化措施,应用psyncrunId命令实现。当从节点正在复制主节点时,如果呈现网络闪断或者命令失落等异常情况时,从节点会向主节点要求补发失落的命令数据,主节点的复制积压缓冲区将这部分数据间接发送给从节点,这样就能够放弃主从节点复制的一致性。补发的这部分数据个别远远小于全量数据。 2、主从连贯中断期间主节点仍然响应命令,但因复制连贯中断命令无奈发送给从节点,不过主节点内的复制积压缓冲区仍然能够保留最近一段时间的写命令数据。 3、当主从连贯复原后,因为从节点之前保留了本身已复制的偏移量和主节点的运行ID。因而会把它们当做psync参数发送给主节点,要求进行局部复制。 4、主节点接管到psync命令后首先核查参数runId是否与本身统一,如果统一,阐明之前复制的是以后主节点;之后依据参数offset在复制积压缓冲区中查找,如果offset之后的数据存在,则对从节点发送+COUTINUE命令,示意能够进行局部复制。因为缓冲区大小固定,若产生缓冲溢出,则进行全量复制。 5、主节点依据偏移量把复制积压缓冲区里的数据发送给从节点,保障主从复制进入失常状态。 Redis主从复制会存在以下问题: 一旦主节点宕机,从节点降职为主节点,同时须要批改利用方的主节点地址,还须要命令所有从节点去复制新的主节点,整个过程须要人工干预。主节点的写能力受到单机的限度。主节点的存储能力受到单机的限度。原生复制的弊病在晚期的版本中也会比较突出,比方:redis复制中断后,从节点会发动psync。此时如果同步不胜利,则会进行全量同步,主库执行全量备份的同时,可能会造成毫秒或秒级的卡顿。所以用哨兵解决以上问题。 哨兵的性能 Redis Sentinel(哨兵)次要性能包含主节点存活检测、主从运行状况检测、主动故障转移、主从切换。Redis Sentinel最小配置是一主一从。 Redis的Sentinel零碎能够用来治理多个Redis服务器,该零碎能够执行以下四个工作: 监控:一直查看主服务器和从服务器是否失常运行。告诉:当被监控的某个redis服务器呈现问题,Sentinel通过API脚本向管理员或者其余应用程序发出通知。主动故障转移:当主节点不能失常工作时,Sentinel会开始一次主动的故障转移操作,它会将与生效主节点是主从关系的其中一个从节点降级为新的主节点,并且将其余的从节点指向新的主节点,这样人工干预就能够免了。配置提供者:在Redis Sentinel模式下,客户端利用在初始化时连贯的是Sentinel节点汇合,从中获取主节点的信息。 哨兵的原理 1、每个Sentinel节点都须要定期执行以下工作:每个Sentinel以每秒一次的频率,向它所知的主服务器、从服务器以及其余的Sentinel实例发送一个PING命令。(如上图) 2、如果一个实例间隔最初一次无效回复PING命令的工夫超过down-after-milliseconds所指定的值,那么这个实例会被Sentinel标记为主观下线。(如上图) 3、如果一个主服务器被标记为主观下线,那么正在监督这个服务器的所有Sentinel节点,要以每秒一次的频率确认主服务器确实进入了主观下线状态。 4、如果一个主服务器被标记为主观下线,并且有足够数量的Sentinel(至多要达到配置文件指定的数量)在指定的工夫范畴内批准这一判断,那么这个主服务器被标记为主观下线。 5、个别状况下,每个Sentinel会以每10秒一次的频率向它已知的所有主服务器和从服务器发送INFO命令,当一个主服务器被标记为主观下线时,Sentinel向下线主服务器的所有从服务器发送INFO命令的频率,会从10秒一次改为每秒一次。 6、Sentinel和其余Sentinel协商主观下线的主节点的状态,如果处于SDOWN状态,则投票主动选出新的主节点,将残余从节点指向新的主节点进行数据复制。 7、当没有足够数量的Sentinel批准主服务器下线时,主服务器的主观下线状态就会被移除。当主服务器从新向Sentinel的PING命令返回无效回复时,主服务器的主观下线状态就会被移除。 点击关注,第一工夫理解华为云陈腐技术~

February 4, 2021 · 1 min · jiezi

关于redis:Redis-实战-14-Redis-的-Lua-脚本编程

简介Redis 从 2.6 版本开始引入应用 Lua 编程语言进行的服务器端脚本编程性能,这个性能能够让用户间接在 Redis 外部执行各种操作,从而达到简化代码并进步性能的作用。 P248 在不编写 C 代码的状况下增加新性能 P248通过应用 Lua 对 Redis 进行脚本编程,咱们能够防止一些减慢开发速度或者导致性能降落对常见陷阱。 P248 将 Lua 脚本载入 Redis P249SCRIPT LOAD 命令能够将脚本载入 Redis ,这个命令承受一个字符串格局的 Lua 脚本为参数,它会把脚本存储起来期待之后应用,而后返回被存储脚本的 SHA1 校验和EVALSHA 命令能够调用之前存储的脚本,这个命令接管脚本的 SHA1 校验和以及脚本所需的全副参数EVAL 命令能够间接执行指定的脚本,这个命令接管脚本字符串以及脚本所需的全副参数。这个命令除了会执行脚本之外,还会将被执行的脚本缓存到 Redis 服务器外面因为 Lua 的数据传入和传出限度, Lua 与 Redis 须要进行互相转换。因为脚本在返回各种不同类型的数据时可能会产生含糊不清的后果,所以咱们应该尽量显式的返回字符串。 P250 咱们能够在 官网文档 中找到 Redis 和 Lua 不同类型之间的转换表: Redis 类型转换至 Lua 类型 RedisLuainteger replynumberbulk replystringmulti bulk replytable (may have other Redis data types nested)status replytable with a single ok field containing the statuserror replytable with a single err field containing the errorNil bulk replyfalse boolean typeNil multi bulk replyfalse boolean typeLua 类型转换至 Redis 类型 ...

February 3, 2021 · 2 min · jiezi

关于redis:AOP与Redis缓存实现

1. AOP实现缓存业务1.1 业务需要1). 自定义注解 @CacheFind(key=“xxx”,second=-1)2). 应用自定义注解 标识业务办法 将办法的返回值保留到缓存中.3). 利用AOP 拦挡注解 利用盘绕告诉办法实现业务 1.2 自定义注解@CacheFind 1.3 注解标识 1.4 编辑AOPpackage com.jt.aop;import com.jt.anno.CacheFind;import com.jt.util.ObjectMapperUtil;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.stereotype.Controller;import org.springframework.stereotype.Repository;import org.springframework.stereotype.Service;import redis.clients.jedis.Jedis;import java.lang.reflect.Method;import java.util.Arrays;/*@Service@Controller@Repository*/@Component //组件 将类交给spring容器治理@Aspect //示意我是一个切面public class RedisAOP { @Autowired private Jedis jedis; /* * 实现AOP业务调用 * 1.拦挡指定的注解 * 2.利用盘绕告诉实现 * 实现步骤: * 1.获取KEY 必须先获取注解 从注解中获取key? * 2.校验redis中是否有值 * * * 3.知识点补充: * 指定参数名称进行传值,运行期绑定参数类型实现注解的拦挡 * joinPoint必须位于参数的第一位. */ @Around("@annotation(cacheFind)") public Object around(ProceedingJoinPoint joinPoint,CacheFind cacheFind){ Object result = null; //key=业务名称::参数 String key = cacheFind.key(); String args = Arrays.toString(joinPoint.getArgs()); key = key + "::" + args; //2.校验是否有值 if(jedis.exists(key)){ String json = jedis.get(key); MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); Class returnType = methodSignature.getReturnType(); result = ObjectMapperUtil.toObj(json,returnType); System.out.println("AOP查问redis缓存"); }else{ //redis中没有数据,所以须要查询数据库,将数据保留到缓存中 try { result = joinPoint.proceed(); String json = ObjectMapperUtil.toJSON(result); //是否设定超时工夫 if(cacheFind.seconds()>0){ jedis.setex(key, cacheFind.seconds(), json); }else{ jedis.set(key,json); } System.out.println("AOP查询数据库"); } catch (Throwable throwable) { throwable.printStackTrace(); } } return result; } /** * //1.获取key 注解 办法对象 类 办法名称 参数 * Class targetClass = joinPoint.getTarget().getClass(); * //2.获取办法对象 * String methodName = joinPoint.getSignature().getName(); * Object[] args = joinPoint.getArgs(); * Class[] classArgs = new Class[args.length]; * for(int i=0;i<args.length;i++){ * classArgs[i] = args[i].getClass(); * } * try { * //反射实例化对象 * Method method = targetClass.getMethod(methodName,classArgs); * CacheFind cacheFind = method.getAnnotation(CacheFind.class); * String key = cacheFind.key(); * System.out.println(key); * } catch (NoSuchMethodException e) { * e.printStackTrace(); * } */ //公式 aop = 切入点表达式 + 告诉办法 //@Pointcut("bean(itemCatServiceImpl)") //@Pointcut("within(com.jt.service.*)") //@Pointcut("execution(* com.jt.service.*.*(..))") //.* 以后包的一级子目录 /* @Pointcut("execution(* com.jt.service..*.*(..))") //..* 以后包的所有的子目录 public void pointCut(){ }*/ //如何获取指标对象的相干参数? //ProceedingJoinPoint is only supported for around advice /* @Before("pointCut()") public void before(JoinPoint joinPoint){ //连接点 Object target = joinPoint.getTarget(); Object[] args = joinPoint.getArgs(); String className = joinPoint.getSignature().getDeclaringTypeName(); String methodName = joinPoint.getSignature().getName(); System.out.println("指标对象:"+target); System.out.println("办法参数:"+Arrays.toString(args)); System.out.println("类名称:"+className); System.out.println("办法名称:"+methodName); }*/}2. 对于Redis惯例属性2.1 Redis中长久化策略-RDB2.1.1 需要阐明阐明: Redis中将数据都保留到了内存中,然而内存的特点断电及擦除. 为了保障redis中的缓存数据不失落,则须要将内存数据定期进行长久化操作.长久化: 将内存数据,写到磁盘中. ...

February 3, 2021 · 3 min · jiezi

关于redis:抽奖活动难点亮点

业务需要通过流动模式,吸引用户为京东金融拉取信用花,为车主服务带来用户量,进步绑车量,将京东金融用户转化为车主用户。通过抽奖流动,用一些处分和刺激的伎俩来促使用户应用咱们的app,进步用户黏性。抽奖阐明: 用户抽奖须要耗费钥匙(抽奖机会),有两种形式获取钥匙,一种是每天第一次登录可获取两把钥匙,一种是实现工作可获取一把钥匙。用户在领有钥匙的状况下,点击解锁图片按钮,主动应用一把钥匙解锁碎片,需四张碎片解锁一张整图,解锁整图时才真正触发抽奖。抽奖会为用户抽取优惠券,现金红包等。亮点: 发奖与抽奖异步分布式锁3.生产端 多线程生产 本次生产汇合全副解决实现后再提交(CountDownLatch),敞开mq主动生产。可能呈现反复生产,通过保障幂等性或去重表解决。 放弃重试失败重试会影响零碎性能,重试次数越多,对系统性能的影响越大。抽奖过程中,从抽奖信息验证到扣库存、中奖信息入库的整个过程中,任何一个环节异样或失败,咱们都不会进行重试,全副当做未中奖解决,这是由抽奖的业务场景决定的,即:抽奖自身是随机的,不须要保障100%中奖。如果业务上要求100%中奖,能够在流程最初增加一个“弥补奖品环节”,即:返回失败信息之前,在给用户发一个奖品,不批改后面的整个流程。

February 3, 2021 · 1 min · jiezi

关于redis:Redis学习笔记缓存污染

一张思维导图鸟瞰全文 什么是缓存净化问题?缓存净化问题说的是缓存中一些只会被拜访一次或者几次的的数据,被拜访完后,再也不会被拜访到,但这部分数据仍然留存在缓存中,耗费缓存空间。 缓存净化会随着数据的继续减少而逐步露出,随着服务的一直运行,缓存中会存在大量的永远不会再次被拜访的数据。缓存空间是无限的,如果缓存空间满了,再往缓存里写数据时就会有额定开销,影响Redis性能。这部分额定开销次要是指写的时候判断淘汰策略,依据淘汰策略去抉择要淘汰的数据,而后进行删除操作。 如何解决缓存净化问题解决缓存净化问题,实际上就是要把不会再被拜访的数据筛选进去并删除掉,为后续写入的数据腾空间。缓存淘汰策略就是找出那些能够删除的缓存数据的规定。上面将介绍Redis反对的几种缓存淘汰策略。 缓存淘汰策略Redis共反对八种淘汰策略,别离是noeviction、volatile-random、volatile-ttl、volatile-lru、volatile-lfu、allkeys-lru、allkeys-random 和 allkeys-lfu 策略。看了一堆单词,很蛊惑,没关系这里只是先总体概述一下。上面别离开展具体介绍。其中allkeys结尾的淘汰策略的是在所有数据中进行淘汰,共有三种。volatile结尾的淘汰策略是在设置了过期工夫的数据中进行淘汰,共有四种。 1.noeviction该策略是Redis的默认策略。在这种策略下,一旦缓存被写满了,再有写申请来时,Redis 不再提供服务,而是间接返回谬误。这种策略不会淘汰数据,所以无奈解决缓存净化问题。个别生产环境不倡议应用。 其余七种规定都会依据本人相应的规定来抉择数据进行删除操作。 2.volatile-random这个算法比较简单,在设置了过期工夫的键值对中,进行随机删除。因为是随机删除,无奈把不再拜访的数据筛选进去,所以可能仍然会存在缓存净化景象,无奈解决缓存净化问题。 3.volatile-ttl这种算法判断淘汰数据时参考的指标比随即删除时多进行一步过期工夫的排序。Redis在筛选需删除的数据时,越早过期的数据越优先被抉择。 4.volatile-lru会应用 LRU 算法筛选设置了过期工夫的键值对。 LRU算法:LRU 算法的全称是 Least Recently Used。依照最近起码应用的准则来筛选数据。Redis优化的LRU算法实现: Redis会记录每个数据的最近一次被拜访的工夫戳。在Redis在决定淘汰的数据时,第一次会随机选出 N 个数据,把它们作为一个候选汇合。接下来,Redis 会比拟这 N 个数据的 lru 字段,把 lru 字段值最小的数据从缓存中淘汰进来。通过随机读取待删除汇合,能够让Redis不必保护一个微小的链表,也不必操作链表,进而晋升性能。 Redis 选出的数据个数 N,通过 配置参数 maxmemory-samples 进行配置。个数N越大,则候选汇合越大,抉择到的最久未被应用的就更精确,N越小,抉择到最久未被应用的数据的概率也会随之减小。 5.volatile-lfu会应用 LFU 算法抉择设置了过期工夫的键值对。 LFU 算法:LFU 缓存策略是在 LRU 策略根底上,为每个数据减少了一个计数器,来统计这个数据的拜访次数。当应用 LFU 策略筛选淘汰数据时,首先会依据数据的拜访次数进行筛选,把拜访次数最低的数据淘汰出缓存。如果两个数据的拜访次数雷同,LFU 策略再比拟这两个数据的拜访时效性,把间隔上一次拜访工夫更久的数据淘汰出缓存。Redis的LFU算法实现: 当 LFU 策略筛选数据时,Redis 会在候选汇合中,依据数据 lru 字段的后 8bit 抉择拜访次数起码的数据进行淘汰。当拜访次数雷同时,再依据 lru 字段的前 16bit 值大小,抉择拜访工夫最长远的数据进行淘汰。 Redis 只应用了 8bit 记录数据的拜访次数,而 8bit 记录的最大值是 255,这样在拜访疾速的状况下,如果每次被拜访就将拜访次数加一,很快某条数据就达到最大值255,可能很多数据都是255,那么进化成LRU算法了。所以Redis为了解决这个问题,实现了一个更优的计数规定,并能够通过配置项,来管制计数器减少的速度。 参数 : lfu-log-factor ,用计数器以后的值乘以配置项 lfu_log_factor 再加 1,再取其倒数,失去一个 p 值;而后,把这个 p 值和一个取值范畴在(0,1)间的随机数 r 值比大小,只有 p 值大于 r 值时,计数器才加 1。 ...

February 3, 2021 · 1 min · jiezi

关于redis:Redis-实战-13-扩展-Redis

简介当数据量增大或者读写申请增多后,一台 Redis 服务器可能没方法再存储所有数据或者解决所有读写申请,那么就须要对 Redis 进行扩大,保障 Redis 在能存储所有数据对状况下,同时能失常解决读写申请。 P227 扩大读性能 P227进步性能的几个路径 P228应用短构造:确保压缩列表的最大长度不会太大依据查问类型抉择构造 不要把列表当作汇合应用不要获取整个散列,而后再客户端外面进行排序,而应应用有序汇合大体积对象存储前进行压缩:缩小读写所需的网络带宽。比照 lz4, gzip 和 bzip2 等压缩算法,抉择对存储数据压缩成果和性能最好对压缩算法流水线和连接池:复制、解决故障、事务及性能优化 中介绍过流水线扩大读性能最简略的办法就是增加只读服务器(复制、解决故障、事务及性能优化 中介绍过通过复制 (replication) 让一个 Redis 服务器成为从服务器及运作原理和治理办法),并只对主服务器进行写入(默认状况下,尝试对一个从服务器进行写入将引发一个谬误,即便它是其余从服务器的主服务器)。 P228 增加从服务器 P228在配置文件中加上: slaveof <master-host> <master-port>向正在运行对 Redis 服务器发送: SLAVEOF <master-host> <master-port>能够通向从服务器发送 SLAVEOF NO ONE 命令让其与主服务器断开。 P228 当一个主服务器有大量从服务器时,那么它们以前同步时就会耗尽大部分带宽,导致主服务器提早变高,甚至导致主服务器断开和从服务器的连贯。 P229 解决从服务器重同步 (resync) 问题的办法 P229 构建树状的从服务器群组:通过构建二级从服务器升高主服务器须要传递给从服务器的数据量对网络连接进行压缩:应用带压缩带 SSH 隧道 (tunnel) 进行连贯能够显著地升高带宽(留神应用 SSH 提供的选项让 SSH 连贯在断线后主动连贯)故障转移 P230Redis Sentinel 能够配合 Redis 的复制性能应用,并对下线的主服务器进行故障转移。 Redis Sentinel 是运行在非凡模式下的 Redis 服务器,它会监督一系列主服务器以及它们的从服务器,通过向主服务器发送 PUBLISH 命令和 SUBSCRIBE 命令,并向主服务器和从服务器发送 PING 命令,各个 Sentinel 过程能够自主辨认可用的从服务器和其余 Sentinel 。当主服务器生效时,监督这个主服务器的所有 Sentinel 就会基于彼此共有的信息选出一个 Sentinel ,并从现有的从服务器中抉择一个新的主服务器。而后被选中的 Sentinel 就会让残余的其余从服务器去复制这个新的主服务器(默认设置下, Sentinel 会一个接一个地迁徙从服务器,但这个数量能够通过配置选项进行批改)。 P230 ...

February 2, 2021 · 1 min · jiezi

关于redis:Redis-实战-12-降低内存占用

简介升高 Redis 的内存占用有助于缩小创立快照和加载快照所需的工夫、晋升载入 AOF 文件和重写 AOF 文件时的效率、缩短从服务器进行同步所需的工夫(快照、 AOF 文件重写在 长久化选项 中进行了介绍,从服务器同步在 复制、解决故障、事务及性能优化 中进行了介绍),并且能让 Redis 存储更多的数据而无需增加额定的硬件。 P208 短构造 (short structure) P208Redis 为列表、汇合、散列和有序汇合提供了一组配置选项,这些选项能够让 Redis 以更节约空间的形式存储长度较短的构造(前面简称“短构造”)。 P208 在列表、散列和有序汇合的长度较短或者体积较小的时候, Redis 能够抉择应用一种名为压缩列表 (ziplist) 的紧凑存储形式来存储这些机构。压缩列表是列表、散列和有序汇合这 3 种不同类型的对象的一种非结构化 (unstructured) 示意:与 Redis 在通常状况下应用双向链表示意列表、应用散列表示意散列、应用散列表加上跳表 (skiplist) 示意有序汇合的做法不同,压缩列表会以序列化的形式存储数据,这些序列化数据每次被读取的时候都要进行解码,每次被写入的时候也要进行部分的从新编码,并且可能须要对内存外面的数据进行挪动。 P209 压缩列表示意 P209本节以最简略的列表进行察看比照。 双向链表 P209列表不进行压缩时应用双向链表 (doubly linked list) 进行存储,链表的每个结点都有三个指针: P209 指向前一个结点的指针指向后一个结点的指针指向结点蕴含的字符串值的指针其中字符串值又分为三个局部: P209 字符串的长度字符串残余可用的字节数以空字符结尾的字符串自身能够发现未压缩前,每存储一个字符串,起码须要 21 字节的额定开销 (overhead) 。(三个指针每个占 4 个字节,两个整数每个占 4 个字节,字符串结尾的空字符占 1 个字节) P209 压缩列表 P209压缩列表是由结点(非实在结点)组成的序列 (sequence) ,每个结点都由两个长度值和一个字符串组成。 P209 第一个长度值:前一个结点的长度,用于从后向前的遍历(个别以一个字节存储)第二个长度值:以后结点的长度(个别以一个字节存储)字符串:长度等于字节数,没有空字符能够发现压缩后,每存储一个字符串,起码须要 2 字节的额定开销。 P210 ...

February 1, 2021 · 2 min · jiezi

关于redis:Redis操作数据常用命令详细注释

Redis的基本操作 应用help查问有哪些命令 help @string # 查问string类型命令help @hash # 查问hash命令help @list # 查问list命令help @set # 查问set命令help @zset # 查问zset命令help @cluster # 查问集群命令help @generic # 查问通用命令......等等其余命令,能够应用Table键提醒 示例所有Key名都为bigkang为示例 # 查问所有Keykeys * # 判断某个Key是否存在exists <key>exists bigkang# 查问某个Key的类型type <key>type bigkang# 删除某个Key,返回一条影响行数,1示意true,删除胜利del <key>del bigkang# 给Key设置超时工夫,单位秒,返回一示意true,设置胜利expire <key> <seconds>expire bigkang 30# 查问Key过期工夫,返回秒数负数为超时工夫,,-1示意永不过期,-2示意已过期ttl <key>ttl bigkang# 查看以后数据库的key的数量(单个库)dbsize# 清空以后库Flushdb# 清空所有库Flushall字符串(String)的操作help @string # 查问string类型命令# 查问Key对应键值get <key>get bigkang# 设置值,增加键值对,给bigkang赋值为123,没有则创立bigkangset <key> <value>set bigkang 123# 追加,给bigkang追加456append <key> <value>append bigkang 456# 查问Key长度,这个key的长度也就是lengthstrlen <key>strlen bigkang# 设置值,如果不存在则设置一个值,如果存在则设置失败setnx <key> <value>setnx bigkang 123# 给Key值减少1,相似于i++操作,如果是字符串将无返回,必须为数据,返回值为批改后的Valueincr <key>incr bigkang# 给Key值缩小1,相似于i--操作,如果是字符串将无返回,必须为数据,返回值为批改后的Valuedecr <key>dect bigkang# 指定Key增加或者缩小肯定的数量,给bigkang这个key的Value增加100,而后再缩小100,返回值为批改后的Valueincrby / decrby <key> <步长>incrby bigkang 100decrby bigkang 100# 批量设置键值对mset <key1> <value1> <key2> <value2>mset bigkang1 1 bigkang2 2 bigkang3 3# 同时设置一个或多个 key-value 对,如果不存在则设置,如果其中一个条件不满足则都失败msetnx <key1> <value1> <key2> <value2> msetnx bigkang4 1 bigkang5 2 bigkang6 3# 截取范畴,取得值的范畴,相似java中的substring,起始下标为0,只返回到结尾,超出失常返回getrange <key> <起始地位> <完结地位>getrange bigkang 0 10# 插入值,从指定地位插入字符串,返回字符串长度setrange <key> <起始地位> <value>setrange bigkang 0 big# 设置键值的同时,设置过期工夫,单位秒setex <key> <过期工夫> <value># 获取以前的值写入新的值getset <key> <value>getset bigkang 123 哈希(Hash)的操作help @hash # 查问hash类型命令# 设置Hash值,Hash相似以Java中的Map,Hash的Key存在返回0,不存在返回1,如果是String则报错,设置name 为 bigkang,age为 21hset <key> <field> <value>hset bigkang name bigkang age 21# 从Hash中取出某个属性的Value值hget <key> <field>hget bigkang name# 批量设置Hash的值hmset <key> <field1> <value1> <field2> <value2>hmset bigkang name bigkang1 age 2000# 批量获取值hmset <key> <field1> <field2> hmget bigkang name age# 判断field是否存在,返回0 OR 1,对应True,Falsehexists <key> <field>hexists bigkang name# 列出某个key的所有fieldhkeys <key>hkeys bigkang# 列出某个key的所有Valuehvals <key>hvals bigkang# 为哈希表 key 中的域 field 的值加上增量 incrementhincrby <key> <field> <increment>hincrby bigkang age 1# 将哈希表 key 中的域 field 的值设置为 value ,不存在时进行设置,存在不设置hsetnx <key> <field> <value>hsetnx bigkang name bigkang 字符串链表(list)的操作help @list # 查问list类型命令# 从右边/左边插入一个或多个值lpush/rpush <key> <value1> <value2> <value3># 右边插入lpush bigkang 1 2 3# 左边插入rpush bigkang 4 5 6# 从右边/左边吐出一个值lpop/rpop key# 从右边吐出lpop bigkang# 从左边吐出rpop bigkang# 从一个列表左边吐出一个值,插到另一个列表右边rpoplpush <key1> <key2>rpoplpush bigkang bigkang1# 依照索引下标取得元素(从左到右),索引从0开始lindex <key> <index>lindex bigkang 2# 依照起始地位完结地位范畴取得元素(从左到右),索引从0开始lrange <key> <start> <stop>lrang bigkang 0 3# 取得列表长度llen <key>llen bigkang# 依据Key找到某个值,并且在他后面/前面插入一个值linsert <key> AFTER/BEFORE <value> <newvalue># 在bigkang这个key的值为1的后面插入0.9linsert bigkang AFTER 1 0.9# 在bigkang这个key的值为1的前面插入1.1linsert bigkang BEFORE 1 1.1# 从依据某个Key,找到Value,删除这个Value几个个数lrem <key> <n> <value># 在bigkang中,从右边开始查问,删除1这个元素,删除两个(可能元素List中有多个1)lrem bigkang 2 1字符串汇合(set)的操作help @set # 查问set类型命令# 将一个或多个 member 元素退出到汇合 key 当中,曾经存在于汇合的 member 元素将被疏忽,插入胜利返回1,插入失败示意0曾经存在sadd <key> <value1> <value2> ..... sadd bigkang 1 2 3# 取出该汇合的所有值smembers <key>smembers bigkang# 返回该汇合的元素个数scard <key>scard bigkang# 判断汇合<key>是否为含有该<value>值,有返回1,没有返回0sismember <key> <value>sismember bigkang 1# 删除汇合中的某个元素srem <key> <value1> <value2> .... srem bigkang 1 2 3# 随机从该汇合中吐出一个值,会将原来的值删除spop <key>spop bigkang# 随机从该汇合中取出n个值。 不会从汇合中删除srandmember <key> <n>srandmember bigkang 3# 返回两个汇合的交加元素,如bigkang有1,bigkang2也有1,则返回1,所有雷同的都会返回sinter <key1> <key2>sinter bigkang bigkang2# 返回两个汇合的并集元素,例如bigkang为 1 2 3,bigkang2 为 3 4 5 ,则返回1 2 3 4 5sunion <key1> <key2>sunion bigkang bigkang2# 返回两个汇合的差集元素,例如bigkang为 1 2 3,bigkang2 为 3 4 5 ,则返回1 2 4 5sdiff <key1> <key2>sdiff bigkang bigkang2有序字符串汇合(zset)的操作help @sorted_set # 查问zset类型命令# 将一个或多个 member 元素及其 score 值退出到有序集 key 当中,zset会依据score排序zadd <key> <score1> <value1> <score2> <value2>... zadd bigkang 1 A 2 B 3 C# 返回有序集 key 中,下标在<start> <stop>之间的元素,带WITHSCORES,能够让分数一起和值返回到后果集,索引从0开始,0 1 会蕴含0 和 1zrange <key> <start> <stop> [WITHSCORES]# 带分数返回0 到 2 三个值,并且返回分数,从小到大zrange bigkang 0 2 WITHSCORES# 不返回分数zrange bigkang 0 2# 同上,程序相同,从大到小zrevrange bigkang 0 2# -1示意返回所有zrevrange bigkang 0 -1# 返回有序集 key 中,分数在min到max中的值(蕴含),有序集成员按 score 值递增(从小到大)秩序排列zrangebyscore key min max [withscores][limit offset count]zrangebyscore bigkang 1 2.5 WITHSCORES# 同上,改为从大到小排列,max min相同zrevrangebyscore key max min [withscores][limit offset count]zrevrangebyscore bigkang 2.5 1 WITHSCORES# 为元素的score加上增量zincrby <key> <increment> <value>zincrby bigkang 3 A# 删除该汇合下,指定值的元素zrem <key> <value>zrem bigkang A# 统计该汇合,分数区间内的元素个数zcount <key> <min> <max>zcount bigkang 1 20# 返回该值在汇合中的排名,从0开始,返回索引下标,从小到大zrank <key> <value>zrank bigkang B Bit操作设置(Bit) 首先咱们须要理解什么是Bit,其实所有的Bit操作都是在操作字符串类型,咱们设置了bit当前能够发现他的类型其实是一个String ...

February 1, 2021 · 5 min · jiezi

关于redis:Reactive-Spring实战-响应式Redis交互

本文分享Spring中如何实现Redis响应式交互模式。 本文将模仿一个用户服务,并应用Redis作为数据存储服务器。本文波及两个java bean,用户与权利 public class User { private long id; private String name; // 标签 private String label; // 收货地址经度 private Double deliveryAddressLon; // 收货地址维度 private Double deliveryAddressLat; // 最新签到日 private String lastSigninDay; // 积分 private Integer score; // 权利 private List<Rights> rights; ...}public class Rights { private Long id; private Long userId; private String name; ...}启动引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency>增加Redis配置 spring.redis.host=192.168.56.102spring.redis.port=6379spring.redis.password=spring.redis.timeout=5000SpringBoot启动 @SpringBootApplicationpublic class UserServiceReactive { public static void main(String[] args) { new SpringApplicationBuilder( UserServiceReactive.class) .web(WebApplicationType.REACTIVE).run(args); }}利用启动后,Spring会主动生成ReactiveRedisTemplate(它的底层框架是Lettuce)。ReactiveRedisTemplate与RedisTemplate应用相似,但它提供的是异步的,响应式Redis交互方式。这里再强调一下,响应式编程是异步的,ReactiveRedisTemplate发送Redis申请后不会阻塞线程,以后线程能够去执行其余工作。等到Redis响应数据返回后,ReactiveRedisTemplate再调度线程解决响应数据。响应式编程能够通过优雅的形式实现异步调用以及解决异步后果,正是它的最大的意义。 ...

January 31, 2021 · 3 min · jiezi

关于redis:Redis-个人使用指南

通过命令行形式连贯redis 1、首先装置redis客户端 yum install redis2、连贯 redis-cli -h 127.0.0.1 -p 6379 -a password# host:近程redis服务器host# port:近程redis服务端口$ password:近程redis服务明码(无明码的的话就不须要-a参数了)

January 30, 2021 · 1 min · jiezi

关于redis:Redis第六章节事务

目录简介执行过程特点案例watch简介事务(Transaction),个别是指要做的或所做的事件。在计算机术语中是指拜访并可能更新数据库中各种数据项的一个程序执行单元(unit)。 执行过程开始事务 -> 命令入队 -> 执行事务。 特点① 批量操作在发送 exec 命令前被放入队列缓存。 ② 收到exec命令后进入事务执行,事务中任意命令执行失败,其余的命令仍然会被执行。 ③ 在事务的执行过程中,其余客户端提交的命令申请不会插入到事务执行命令的序列中。 案例:(1)失常执行 localhost:6379> multi OK localhost:6379> set a 1111 QUEUED localhost:6379> set b 2222 QUEUED localhost:6379> set c 3333 QUEUED localhost:6379> set d 4444 QUEUED localhost:6379> exec 1) OK 2) OK 3) OK 4) OK(2)勾销事务 localhost:6379> multi OK localhost:6379> set e 55555 QUEUED localhost:6379> set f 66666 QUEUED localhost:6379> discard OK localhost:6379> exec (error) ERR EXEC without MULTI(3)编译型谬误最初执行exec命令之后,会执行队列中的命令,队列中命令有失败的,所以最初整个命令都执行失败。 编译型异样代码有问题,命令有错,事务中所有的命令都不会被执行。(4)运行时谬误 ...

January 30, 2021 · 1 min · jiezi

关于redis:Docker-安装-Redis

关上 终端 #获取镜像docker pull redis #运行容器docker run -itd --name redis-test -p 6379:6379 redis#通过 redis-cli 连贯测试应用 redis 服务docker exec -it redis-test /bin/bash

January 30, 2021 · 1 min · jiezi

关于redis:Redis-实战-10-实现内容搜索定向广告和职位搜索

应用 Redis 进行搜寻 P153通过改变程序搜寻数据的形式,并应用 Redis 来缩小绝大部分基于单词或者关键字进行的内容搜寻操作的执行工夫。 P154 根本搜寻原理 P154倒排索引 (inverted indexes) 是互联网上绝大部分搜索引擎应用的底层构造,它相似于书本开端的索引。倒排索引从每个被索引的文档外面提取一些单词,并记录蕴含每个单词的文档汇合。 P154 示例 假如有三个文档: R = "it is what it is"S = "what is it"T = "it is a banana"咱们就能失去上面的倒排索引汇合: "a": {2}"banana": {2}"is": {0, 1, 2}"it": {0, 1, 2}"what": {0, 1}检索的条件 "what", "is" 和 "it" 将对应这个汇合:{0,1} ∩ {0,1,2} ∩ {0,1,2} = {0,1} 能够发现 Redis 的汇合和有序汇合非常适合解决倒排索引。 根本索引操作 从文档外面提取单词的过程通常被成为语法分析 (parsing) 和标记化 (tokenization) ,这个过程能够产生一系列用于示意文档的标记 (token) ,有时又被成为单词 (word) 。 P155 标记化的一个常见的附加步骤就是移除非用词 (stop word) 。非用词就是那些在文档中频繁呈现却没有提供相应信息量的单词,对这些单词进行搜寻将返回大量无用的后果。 P155 ...

January 29, 2021 · 2 min · jiezi

关于redis:Redis的Hash冲突以及渐进式ReHash源码分析

Redis数据DB      Redis是一个一个的DB,那么这个DB到底是一个什么样构造的数据呢?       如下是Redis官网的源码(5.0) /* Redis数据库示意。有多个数据库标识从0(默认数据库)到配置的最大值的整数数据库。数据库号是构造中的“id”字段*/typedef struct redisDb { dict *dict; /* 这个数据库的键空间(字典类型) */ dict *expires; /* 设置超时的键的超时 */ dict *blocking_keys; /* 客户端期待数据的密钥(BLPOP) */ dict *ready_keys; /* 接管到推送的阻塞键 */ dict *watched_keys; /* EXEC CAS的监督键 */ int id; /* 数据库ID */ long long avg_ttl; /* 均匀TTL,仅用于统计 */ list *defrag_later; /* 要一一进行磁盘整顿的键名列表 */} redisDb;      咱们能够看到Redis的数据库次要的数据是寄存在字典中的 Redis数据Dict字典      官网源码地址:https://github.com/redis/redi...       咱们找到dict字典的定义: // 字典类型数据定义typedef struct dict { dictType *type; /* 字典类型数组 */ void *privdata; /* 公有数据 */ dictht ht[2]; /* 字典Hash表数组 */ long rehashidx; /* 如果 rehashidx == -1,示意没有进行Rehash,如果为负数示意有ReHash操作 */ unsigned long iterators; /* 以后正在运行的迭代器数 */} dict;      次要的数据是寄存在咱们的字典Hash表数组中的咱们在来看一下这个dictht,字典Hash表 ...

January 29, 2021 · 4 min · jiezi

关于redis:docker-操作redis

1、搜寻源docker search redis2、下载源docker pull redis3、创立并启动myredis容器(设置端口才能够连贯)docker run -d -p 6379:6379 -it --name="myredis" redis4、查看容器docker ps myredis5、进入myredis容器docker exec -it myredis redis-cli

January 29, 2021 · 1 min · jiezi

关于redis:Redis配置文件解读

# Redis configuration file example.# Note that in order to read the configuration file, Redis must be# started with the file path as first argument:# 为了读取配置文件,Redis必须以文件门路作为第一个参数启动。# ./redis-server /path/to/redis.conf# Note on units: when memory size is needed, it is possible to specify# it in the usual form of 1k 5GB 4M and so forth:# 对于单元的注意事项:当须要内存大小时,能够用通常的1k 5GB 4M等模式指定它# 1k => 1000 bytes# 1kb => 1024 bytes# 1m => 1000000 bytes# 1mb => 1024*1024 bytes# 1g => 1000000000 bytes# 1gb => 1024*1024*1024 bytes## units are case insensitive so 1GB 1Gb 1gB are all the same.######################## INCLUDES ####################### Include one or more other config files here. This is useful if you# have a standard template that goes to all Redis servers but also need# to customize a few per-server settings. Include files can include# other files, so use this wisely.# include 能够蕴含一个或多个其余配置文件,如果您有一个规范模板,可用于所有Redis服 # 务器,而每个服务只需大量的配置,那么这很有用。Include文件能够蕴含其余文件, # 所以要明智地应用它。# Notice option "include" won't be rewritten by command "CONFIG REWRITE"# from admin or Redis Sentinel. Since Redis always uses the last processed# line as value of a configuration directive, you'd better put includes# at the beginning of this file to avoid overwriting config change at runtime.# 留神:选项 "include" 不能通过admin或者 Redis Sentinel 应用 "CONFIG REWRITE" 命# 令重写。# If instead you are interested in using includes to override configuration# options, it is better to use include as the last line.# 如果您对应用include重写配置选项感兴趣,那么最好应用include作为最初一行# include /path/to/local.conf# include /path/to/other.conf######################### MODULES ############################ Load modules at startup. If the server is not able to load modules# it will abort. It is possible to use multiple loadmodule directives.# REDIS在启动的时候加载自定义模块,如果模块不能加载,REDIS将启动失败。# 能够配置多个loadmodule命令。# loadmodule /path/to/my_module.so# loadmodule /path/to/other_module.so######################## NETWORK ############################## By default, if no "bind" configuration directive is specified, Redis listens# for connections from all the network interfaces available on the server.# It is possible to listen to just one or multiple selected interfaces using# the "bind" configuration directive, followed by one or more IP addresses.# 默认状况下,如果没有指定“bind”配置指令,Redis将侦听服务器上所有可用# 网络地址。应用“bind”配置指令,后跟一个或多个IP地址,能够只监听一个或多个# 指定的IP地址。# Examples:## bind 192.168.1.100 10.0.0.1# bind 127.0.0.1 ::1## ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the# internet, binding to all the interfaces is dangerous and will expose the# instance to everybody on the internet. So by default we uncomment the# following bind directive, that will force Redis to listen only into# the IPv4 loopback interface address (this means Redis will be able to# accept connections only from clients running into the same computer it# is running).# 如果Redis所在的服务器裸露在了互联网上,那么Redis监听所有的网络地址# 是危险的。互联网上的每个人都能够应用该Redis服务。所有默认状况下,咱们# 只监听本地IP地址,这样,只有本服务器上的利用能力应用该Redis服务。# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES# JUST COMMENT THE FOLLOWING LINE.# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~bind 127.0.0.1# Protected mode is a layer of security protection, in order to avoid that# Redis instances left open on the internet are accessed and exploited.## When protected mode is on and if:## 1) The server is not binding explicitly to a set of addresses using the# "bind" directive.# 2) No password is configured.# 爱护模块是一个平安保护层,目标是防止在互联网上裸露的Redis服务被# 利用和拜访。在上面状况下时,保护模式被开启:# 1:没有应用“bind”指令显式绑定到一组地址# 2:没有配置拜访明码# The server only accepts connections from clients connecting from the# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain# sockets.## By default protected mode is enabled. You should disable it only if# you are sure you want clients from other hosts to connect to Redis# even if no authentication is configured, nor a specific set of interfaces# are explicitly listed using the "bind" directive.#默认状况下,已启用保护模式。只有当您确定心愿其余主机的客户机连贯到Redis时,# 才应该禁用它,即便没有配置身份验证,也没有应用“bind”指令显式列出一组# 特定的网络IP地址。protected-mode yes# Accept connections on the specified port, default is 6379 (IANA #815344).# If port 0 is specified Redis will not listen on a TCP socket.# 在指定端口上承受连贯。默认端口是6379.# 如果端口指定为0,将不再承受TCP连贯。port 6379# TCP listen() backlog.## In high requests-per-second environments you need an high backlog in order# to avoid slow clients connections issues. Note that the Linux kernel# will silently truncate it to the value of /proc/sys/net/core/somaxconn so# make sure to raise both the value of somaxconn and tcp_max_syn_backlog# in order to get the desired effect.# 在每秒申请数高的环境中,能够配置一个高 tcp-backlog 值,# 从而防止客户机连贯速度慢的问题,请留神,Linux内核将静默地将其# 截断为/proc/sys/net/core/somaxconn的值,因而请确保同时# 进步somaxconn和tcp_max_syn_backlog的值,以取得所需的成果。tcp-backlog 511# Unix socket.## Specify the path for the Unix socket that will be used to listen for# incoming connections. There is no default, so Redis will not listen# on a unix socket when not specified.# 指定将用于侦听传入连贯的Unix套接字的门路。没有默认值,# 因而未指定时,Redis将不会侦听unix套接字# unixsocket /tmp/redis.sock# unixsocketperm 700# Close the connection after a client is idle for N seconds (0 to disable)timeout 0# TCP keepalive.## If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence# of communication. This is useful for two reasons:## 1) Detect dead peers.# 2) Take the connection alive from the point of view of network# equipment in the middle.# 如果不为0,在客户端离线状况下,应用 SO_KEEPALIVE 来发送TCP# 应答音讯。这样做有2个目标:# 1:检测死机# 2:以网络中间件形式来对待网络# On Linux, the specified value (in seconds) is the period used to send ACKs.# Note that to close the connection the double of the time is needed.# On other kernels the period depends on the kernel configuration.# 在Linux零碎,该指定值(以秒为单位)是发送确认的周期。# 须要留神的是,敞开连贯须要破费双倍的工夫。# 在其它内核上,周期依赖于内核配置。# A reasonable value for this option is 300 seconds, which is the new# Redis default starting with Redis 3.2.1.# 该选项的正当值是300秒。这是从Redis 3.2.1开始的新Redis默认值tcp-keepalive 300##################### TLS/SSL ######################### By default, TLS/SSL is disabled. To enable it, the "tls-port" configuration# directive can be used to define TLS-listening ports. To enable TLS on the# default port, use:# 默认状况下,TLS/SSL是禁用的。如果须要启动,配置tls-port来定义TLS# 监听段。能够应用上面配置来启动TLS。# port 0# tls-port 6379# Configure a X.509 certificate and private key to use for authenticating the# server to connected clients, masters or cluster peers. These files should be# PEM formatted.# 配置X.509证书和私钥,以用于验证连贯的客户端、主机或群集。# 这些文件应为PEM格局。# tls-cert-file redis.crt # tls-key-file redis.key# Configure a DH parameters file to enable Diffie-Hellman (DH) key exchange:## tls-dh-params-file redis.dh# Configure a CA certificate(s) bundle or directory to authenticate TLS/SSL# clients and peers. Redis requires an explicit configuration of at least one# of these, and will not implicitly use the system wide configuration.## tls-ca-cert-file ca.crt# tls-ca-cert-dir /etc/ssl/certs# By default, clients (including replica servers) on a TLS port are required# to authenticate using valid client side certificates.## It is possible to disable authentication using this directive.## tls-auth-clients no# By default, a Redis replica does not attempt to establish a TLS connection# with its master.## Use the following directive to enable TLS on replication links.## tls-replication yes# By default, the Redis Cluster bus uses a plain TCP connection. To enable# TLS for the bus protocol, use the following directive:## tls-cluster yes######################## GENERAL ############################### By default Redis does not run as a daemon. Use 'yes' if you need it.# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.# 默认状况下,Redis并不是守护过程。如果须要是守护过程,请配置为yes.# 如果是守护过程,Redis会写一个PID文件:/var/run/redis.piddaemonize no# If you run Redis from upstart or systemd, Redis can interact with your# supervision tree. Options:# 能够通过upstart和systemd治理Redis守护过程# supervised no - no supervision interaction# supervised no - 无监督互动# supervised upstart - signal upstart by putting Redis into SIGSTOP mode# supervised upstart - 通过将Redis置于SIGSTOP模式发出信号# supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET# supervised systemd - signal systemd将READY = 1写入$ NOTIFY_SOCKET# supervised auto - detect upstart or systemd method based on# UPSTART_JOB or NOTIFY_SOCKET environment variables# supervised auto - 检测upstart或systemd办法基于 UPSTART_JOB# 或NOTIFY_SOCKET环境变量# Note: these supervision methods only signal "process is ready."# They do not enable continuous liveness pings back to your supervisor.supervised no# If a pid file is specified, Redis writes it where specified at startup# and removes it at exit.# 指定pid文件。Redis将在启动的时候写入,退出的时候删除。# When the server runs non daemonized, no pid file is created if none is# specified in the configuration. When the server is daemonized, the pid file# is used even if not specified, defaulting to "/var/run/redis.pid".# 如果Reids是非守护过程,如果没有配置pid文件,那么就不会产生pid文件。# 如果是守护过程,即便没有配置pid文件,也会创立pid文件。默认门路# 是 /var/run/redis.pid# Creating a pid file is best effort: if Redis is not able to create it# nothing bad happens, the server will start and run normally.# 创立一个pid文件是最好的办法:如果Redis不能创立它,# 那么不会有什么不好的事件产生,服务器将失常启动和运行。pidfile /var/run/redis_6379.pid# Specify the server verbosity level. 指定日志级别# This can be one of:# debug (a lot of information, useful for development/testing)# verbose (many rarely useful info, but not a mess like the debug level)# notice (moderately verbose, what you want in production probably)# warning (only very important / critical messages are logged)loglevel notice# Specify the log file name. Also the empty string can be used to force# Redis to log on the standard output. Note that if you use standard# output for logging but daemonize, logs will be sent to /dev/null# 指定日志文件名。也能够应用空字符串强制Redis应用日志规范输入。# 请留神,如果您应用规范输入进行日志记录,然而daemonize,# 日志将被发送到/dev/nulllogfile ""# To enable logging to the system logger, just set 'syslog-enabled' to yes,# and optionally update the other syslog parameters to suit your needs.# 如果须要打印日志到操作系统日志,配置syslog-enabled为yes。# 并依据须要更新其余syslog参数# syslog-enabled no# Specify the syslog identity. 指定系统日志标识# syslog-ident redis# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.# 指定日志日志设置,必须是USER 或者是 LOCAL0 到 LOCAL7。# syslog-facility local0# Set the number of databases. The default database is DB 0, you can select# a different one on a per-connection basis using SELECT <dbid> where# dbid is a number between 0 and 'databases'-1# 设置数据库数量。默认数据是DB 0。能够在连贯redis的时候抉择一个不同的# 数据库应用 SELECT <dbid>。dbid 是一个数字基于 0 到 'databases'-1 。databases 16# By default Redis shows an ASCII art logo only when started to log to the# standard output and if the standard output is a TTY. Basically this means# that normally a logo is displayed only in interactive sessions.# 默认状况下,只有在TTY规范日志输入的状况下,能力打印LOGO。# However it is possible to force the pre-4.0 behavior and always show a# ASCII art logo in startup logs by setting the following option to yes.# 如果想要强制在启动的时候打印LOGO,配置 always-show-logo 为yes always-show-logo yes######################## SNAPSHOTTING ########################### Save the DB on disk: 保留DB到磁盘## save <seconds> <changes>## Will save the DB if both the given number of seconds and the given# number of write operations against the DB occurred.# 在指定秒数 和 指定写入数据的次数共事满足的状况下,将保留DB到磁盘## In the example below the behaviour will be to save:# after 900 sec (15 min) if at least 1 key changed# after 300 sec (5 min) if at least 10 keys changed# after 60 sec if at least 10000 keys changed## Note: you can disable saving completely by commenting out all "save" lines.# 如果禁用保留,通过正文 save 配置行# It is also possible to remove all the previously configured save# points by adding a save directive with a single empty string argument# like in the following example:# 还能够通过增加带有单个空字符串参数的save指令来删除所有先前配置的存储点# save ""save 900 1 # 900秒内至多1次写操作save 300 10 # 300秒内至多10次写操作save 60 10000 # 60秒内至多10000 次写操作# By default Redis will stop accepting writes if RDB snapshots are enabled# (at least one save point) and the latest background save failed.# This will make the user aware (in a hard way) that data is not persisting# on disk properly, otherwise chances are that no one will notice and some# disaster will happen.# 默认状况下,如果启用了RDB快照(至多有一个保留点),并且最新的后盾保留失败,# 则Redis将进行承受写入。这将使用户意识到(以一种硬的形式)数据没有正确地# 保留在磁盘上,否则很可能没有人会留神到,并且会产生一些劫难。## If the background saving process will start working again Redis will# automatically allow writes again.# 如果后盾保留过程从新开始工作,Redis将主动容许再次写入。# However if you have setup your proper monitoring of the Redis server# and persistence, you may want to disable this feature so that Redis will# continue to work as usual even if there are problems with disk,# permissions, and so forth.# 然而,如果您曾经设置了对Redis服务器和持久性的适当监督,那么您可能心愿禁用此性能,# 以便即便磁盘、权限等呈现问题,Redis也将持续失常工作。stop-writes-on-bgsave-error yes# Compress string objects using LZF when dump .rdb databases?# For default that's set to 'yes' as it's almost always a win.# If you want to save some CPU in the saving child set it to 'no' but# the dataset will likely be bigger if you have compressible values or keys.# 在转储.rdb数据库时应用LZF压缩字符串对象?默认设置为“是”,因为这简直总是一场胜利。# 如果您想在saving子过程中保留一些CPU,请将其设置为“no”,但如果您有可压缩的值或键,# 则数据集可能会更大。rdbcompression yes# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.# This makes the format more resistant to corruption but there is a performance# hit to pay (around 10%) when saving and loading RDB files, so you can disable it# for maximum performances.# 从RDB的版本5开始,CRC64校验和被放在文件的开端,这能避免文件格式损坏,# 然而在保留和加载RDB文件时,会有一个性能损失(大概10%),#因而您能够禁用它以取得最大的性能# RDB files created with checksum disabled have a checksum of zero that will# tell the loading code to skip the check.# 在禁用校验和的状况下创立的RDB文件的校验和为零,这将通知加载代码跳过查看。rdbchecksum yes# The filename where to dump the DB DB快照到磁盘的文件名dbfilename dump.rdb# Remove RDB files used by replication in instances without persistence# enabled. By default this option is disabled, however there are environments# where for regulations or other security concerns, RDB files persisted on# disk by masters in order to feed replicas, or stored on disk by replicas# in order to load them for the initial synchronization, should be deleted# ASAP. Note that this option ONLY WORKS in instances that have both AOF# and RDB persistence disabled, otherwise is completely ignored.# 在没有启用持久性的实例中删除复制应用的RDB文件。默认状况下,# 此选项处于禁用状态。然而,在某些环境中,出于治理法规或其余平安思考,# 应尽快删除主服务器在磁盘上保留的RDB文件,以便向正本提供数据,# 或通过正本存储在磁盘上以加载这些文件以进行初始同步。#请留神,此选项仅实用于同时禁用AOF和RDB持久性的实例,否则将齐全疏忽。# An alternative (and sometimes better) way to obtain the same effect is# to use diskless replication on both master and replicas instances. However# in the case of replicas, diskless is not always an option.# 另一种(有时更好)的办法是在主实例和正本实例上应用无盘复制。# 然而,对于正本,无盘并不总是一个选项。rdb-del-sync-files no# The working directory. 工作目录## The DB will be written inside this directory, with the filename specified# above using the 'dbfilename' configuration directive.# 数据库将写入此目录中,并应用下面应用“dbfilename”配置指令指定的文件名。# The Append Only File will also be created inside this directory.# AOF 文件也是写在此目录# Note that you must specify a directory here, not a file name. 这里必须是目录,而不是文件名dir ./################################# REPLICATION ################################## Master-Replica replication. Use replicaof to make a Redis instance a copy of# another Redis server. A few things to understand ASAP about Redis replication.# 应用replicaof使Redis实例成为另一个Redis服务器的正本。# 对于Redis复制,须要尽快理解一些事件。# +------------------+ +---------------+# | Master | ---> | Replica |# | (receive writes) | | (exact copy) |# +------------------+ +---------------+## 1) Redis replication is asynchronous, but you can configure a master to# stop accepting writes if it appears to be not connected with at least# a given number of replicas.# Redis复制是异步的,然而您能够配置一个主服务器,# 使其进行承受写入,如果它仿佛没有连贯到至多给定数量的正本。# 2) Redis replicas are able to perform a partial resynchronization with the# master if the replication link is lost for a relatively small amount of# time. You may want to configure the replication backlog size (see the next# sections of this file) with a sensible value depending on your needs.# 如果复制链接失落的工夫绝对较短,则Redis正本可能与主服务器执行局部从新同步。# 依据您的须要,您可能须要应用一个正当的值# 来配置复制backlog大小(请参阅此文件的下一节)。# 3) Replication is automatic and does not need user intervention. After a# network partition replicas automatically try to reconnect to masters# and resynchronize with them.# 复制是主动的,不须要用户干涉。在网络分区之后,# 复制正本会主动尝试从新连贯到主机并与它们从新同步。# replicaof <masterip> <masterport># If the master is password protected (using the "requirepass" configuration# directive below) it is possible to tell the replica to authenticate before# starting the replication synchronization process, otherwise the master will# refuse the replica request.# 如果主机受密码保护(应用上面的“requirepass”配置指令),# 则能够在开始复制同步过程之前告诉正本进行身份验证,# 否则主服务器将回绝正本申请。# masterauth <master-password>## However this is not enough if you are using Redis ACLs (for Redis version# 6 or greater), and the default user is not capable of running the PSYNC# command and/or other commands needed for replication. In this case it's# better to configure a special user to use with replication, and specify the# masteruser configuration as such:# 然而,如果您应用的是Redis acl(用于Redis version 6或更高版本)# 并且默认用户无奈运行PSYNC命令和/或复制所需的其余命令,那么这还不够。# 在这种状况下,最好配置一个用于复制的非凡用户,并按如下形式指定主用户配置:# masteruser <username>## When masteruser is specified, the replica will authenticate against its# master using the new AUTH form: AUTH <username> <password>.# 指定masteruser后,复制正本将应用新的身份验证模式# AUTH<username><password>对其主服务器进行身份验证。# When a replica loses its connection with the master, or when the replication# is still in progress, the replica can act in two different ways:# 当复制正本失去与主服务器的连贯,或复制仍在进行时,# 复制正本能够以两种不同的形式操作:# 1) if replica-serve-stale-data is set to 'yes' (the default) the replica will# still reply to client requests, possibly with out of date data, or the# data set may just be empty if this is the first synchronization.# 如果replica-serve-stale-data设置为“yes”(默认值),则复制正本仍将响应客户端申请# 数据可能已过期,或者如果这是第一次同步,则数据集可能为空。# 2) if replica-serve-stale-data is set to 'no' the replica will reply with# an error "SYNC with master in progress" to all the kind of commands# but to INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG,# SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB,# COMMAND, POST, HOST: and LATENCY.# 如果replica serve stale data设置为“no”,复制正本将对所有类型的命令回答# 谬误“SYNC with master in progress”,除了INFO,AUTH等命令外replica-serve-stale-data yes# You can configure a replica instance to accept writes or not. Writing against# a replica instance may be useful to store some ephemeral data (because data# written on a replica will be easily deleted after resync with the master) but# may also cause problems if clients are writing to it because of a# misconfiguration.# 您能够将正本实例配置为承受或不承受写入。针对正本实例的写入对于存储# 一些短暂的数据可能很有用(因为在正本上写入的数据在与主服务器从新同步后# 很容易被删除),然而如果客户机因为配置谬误而向其写入数据,也可能会导致问题# Since Redis 2.6 by default replicas are read-only.## Note: read only replicas are not designed to be exposed to untrusted clients# on the internet. It's just a protection layer against misuse of the instance.# Still a read only replica exports by default all the administrative commands# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve# security of read only replicas using 'rename-command' to shadow all the# administrative / dangerous commands.# 请留神,复制正本不可在internet上公开。它只是避免实例被滥用的保护层。# 默认状况下,只读正本仍会导出所有治理命令,如CONFIG、DEBUG等。# 在肯定水平上,您能够应用“rename command”来暗藏所有治理/危险命令来进步只读正本的安全性。replica-read-only yes# Replication SYNC strategy: disk or socket.# 复制同步策略:磁盘或网络。# New replicas and reconnecting replicas that are not able to continue the# replication process just receiving differences, need to do what is called a# "full synchronization". An RDB file is transmitted from the master to the# replicas.# 新的复制正本和从新连贯的复制正本如果只是接管到差别而无奈持续复制过程,# 则须要执行所谓的“齐全同步”。RDB文件从主服务器传输到正本。# The transmission can happen in two different ways:## 1) Disk-backed: The Redis master creates a new process that writes the RDB# file on disk. Later the file is transferred by the parent# process to the replicas incrementally.# Redis主机创立一个新过程,将RDB文件写入磁盘.稍后,该文件由父过程以增量形式传输到正本。# 2) Diskless: The Redis master creates a new process that directly writes the# RDB file to replica sockets, without touching the disk at all.# Redis master创立了一个新过程,间接将RDB文件写入正本套接字,而不须要接触磁盘。## With disk-backed replication, while the RDB file is generated, more replicas# can be queued and served with the RDB file as soon as the current child# producing the RDB file finishes its work. With diskless replication instead# once the transfer starts, new replicas arriving will be queued and a new# transfer will start when the current one terminates.# 应用磁盘备份复制,在生成RDB文件时,只有以后生成RDB文件的子级实现工作,# 就能够将更多正本排入队列并与RDB文件一起提供服务。# 应用无盘复制,一旦传输开始,达到的新正本将进入队列,新的传输将在以后复制终止时开始# When diskless replication is used, the master waits a configurable amount of# time (in seconds) before starting the transfer in the hope that multiple# replicas will arrive and the transfer can be parallelized.# 当应用无盘复制时,主机在开始传输之前期待一段可配置的工夫(以秒为单位),# 心愿多个正本将达到并且传输能够并行化。# With slow disks and fast (large bandwidth) networks, diskless replication# works better. 在磁盘速度慢和网络比拟快的状况下,无盘复制比拟适合repl-diskless-sync no# When diskless replication is enabled, it is possible to configure the delay# the server waits in order to spawn the child that transfers the RDB via socket# to the replicas.# 启用无盘复制时,能够配置服务器期待的提早,以便生成通过套接字将RDB传输到正本的子工作。# This is important since once the transfer starts, it is not possible to serve# new replicas arriving, that will be queued for the next RDB transfer, so the# server waits a delay in order to let more replicas arrive.# 这一点很重要,因为一旦传输开始,就不可能为达到的新正本提供服务,新正本将排队# 期待下一次RDB传输,因而服务器会期待一个提早,以便让更多正本达到。# The delay is specified in seconds, and by default is 5 seconds. To disable# it entirely just set it to 0 seconds and the transfer will start ASAP.# 提早以秒为单位指定,默认为5秒。要齐全禁用它,只需将其设置为0秒,传输将尽快开始。repl-diskless-sync-delay 5# -----------------------------------------------------------------------------# WARNING: RDB diskless load is experimental. Since in this setup the replica# does not immediately store an RDB on disk, it may cause data loss during# failovers. RDB diskless load + Redis modules not handling I/O reads may also# cause Redis to abort in case of I/O errors during the initial synchronization# stage with the master. Use only if your do what you are doing.# -----------------------------------------------------------------------------# RDB无盘加载是实验性的。因为在此设置中,复制正本不会立刻在磁盘上存储RDB,# 因而在故障转移期间可能会导致数据失落。RDB无盘加载+不解决I/O读取# 的Redis模块也可能导致Redis在与主机的初始同步阶段呈现I/O谬误时停止。# 只在你确定想做的时才应用。# Replica can load the RDB it reads from the replication link directly from the# socket, or store the RDB to a file and read that file after it was completely# recived from the master.# Replica能够间接从socket加载它从复制链接读取的RDB,或者将RDB存储到一个文件中,# 并在齐全从主服务器接管到该文件之后读取该文件。# In many cases the disk is slower than the network, and storing and loading# the RDB file may increase replication time (and even increase the master's# Copy on Write memory and salve buffers).# 在许多状况下,磁盘比网络慢,存储和加载RDB文件可能会减少复制工夫#(甚至会减少主机的“写入时拷贝”内存和缓冲区)。# However, parsing the RDB file directly from the socket may mean that we have# to flush the contents of the current database before the full rdb was# received. For this reason we have the following options:# 然而,间接从套接字解析RDB文件可能意味着咱们必须在收到残缺的RDB之前刷# 新以后数据库的内容。为此,咱们有以下抉择:# "disabled" - Don't use diskless load (store the rdb file to the disk first)# "on-empty-db" - Use diskless load only when it is completely safe.# "swapdb" - Keep a copy of the current db contents in RAM while parsing# the data directly from the socket. note that this requires# sufficient memory, if you don't have it, you risk an OOM kill.repl-diskless-load disabled# Replicas send PINGs to server in a predefined interval. It's possible to# change this interval with the repl_ping_replica_period option. The default# value is 10 seconds.# 正本以预约义的工夫距离向服务器发送ping。能够应用# repl_ping_replica_period选项更改此距离。默认值为10秒。# repl-ping-replica-period 10# The following option sets the replication timeout for:## 1) Bulk transfer I/O during SYNC, from the point of view of replica.# 2) Master timeout from the point of view of replicas (data, pings).# 3) Replica timeout from the point of view of masters (REPLCONF ACK pings).## It is important to make sure that this value is greater than the value# specified for repl-ping-replica-period otherwise a timeout will be detected# every time there is low traffic between the master and the replica.## repl-timeout 60# Disable TCP_NODELAY on the replica socket after SYNC?## If you select "yes" Redis will use a smaller number of TCP packets and# less bandwidth to send data to replicas. But this can add a delay for# the data to appear on the replica side, up to 40 milliseconds with# Linux kernels using a default configuration.## If you select "no" the delay for data to appear on the replica side will# be reduced but more bandwidth will be used for replication.## By default we optimize for low latency, but in very high traffic conditions# or when the master and replicas are many hops away, turning this to "yes" may# be a good idea.repl-disable-tcp-nodelay no# Set the replication backlog size. The backlog is a buffer that accumulates# replica data when replicas are disconnected for some time, so that when a# replica wants to reconnect again, often a full resync is not needed, but a# partial resync is enough, just passing the portion of data the replica# missed while disconnected.## The bigger the replication backlog, the longer the time the replica can be# disconnected and later be able to perform a partial resynchronization.## The backlog is only allocated once there is at least a replica connected.## repl-backlog-size 1mb# After a master has no longer connected replicas for some time, the backlog# will be freed. The following option configures the amount of seconds that# need to elapse, starting from the time the last replica disconnected, for# the backlog buffer to be freed.## Note that replicas never free the backlog for timeout, since they may be# promoted to masters later, and should be able to correctly "partially# resynchronize" with the replicas: hence they should always accumulate backlog.## A value of 0 means to never release the backlog.## repl-backlog-ttl 3600# The replica priority is an integer number published by Redis in the INFO# output. It is used by Redis Sentinel in order to select a replica to promote# into a master if the master is no longer working correctly.## A replica with a low priority number is considered better for promotion, so# for instance if there are three replicas with priority 10, 100, 25 Sentinel# will pick the one with priority 10, that is the lowest.## However a special priority of 0 marks the replica as not able to perform the# role of master, so a replica with priority of 0 will never be selected by# Redis Sentinel for promotion.## By default the priority is 100.replica-priority 100# It is possible for a master to stop accepting writes if there are less than# N replicas connected, having a lag less or equal than M seconds.## The N replicas need to be in "online" state.## The lag in seconds, that must be <= the specified value, is calculated from# the last ping received from the replica, that is usually sent every second.## This option does not GUARANTEE that N replicas will accept the write, but# will limit the window of exposure for lost writes in case not enough replicas# are available, to the specified number of seconds.## For example to require at least 3 replicas with a lag <= 10 seconds use:## min-replicas-to-write 3# min-replicas-max-lag 10## Setting one or the other to 0 disables the feature.## By default min-replicas-to-write is set to 0 (feature disabled) and# min-replicas-max-lag is set to 10.# A Redis master is able to list the address and port of the attached# replicas in different ways. For example the "INFO replication" section# offers this information, which is used, among other tools, by# Redis Sentinel in order to discover replica instances.# Another place where this info is available is in the output of the# "ROLE" command of a master.## The listed IP and address normally reported by a replica is obtained# in the following way:## IP: The address is auto detected by checking the peer address# of the socket used by the replica to connect with the master.## Port: The port is communicated by the replica during the replication# handshake, and is normally the port that the replica is using to# listen for connections.## However when port forwarding or Network Address Translation (NAT) is# used, the replica may be actually reachable via different IP and port# pairs. The following two options can be used by a replica in order to# report to its master a specific set of IP and port, so that both INFO# and ROLE will report those values.## There is no need to use both the options if you need to override just# the port or the IP address.## replica-announce-ip 5.5.5.5# replica-announce-port 1234########################## SECURITY ############################# Warning: since Redis is pretty fast an outside user can try up to# 1 million passwords per second against a modern box. This means that you# should use very strong passwords, otherwise they will be very easy to break.# Note that because the password is really a shared secret between the client# and the server, and should not be memorized by any human, the password# can be easily a long string from /dev/urandom or whatever, so by using a# long and unguessable password no brute force attack will be possible.# Redis ACL users are defined in the following format:## user <username> ... acl rules ...## For example:## user worker +@list +@connection ~jobs:* on >ffa9203c493aa99## The special username "default" is used for new connections. If this user# has the "nopass" rule, then new connections will be immediately authenticated# as the "default" user without the need of any password provided via the# AUTH command. Otherwise if the "default" user is not flagged with "nopass"# the connections will start in not authenticated state, and will require# AUTH (or the HELLO command AUTH option) in order to be authenticated and# start to work.## The ACL rules that describe what an user can do are the following:## on Enable the user: it is possible to authenticate as this user.# off Disable the user: it's no longer possible to authenticate# with this user, however the already authenticated connections# will still work.# +<command> Allow the execution of that command# -<command> Disallow the execution of that command# +@<category> Allow the execution of all the commands in such category# with valid categories are like @admin, @set, @sortedset, ...# and so forth, see the full list in the server.c file where# the Redis command table is described and defined.# The special category @all means all the commands, but currently# present in the server, and that will be loaded in the future# via modules.# +<command>|subcommand Allow a specific subcommand of an otherwise# disabled command. Note that this form is not# allowed as negative like -DEBUG|SEGFAULT, but# only additive starting with "+".# allcommands Alias for +@all. Note that it implies the ability to execute# all the future commands loaded via the modules system.# nocommands Alias for -@all.# ~<pattern> Add a pattern of keys that can be mentioned as part of# commands. For instance ~* allows all the keys. The pattern# is a glob-style pattern like the one of KEYS.# It is possible to specify multiple patterns.# allkeys Alias for ~*# resetkeys Flush the list of allowed keys patterns.# ><password> Add this passowrd to the list of valid password for the user.# For example >mypass will add "mypass" to the list.# This directive clears the "nopass" flag (see later).# <<password> Remove this password from the list of valid passwords.# nopass All the set passwords of the user are removed, and the user# is flagged as requiring no password: it means that every# password will work against this user. If this directive is# used for the default user, every new connection will be# immediately authenticated with the default user without# any explicit AUTH command required. Note that the "resetpass"# directive will clear this condition.# resetpass Flush the list of allowed passwords. Moreover removes the# "nopass" status. After "resetpass" the user has no associated# passwords and there is no way to authenticate without adding# some password (or setting it as "nopass" later).# reset Performs the following actions: resetpass, resetkeys, off,# -@all. The user returns to the same state it has immediately# after its creation.## ACL rules can be specified in any order: for instance you can start with# passwords, then flags, or key patterns. However note that the additive# and subtractive rules will CHANGE MEANING depending on the ordering.# For instance see the following example:## user alice on +@all -DEBUG ~* >somepassword## This will allow "alice" to use all the commands with the exception of the# DEBUG command, since +@all added all the commands to the set of the commands# alice can use, and later DEBUG was removed. However if we invert the order# of two ACL rules the result will be different:## user alice on -DEBUG +@all ~* >somepassword## Now DEBUG was removed when alice had yet no commands in the set of allowed# commands, later all the commands are added, so the user will be able to# execute everything.## Basically ACL rules are processed left-to-right.## For more information about ACL configuration please refer to# the Redis web site at https://redis.io/topics/acl# ACL LOG## The ACL Log tracks failed commands and authentication events associated# with ACLs. The ACL Log is useful to troubleshoot failed commands blocked # by ACLs. The ACL Log is stored in memory. You can reclaim memory with # ACL LOG RESET. Define the maximum entry length of the ACL Log below.acllog-max-len 128# Using an external ACL file## Instead of configuring users here in this file, it is possible to use# a stand-alone file just listing users. The two methods cannot be mixed:# if you configure users here and at the same time you activate the exteranl# ACL file, the server will refuse to start.## The format of the external ACL user file is exactly the same as the# format that is used inside redis.conf to describe users.## aclfile /etc/redis/users.acl# IMPORTANT NOTE: starting with Redis 6 "requirepass" is just a compatiblity# layer on top of the new ACL system. The option effect will be just setting# the password for the default user. Clients will still authenticate using# AUTH <password> as usually, or more explicitly with AUTH default <password># if they follow the new protocol: both will work.## requirepass foobared# Command renaming (DEPRECATED).## ------------------------------------------------------------------------# WARNING: avoid using this option if possible. Instead use ACLs to remove# commands from the default user, and put them only in some admin user you# create for administrative purposes.# ------------------------------------------------------------------------## It is possible to change the name of dangerous commands in a shared# environment. For instance the CONFIG command may be renamed into something# hard to guess so that it will still be available for internal-use tools# but not available for general clients.## Example:## rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52## It is also possible to completely kill a command by renaming it into# an empty string:## rename-command CONFIG ""## Please note that changing the name of commands that are logged into the# AOF file or transmitted to replicas may cause problems.################################### CLIENTS ##################################### Set the max number of connected clients at the same time. By default# this limit is set to 10000 clients, however if the Redis server is not# able to configure the process file limit to allow for the specified limit# the max number of allowed clients is set to the current file limit# minus 32 (as Redis reserves a few file descriptors for internal uses).# 设置同时连贯的客户端的最大数量。默认状况下,此限度设置为10000个客户端,# 然而如果Redis服务器无奈配置过程文件限度以容许指定的限度,则容许的最大客户端# 数将设置为以后文件限度减去32(因为Redis保留了一些文件描述符供外部应用)。# Once the limit is reached Redis will close all the new connections sending# an error 'max number of clients reached'.# 一旦达到限度,Redis将敞开所有新连贯,并发送谬误“max number of clients reached”。# IMPORTANT: When Redis Cluster is used, the max number of connections is also# shared with the cluster bus: every node in the cluster will use two# connections, one incoming and another outgoing. It is important to size the# limit accordingly in case of very large clusters.# 当应用Redis集群时,最大连接数也与集群总线共享:集群中的每个节点将应用两个连贯,# 一个传入,另一个传出。在十分大的簇的状况下,相应地调整限度的大小是很重要的。# maxclients 10000################### MEMORY MANAGEMENT ######################### Set a memory usage limit to the specified amount of bytes.# When the memory limit is reached Redis will try to remove keys# according to the eviction policy selected (see maxmemory-policy).## If Redis can't remove keys according to the policy, or if the policy is# set to 'noeviction', Redis will start to reply with errors to commands# that would use more memory, like SET, LPUSH, and so on, and will continue# to reply to read-only commands like GET.# 将内存应用限度设置为指定的字节数。当达到内存限度时,Redis将依据所选的逐出# 策略删除密钥(请参阅maxmemory策略)。如果Redis无奈依据策略删除密钥,# 或者如果策略设置为“noeviction”,Redis将开始对应用更多内存的命令(如set、# LPUSH等)进行谬误应答,并持续回复GET等只读命令。# This option is usually useful when using Redis as an LRU or LFU cache, or to# set a hard memory limit for an instance (using the 'noeviction' policy).# 当将Redis用作LRU或LFU缓存时,或者设置实例的硬内存限度(应用“noeviction”策略)# 时,此选项通常很有用。# WARNING: If you have replicas attached to an instance with maxmemory on,# the size of the output buffers needed to feed the replicas are subtracted# from the used memory count, so that network problems / resyncs will# not trigger a loop where keys are evicted, and in turn the output# buffer of replicas is full with DELs of keys evicted triggering the deletion# of more keys, and so forth until the database is completely emptied.# 如果将正本附加到启用了maxmemory的实例,则将从已用内存计数中减去提供正本所需# 的输入缓冲区的大小,这样网络问题/从新同步将不会触发一个循环,# 在循环中退出密钥,而正本的输入缓冲区将充斥被发出的密钥的增量,# 从而触发删除操作直到数据库齐全清空。# In short... if you have replicas attached it is suggested that you set a lower# limit for maxmemory so that there is some free RAM on the system for replica# output buffers (but this is not needed if the policy is 'noeviction').## maxmemory <bytes># MAXMEMORY POLICY: how Redis will select what to remove when maxmemory# is reached. You can select one from the following behaviors:# 当达到maxmemory时,Redis将如何抉择要删除的内容。# volatile-lru -> Evict using approximated LRU, only keys with an expire set.# 对设置了过期工夫的KEY,应用LRU淘汰策略# allkeys-lru -> Evict any key using approximated LRU. 所有KEY都采纳LRU淘汰策略# volatile-lfu -> Evict using approximated LFU, only keys with an expire set.# 对设置了过期工夫的KEY,应用LFU淘汰策略# allkeys-lfu -> Evict any key using approximated LFU. 所有KEY都采纳LFU淘汰策略# volatile-random -> Remove a random key having an expire set.# 对设置了有效期的KEY,随机删除一个KEY# allkeys-random -> Remove a random key, any key. 随机删除# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)# 删除靠近过期工夫的KEY# noeviction -> Don't evict anything, just return an error on write operations.# 不淘汰数据,对写操作返回谬误# LRU means Least Recently Used# LFU means Least Frequently Used## Both LRU, LFU and volatile-ttl are implemented using approximated# randomized algorithms.## Note: with any of the above policies, Redis will return an error on write# operations, when there are no suitable keys for eviction.# 应用以上任何一种策略,当没有适合的密钥进行逐出时,Redis将在写操作时返回谬误# At the date of writing these commands are: set setnx setex append# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby# getset mset msetnx exec sort## The default is:## maxmemory-policy noeviction# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated# algorithms (in order to save memory), so you can tune it for speed or# accuracy. For default Redis will check five keys and pick the one that was# used less recently, you can change the sample size using the following# configuration directive.# LRU、LFU和minimal TTL算法不是准确算法,而是近似算法(为了节俭内存),# 因而您能够依据速度或精度对其进行调整。默认状况下Redis将查看五个键并抉择# 最近应用较少的键,能够应用以下配置指令更改样本大小。# The default of 5 produces good enough results. 10 Approximates very closely# true LRU but costs more CPU. 3 is faster but not very accurate.# 默认值为5会产生足够好的后果。10靠近实在的LRU,但占用更多的CPU。3更快,但不是很精确。# maxmemory-samples 5# Starting from Redis 5, by default a replica will ignore its maxmemory setting# (unless it is promoted to master after a failover or manually). It means# that the eviction of keys will be just handled by the master, sending the# DEL commands to the replica as keys evict in the master side.# 默认状况下,复制正本将疏忽其maxmemory设置(除非在故障转移后或手动将其降级为master)。# 这意味着密钥的发出将由主服务器解决,将DEL命令作为主机端的密钥发出发送到正本。# This behavior ensures that masters and replicas stay consistent, and is usually# what you want, however if your replica is writable, or you want the replica# to have a different memory setting, and you are sure all the writes performed# to the replica are idempotent, then you may change this default (but be sure# to understand what you are doing).# 此行为可确保主正本和正本保持一致,并且通常是您想要的,然而,如果您的复制正本是可写的,# 或者您心愿复制正本具备不同的内存设置,并且您确定对正本执行# 的所有写操作都是幂等的,则能够更改此默认值(但肯定要理解您正在做什么)。# Note that since the replica by default does not evict, it may end using more# memory than the one set via maxmemory (there are certain buffers that may# be larger on the replica, or data structures may sometimes take more memory# and so forth). So make sure you monitor your replicas and make sure they# have enough memory to never hit a real out-of-memory condition before the# master hits the configured maxmemory setting.# 请留神,因为复制正本在默认状况下不会逐出,因而它可能会应用比通过maxmemory设置的# 内存更多的内存(正本上有一些缓冲区可能更大,或者数据结构有时可能占用更多内存等等)。# 因而,请确保您监督您的正本,并确保它们有足够的内存,在主机# 命中配置的maxmemory设置之前,它们不会呈现内存不足的状况。# replica-ignore-maxmemory yes# Redis reclaims expired keys in two ways: upon access when those keys are# found to be expired, and also in background, in what is called the# "active expire key". The key space is slowly and interactively scanned# looking for expired keys to reclaim, so that it is possible to free memory# of keys that are expired and will never be accessed again in a short time.# Redis通过两种形式回收过期的密钥:当发现这些密钥过期时在拜访时,以及在后盾,即所# 谓的“流动过期密钥”。密钥空间被迟缓地交互扫描,寻找过期的密钥以回收,这样就能够# 开释过期密钥的内存,而这些密钥在短时间内将永远不会被拜访。# The default effort of the expire cycle will try to avoid having more than# ten percent of expired keys still in memory, and will try to avoid consuming# more than 25% of total memory and to add latency to the system. However# it is possible to increase the expire "effort" that is normally set to# "1", to a greater value, up to the value "10". At its maximum value the# system will use more CPU, longer cycles (and technically may introduce# more latency), and will tollerate less already expired keys still present# in the system. It's a tradeoff betweeen memory, CPU and latecy.# expire循环的默认工作将尽量避免超过10%的过期密钥仍在内存中,并将尽量避免耗费超过25%的# 总内存,并减少零碎的提早。然而,可将设置为“1”的expire “effort”减少到更大的值,直到值“10”。# 在其最大值时,零碎将应用更多的CPU、更长的周期(从技术上讲可能会引入更多的提早),# 并且可能接受较少的已过期密钥# active-expire-effort 1############################# LAZY FREEING ############################### Redis has two primitives to delete keys. One is called DEL and is a blocking# deletion of the object. It means that the server stops processing new commands# in order to reclaim all the memory associated with an object in a synchronous# way. If the key deleted is associated with a small object, the time needed# in order to execute the DEL command is very small and comparable to most other# O(1) or O(log_N) commands in Redis. However if the key is associated with an# aggregated value containing millions of elements, the server can block for# a long time (even seconds) in order to complete the operation.# Redis有两种形式来删除密钥。一种叫做DEL,是对对象的阻塞性删除。这意味着服务器进行# 解决新命令,以便以同步形式回收与对象关联的所有内存。如果删除的密钥与一个小对象关联,# 则执行DEL命令所需的工夫十分小,与Redis中大多数其余O(1)或O(log_N)命令相似。# 然而,如果密钥与蕴含数百万个元素的值相关联,则服务器会进行比拟长的工夫以实现删除操作# For the above reasons Redis also offers non blocking deletion primitives# such as UNLINK (non blocking DEL) and the ASYNC option of FLUSHALL and# FLUSHDB commands, in order to reclaim memory in background. Those commands# are executed in constant time. Another thread will incrementally free the# object in the background as fast as possible.# 基于以上起因,Redis还提供了UNLINK(non-blocking DEL)等非阻塞删除原语,# 以及FLUSHALL和FLUSHDB命令的异步选项,以便在后盾回收内存。这些命令在固定# 工夫内执行。另一个线程将以最快的速度增量开释后盾的对象。# DEL, UNLINK and ASYNC option of FLUSHALL and FLUSHDB are user-controlled.# It's up to the design of the application to understand when it is a good# idea to use one or the other. However the Redis server sometimes has to# delete keys or flush the whole database as a side effect of other operations.# Specifically Redis deletes objects independently of a user call in the# following scenarios:# FLUSHALL,FLUSHDB,DEL,UNLINK和ASYNC选项由用户管制。这取决于应用程序的# 设计来了解怎么做比拟好。然而,因为某些操作,Redis服务器有时不得不删除密钥或# 刷新整个数据库。具体来说,在以下状况下,Redis会独立于用户调用删除对象:# 1) On eviction, because of the maxmemory and maxmemory policy configurations,# in order to make room for new data, without going over the specified# memory limit.# 因为maxmemory和maxmemory策略配置,以便为新数据留出空间,而不超过指定的内存限度。# 2) Because of expire: when a key with an associated time to live (see the# EXPIRE command) must be deleted from memory.# 因为expire:必须从内存中删除具备相干生存工夫的密钥# 3) Because of a side effect of a command that stores data on a key that may# already exist. For example the RENAME command may delete the old key# content when it is replaced with another one. Similarly SUNIONSTORE# or SORT with STORE option may delete existing keys. The SET command# itself removes any old content of the specified key in order to replace# it with the specified string.# 因为命令的副作用是将数据存储在可能曾经存在的键上。例如,重命名命令可能会# 删除旧的密钥内容,当它被另一个替换时。相似地,SUNIONSTORE或SORT with # STORE选项可能会删除现有的密钥。SET命令自身删除指定键的任何旧内容,# 以便用指定的字符串替换它。# 4) During replication, when a replica performs a full resynchronization with# its master, the content of the whole database is removed in order to# load the RDB file just transferred.# 在复制过程中,当正本与其主正本执行齐全从新同步时,整个数据库的内容将被删除,# 以便加载刚刚传输的RDB文件。# In all the above cases the default is to delete objects in a blocking way,# like if DEL was called. However you can configure each case specifically# in order to instead release memory in a non-blocking way like if UNLINK# was called, using the following configuration directives.# 在上述所有状况下,默认状况是以阻塞形式删除对象,就像调用DEL一样。然而,# 您能够具体地配置每种状况,以便应用以下配置指令以非阻塞形式开释内存,就像调用UNLINK一样。lazyfree-lazy-eviction nolazyfree-lazy-expire nolazyfree-lazy-server-del noreplica-lazy-flush no# It is also possible, for the case when to replace the user code DEL calls# with UNLINK calls is not easy, to modify the default behavior of the DEL# command to act exactly like UNLINK, using the following configuration# directive:# 在用UNLINK调用替换用户代码DEL调用并不容易的状况下,还能够应用以下配置# 指令批改DEL命令的默认行为,使其与UNLINK完全相同:lazyfree-lazy-user-del no######################### THREADED I/O ############################## Redis is mostly single threaded, however there are certain threaded# operations such as UNLINK, slow I/O accesses and other things that are# performed on side threads.# Redis次要是单线程的,然而也有一些线程操作,比方UNLINK、迟缓的I/O拜访# 以及其余线程上执行的操作。# Now it is also possible to handle Redis clients socket reads and writes# in different I/O threads. Since especially writing is so slow, normally# Redis users use pipelining in order to speedup the Redis performances per# core, and spawn multiple instances in order to scale more. Using I/O# threads it is possible to easily speedup two times Redis without resorting# to pipelining nor sharding of the instance.# 当初还能够在不同的I/O线程中解决Redis客户端的套接字读写。因为编速度比较慢,# 通常Redis用户应用管道来减速每核的Redis性能,并生成多个实例以扩大更多。应用I/O线程,# 能够轻松地将Redis的速度进步两倍,而无需依赖于管道或实例的分片。# By default threading is disabled, we suggest enabling it only in machines# that have at least 4 or more cores, leaving at least one spare core.# Using more than 8 threads is unlikely to help much. We also recommend using# threaded I/O only if you actually have performance problems, with Redis# instances being able to use a quite big percentage of CPU time, otherwise# there is no point in using this feature.# 默认状况下,线程被禁用,咱们倡议只在至多有4个或更多内核的计算机中启用它,# 并至多保留一个备用内核。应用超过8个线程不大可能有多大帮忙。咱们还倡议仅当# 您理论存在性能问题时才应用线程I/O,因为Redis实例能够占用相当大比例的CPU工夫,# 否则应用此性能没有任何意义。# So for instance if you have a four cores boxes, try to use 2 or 3 I/O# threads, if you have a 8 cores, try to use 6 threads. In order to# enable I/O threads use the following configuration directive:# 例如,如果你有一个4核的CPU,尝试应用2或3个I/O线程,如果你有一个8核,# 尝试应用6个线程。要启用I/O线程,请应用以下配置指令:# io-threads 4## Setting io-threads to 1 will just use the main thread as usually.# When I/O threads are enabled, we only use threads for writes, that is# to thread the write(2) syscall and transfer the client buffers to the# socket. However it is also possible to enable threading of reads and# protocol parsing using the following configuration directive, by setting# it to yes:# 将io线程设置为1只会像平时一样应用主线程。当启用I/O线程时,咱们只应用线程进行写入,# 即线程write(2)零碎调用并将客户机缓冲区传输到套接字。然而,也能够应用以下配置指令# 启用读取线程和协定解析,办法是将其设置为yes# io-threads-do-reads no## Usually threading reads doesn't help much. 通常线程读取没有多大帮忙。## NOTE 1: This configuration directive cannot be changed at runtime via# CONFIG SET. Aso this feature currently does not work when SSL is# enabled.# 无奈在运行时通过配置集更改此配置指令。# NOTE 2: If you want to test the Redis speedup using redis-benchmark, make# sure you also run the benchmark itself in threaded mode, using the# --threads option to match the number of Redis theads, otherwise you'll not# be able to notice the improvements.###################### APPEND ONLY MODE ######################## By default Redis asynchronously dumps the dataset on disk. This mode is# good enough in many applications, but an issue with the Redis process or# a power outage may result into a few minutes of writes lost (depending on# the configured save points).# 默认状况下,Redis异步地将数据集转储到磁盘上。这种模式在许多利用中曾经足够好了,# 然而Redis过程的问题或断电可能会导致几分钟的写操作失落(取决于配置的保留点)。# The Append Only File is an alternative persistence mode that provides# much better durability. For instance using the default data fsync policy# (see later in the config file) Redis can lose just one second of writes in a# dramatic event like a server power outage, or a single write if something# wrong with the Redis process itself happens, but the operating system is# still running correctly.# AOF是另一种持久性模式,它提供了更好的持久性。例如,如果应用默认的数据# fsync策略(请参阅配置文件前面的局部),Redis在服务器断电等戏剧性事件中可能只会# 失落一秒钟的写入操作,或者如果Redis过程自身产生了问题,但操作系统仍在失常运行,# 则只会失落一次写入操作。# AOF and RDB persistence can be enabled at the same time without problems.# If the AOF is enabled on startup Redis will load the AOF, that is the file# with the better durability guarantees.# AOF和RDB持久性能够同时启用而不会呈现问题。如果启动时启用了AOF,Redis将加载AOF,# 即具备更好的持久性保障的文件。# Please check http://redis.io/topics/persistence for more information.appendonly no# The name of the append only file (default: "appendonly.aof") AOF文件名appendfilename "appendonly.aof"# The fsync() call tells the Operating System to actually write data on disk# instead of waiting for more data in the output buffer. Some OS will really flush# data on disk, some other OS will just try to do it ASAP.# fsync() 调用通知操作系统在磁盘上理论写入数据,而不是期待输入缓冲区中的更多数据。# 有些操作系统会在磁盘上刷新数据,而有些操作系统则会尽快刷新# Redis supports three different modes:## no: don't fsync, just let the OS flush the data when it wants. Faster. 等操作系统刷新缓存到磁盘# always: fsync after every write to the append only log. Slow, Safest. 每次写操作都刷新# everysec: fsync only one time every second. Compromise. 每秒刷新## The default is "everysec", as that's usually the right compromise between# speed and data safety. It's up to you to understand if you can relax this to# "no" that will let the operating system flush the output buffer when# it wants, for better performances (but if you can live with the idea of# some data loss consider the default persistence mode that's snapshotting),# or on the contrary, use "always" that's very slow but a bit safer than# everysec.# 默认值是“everysec”,因为这通常是速度和数据安全之间的正确折衷。为了更新好的性能,# 能够设置为"no",或者恰恰相反,应用“always”,它十分慢,但比everysec平安一些。# More details please check the following article:# http://antirez.com/post/redis-persistence-demystified.html## If unsure, use "everysec".# appendfsync alwaysappendfsync everysec# appendfsync no# When the AOF fsync policy is set to always or everysec, and a background# saving process (a background save or AOF log background rewriting) is# performing a lot of I/O against the disk, in some Linux configurations# Redis may block too long on the fsync() call. Note that there is no fix for# this currently, as even performing fsync in a different thread will block# our synchronous write(2) call.# 当AOF fsync策略设置为always或everysec,后盾保留过程(后盾保留或AOF日志后盾重写)# 正在对磁盘执行大量I/O时,在某些Linux配置中,Redis可能会在fsync() 调用上阻塞太长时间。# 留神,目前没对此进行修复,因为即便在不同的线程中执行fsync也会阻止咱们的同步write调用。# In order to mitigate this problem it's possible to use the following option# that will prevent fsync() from being called in the main process while a# BGSAVE or BGREWRITEAOF is in progress.## This means that while another child is saving, the durability of Redis is# the same as "appendfsync none". In practical terms, this means that it is# possible to lose up to 30 seconds of log in the worst scenario (with the# default Linux settings).## If you have latency problems turn this to "yes". Otherwise leave it as# "no" that is the safest pick from the point of view of durability.# 如果您有提早问题,请将此选项设置为“是”。否则,将其保留为“否”,从耐用性的角度来看,# 这是最平安的抉择。no-appendfsync-on-rewrite no# Automatic rewrite of the append only file.# Redis is able to automatically rewrite the log file implicitly calling# BGREWRITEAOF when the AOF log size grows by the specified percentage.# Redis可能在AOF日志大小按指定的百分比增长时主动重写日志文件,并隐式调用BGREWRITEAOF。# This is how it works: Redis remembers the size of the AOF file after the# latest rewrite (if no rewrite has happened since the restart, the size of# the AOF at startup is used).# 它是这样工作的:Redis在最近一次重写之后记住AOF文件的大小(如果重新启动后没有重写,# 则应用启动时AOF的大小)。# This base size is compared to the current size. If the current size is# bigger than the specified percentage, the rewrite is triggered. Also# you need to specify a minimal size for the AOF file to be rewritten, this# is useful to avoid rewriting the AOF file even if the percentage increase# is reached but it is still pretty small.# 将此根本大小与以后大小进行比拟。如果以后大小大于指定的百分比,则会触发重写。# 此外,您还须要为要重写的AOF文件指定最小大小,这对于防止重写AOF文件十分有用,# 即便达到了百分比减少,但它依然很小。# Specify a percentage of zero in order to disable the automatic AOF# rewrite feature.auto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb# An AOF file may be found to be truncated at the end during the Redis# startup process, when the AOF data gets loaded back into memory.# This may happen when the system where Redis is running# crashes, especially when an ext4 filesystem is mounted without the# data=ordered option (however this can't happen when Redis itself# crashes or aborts but the operating system still works correctly).# 在Redis启动过程中,当AOF数据加载回内存时,可能会发现AOF文件在开端被截断。# 当运行Redis的零碎解体时,尤其是在没有data=ordered选项的状况下挂载ext4文件系统时,# 可能会产生这种状况(然而,当Redis自身解体或停止,但操作系统依然失常工作时,# 这种状况就不会产生)。# Redis can either exit with an error when this happens, or load as much# data as possible (the default now) and start if the AOF file is found# to be truncated at the end. The following option controls this behavior.# Redis能够在产生这种状况时退出,或者尽可能多地加载数据(默认当初),# 如果发现AOF文件在结尾被截断。以下选项管制此行为。# If aof-load-truncated is set to yes, a truncated AOF file is loaded and# the Redis server starts emitting a log to inform the user of the event.# Otherwise if the option is set to no, the server aborts with an error# and refuses to start. When the option is set to no, the user requires# to fix the AOF file using the "redis-check-aof" utility before to restart# the server.# 如果aof-load-truncated设置为yes,则加载一个截断的aof文件,Redis服务器则记录日志来告诉用户。# 如果该选项设置为“否”,则服务器会因谬误而停止并回绝启动。当该选项设置为no时,# 用户须要在重新启动服务器之前应用“redis-check-aof”实用程序修复AOF文件# Note that if the AOF file will be found to be corrupted in the middle# the server will still exit with an error. This option only applies when# Redis will try to read more data from the AOF file but not enough bytes# will be found.# 请留神,如果发现AOF文件在两头被损坏,服务器仍将退出并返回一个谬误。# 此选项仅实用于Redis将尝试从AOF文件读取更多数据,但找不到足够字节的状况。aof-load-truncated yes# When rewriting the AOF file, Redis is able to use an RDB preamble in the# AOF file for faster rewrites and recoveries. When this option is turned# on the rewritten AOF file is composed of two different stanzas:# 在重写AOF文件时,Redis可能在AOF文件中应用RDB前导码以放慢重写和复原。# [RDB file][AOF tail]## When loading Redis recognizes that the AOF file starts with the "REDIS"# string and loads the prefixed RDB file, and continues loading the AOF# tail.aof-use-rdb-preamble yes######################## LUA SCRIPTING ############################ Max execution time of a Lua script in milliseconds.## If the maximum execution time is reached Redis will log that a script is# still in execution after the maximum allowed time and will start to# reply to queries with an error.## When a long running script exceeds the maximum execution time only the# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be# used to stop a script that did not yet called write commands. The second# is the only way to shut down the server in the case a write command was# already issued by the script but the user doesn't want to wait for the natural# termination of the script.## Set it to 0 or a negative value for unlimited execution without warnings.lua-time-limit 5000########################### REDIS CLUSTER ############################ Normal Redis instances can't be part of a Redis Cluster; only nodes that are# started as cluster nodes can. In order to start a Redis instance as a# cluster node enable the cluster support uncommenting the following:# 一般的Redis实例不能是Redis集群的一部分;只有作为集群节点启动的节点才能够。# 为了将Redis实例作为群集节点启动,请启用群集反对勾销正文以下内容:# cluster-enabled yes# Every cluster node has a cluster configuration file. This file is not# intended to be edited by hand. It is created and updated by Redis nodes.# Every Redis Cluster node requires a different cluster configuration file.# Make sure that instances running in the same system do not have# overlapping cluster configuration file names.# 每个群集节点都有一个群集配置文件。此文件不可手动编辑。它由Redis节点创立和更新。# 每个Redis集群节点都须要不同的集群配置文件。确保在同一零碎中运行的实例没有重叠的# 群集配置文件名。# cluster-config-file nodes-6379.conf# Cluster node timeout is the amount of milliseconds a node must be unreachable# for it to be considered in failure state.# Most other internal time limits are multiple of the node timeout.# Cluster node timeout是节点必须无法访问能力被视为处于故障状态的毫秒数。# 大其余少数工夫限度是节点超时的倍数。# cluster-node-timeout 15000# A replica of a failing master will avoid to start a failover if its data# looks too old.# 如果数据太旧,集群中的不可用master的slave节点会防止成为备用master# There is no simple way for a replica to actually have an exact measure of# its "data age", so the following two checks are performed:# 对于复制正本来说,没有一种简略的办法来理论精确测量其“数据期限# 1) If there are multiple replicas able to failover, they exchange messages# in order to try to give an advantage to the replica with the best# replication offset (more data from the master processed).# Replicas will try to get their rank by offset, and apply to the start# of the failover a delay proportional to their rank.# 如果有多个复制正本可能进行故障转移,# 2) Every single replica computes the time of the last interaction with# its master. This can be the last ping or command received (if the master# is still in the "connected" state), or the time that elapsed since the# disconnection with the master (if the replication link is currently down).# If the last interaction is too old, the replica will not try to failover# at all.## The point "2" can be tuned by user. Specifically a replica will not perform# the failover if, since the last interaction with the master, the time# elapsed is greater than:## (node-timeout * replica-validity-factor) + repl-ping-replica-period## So for example if node-timeout is 30 seconds, and the replica-validity-factor# is 10, and assuming a default repl-ping-replica-period of 10 seconds, the# replica will not try to failover if it was not able to talk with the master# for longer than 310 seconds.## A large replica-validity-factor may allow replicas with too old data to failover# a master, while a too small value may prevent the cluster from being able to# elect a replica at all.## For maximum availability, it is possible to set the replica-validity-factor# to a value of 0, which means, that replicas will always try to failover the# master regardless of the last time they interacted with the master.# (However they'll always try to apply a delay proportional to their# offset rank).# 为了达到最大限度的高可用性,能够设置为0,即slave不论和master失联多久都能够晋升为master# Zero is the only value able to guarantee that when all the partitions heal# the cluster will always be able to continue.# # cluster-replica-validity-factor 10# Cluster replicas are able to migrate to orphaned masters, that are masters# that are left without working replicas. This improves the cluster ability# to resist to failures as otherwise an orphaned master can't be failed over# in case of failure if it has no working replicas.## Replicas migrate to orphaned masters only if there are still at least a# given number of other working replicas for their old master. This number# is the "migration barrier". A migration barrier of 1 means that a replica# will migrate only if there is at least 1 other working replica for its master# and so forth. It usually reflects the number of replicas you want for every# master in your cluster.## Default is 1 (replicas migrate only if their masters remain with at least# one replica). To disable migration just set it to a very large value.# A value of 0 can be set but is useful only for debugging and dangerous# in production.## cluster-migration-barrier 1# By default Redis Cluster nodes stop accepting queries if they detect there# is at least an hash slot uncovered (no available node is serving it).# This way if the cluster is partially down (for example a range of hash slots# are no longer covered) all the cluster becomes, eventually, unavailable.# It automatically returns available as soon as all the slots are covered again.# 默认状况下如果redis集群如果检测到至多有1个hash slot不可用,集群将进行查问数据。# 如果所有slot复原则集群主动复原。# However sometimes you want the subset of the cluster which is working,# to continue to accept queries for the part of the key space that is still# covered. In order to do so, just set the cluster-require-full-coverage# option to no.# 如果须要集群局部可用状况下仍可提供查问服务,设置为no。# cluster-require-full-coverage yes# This option, when set to yes, prevents replicas from trying to failover its# master during master failures. However the master can still perform a# manual failover, if forced to do so.# 选项设置为yes时,会阻止replicas尝试对其master在主故障期间进行故障转移# 然而,master依然能够执行手动故障转移,如果强制这样做的话。# This is useful in different scenarios, especially in the case of multiple# data center operations, where we want one side to never be promoted if not# in the case of a total DC failure.## cluster-replica-no-failover no# This option, when set to yes, allows nodes to serve read traffic while the# the cluster is in a down state, as long as it believes it owns the slots. ## This is useful for two cases. The first case is for when an application # doesn't require consistency of data during node failures or network partitions.# One example of this is a cache, where as long as the node has the data it# should be able to serve it. ## The second use case is for configurations that don't meet the recommended # three shards but want to enable cluster mode and scale later. A # master outage in a 1 or 2 shard configuration causes a read/write outage to the# entire cluster without this option set, with it set there is only a write outage.# Without a quorum of masters, slot ownership will not change automatically. ## cluster-allow-reads-when-down no# In order to setup your cluster make sure to read the documentation# available at http://redis.io web site.########################## CLUSTER DOCKER/NAT support ######################### In certain deployments, Redis Cluster nodes address discovery fails, because# addresses are NAT-ted or because ports are forwarded (the typical case is# Docker and other containers).## In order to make Redis Cluster working in such environments, a static# configuration where each node knows its public address is needed. The# following two options are used for this scope, and are:## * cluster-announce-ip# * cluster-announce-port# * cluster-announce-bus-port## Each instruct the node about its address, client port, and cluster message# bus port. The information is then published in the header of the bus packets# so that other nodes will be able to correctly map the address of the node# publishing the information.## If the above options are not used, the normal Redis Cluster auto-detection# will be used instead.## Note that when remapped, the bus port may not be at the fixed offset of# clients port + 10000, so you can specify any port and bus-port depending# on how they get remapped. If the bus-port is not set, a fixed offset of# 10000 will be used as usually.## Example:## cluster-announce-ip 10.1.1.5# cluster-announce-port 6379# cluster-announce-bus-port 6380################################## SLOW LOG #################################### The Redis Slow Log is a system to log queries that exceeded a specified# execution time. The execution time does not include the I/O operations# like talking with the client, sending the reply and so forth,# but just the time needed to actually execute the command (this is the only# stage of command execution where the thread is blocked and can not serve# other requests in the meantime).## You can configure the slow log with two parameters: one tells Redis# what is the execution time, in microseconds, to exceed in order for the# command to get logged, and the other parameter is the length of the# slow log. When a new command is logged the oldest one is removed from the# queue of logged commands.# The following time is expressed in microseconds, so 1000000 is equivalent# to one second. Note that a negative number disables the slow log, while# a value of zero forces the logging of every command.slowlog-log-slower-than 10000# There is no limit to this length. Just be aware that it will consume memory.# You can reclaim memory used by the slow log with SLOWLOG RESET.slowlog-max-len 128################################ LATENCY MONITOR ############################### The Redis latency monitoring subsystem samples different operations# at runtime in order to collect data related to possible sources of# latency of a Redis instance.## Via the LATENCY command this information is available to the user that can# print graphs and obtain reports.## The system only logs operations that were performed in a time equal or# greater than the amount of milliseconds specified via the# latency-monitor-threshold configuration directive. When its value is set# to zero, the latency monitor is turned off.## By default latency monitoring is disabled since it is mostly not needed# if you don't have latency issues, and collecting data has a performance# impact, that while very small, can be measured under big load. Latency# monitoring can easily be enabled at runtime using the command# "CONFIG SET latency-monitor-threshold <milliseconds>" if needed.latency-monitor-threshold 0############################### ADVANCED CONFIG ################################ Hashes are encoded using a memory efficient data structure when they have a# small number of entries, and the biggest entry does not exceed a given# threshold. These thresholds can be configured using the following directives.hash-max-ziplist-entries 512hash-max-ziplist-value 64# Lists are also encoded in a special way to save a lot of space.# The number of entries allowed per internal list node can be specified# as a fixed maximum size or a maximum number of elements.# For a fixed maximum size, use -5 through -1, meaning:# -5: max size: 64 Kb <-- not recommended for normal workloads# -4: max size: 32 Kb <-- not recommended# -3: max size: 16 Kb <-- probably not recommended# -2: max size: 8 Kb <-- good# -1: max size: 4 Kb <-- good# Positive numbers mean store up to _exactly_ that number of elements# per list node.# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size),# but if your use case is unique, adjust the settings as necessary.list-max-ziplist-size -2# Lists may also be compressed.# Compress depth is the number of quicklist ziplist nodes from *each* side of# the list to *exclude* from compression. The head and tail of the list# are always uncompressed for fast push/pop operations. Settings are:# 0: disable all list compression# 1: depth 1 means "don't start compressing until after 1 node into the list,# going from either the head or tail"# So: [head]->node->node->...->node->[tail]# [head], [tail] will always be uncompressed; inner nodes will compress.# 2: [head]->[next]->node->node->...->node->[prev]->[tail]# 2 here means: don't compress head or head->next or tail->prev or tail,# but compress all nodes between them.# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail]# etc.list-compress-depth 0# Sets have a special encoding in just one case: when a set is composed# of just strings that happen to be integers in radix 10 in the range# of 64 bit signed integers.# The following configuration setting sets the limit in the size of the# set in order to use this special memory saving encoding.set-max-intset-entries 512# Similarly to hashes and lists, sorted sets are also specially encoded in# order to save a lot of space. This encoding is only used when the length and# elements of a sorted set are below the following limits:zset-max-ziplist-entries 128zset-max-ziplist-value 64# HyperLogLog sparse representation bytes limit. The limit includes the# 16 bytes header. When an HyperLogLog using the sparse representation crosses# this limit, it is converted into the dense representation.## A value greater than 16000 is totally useless, since at that point the# dense representation is more memory efficient.## The suggested value is ~ 3000 in order to have the benefits of# the space efficient encoding without slowing down too much PFADD,# which is O(N) with the sparse encoding. The value can be raised to# ~ 10000 when CPU is not a concern, but space is, and the data set is# composed of many HyperLogLogs with cardinality in the 0 - 15000 range.hll-sparse-max-bytes 3000# Streams macro node max size / items. The stream data structure is a radix# tree of big nodes that encode multiple items inside. Using this configuration# it is possible to configure how big a single node can be in bytes, and the# maximum number of items it may contain before switching to a new node when# appending new stream entries. If any of the following settings are set to# zero, the limit is ignored, so for instance it is possible to set just a# max entires limit by setting max-bytes to 0 and max-entries to the desired# value.stream-node-max-bytes 4096stream-node-max-entries 100# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in# order to help rehashing the main Redis hash table (the one mapping top-level# keys to values). The hash table implementation Redis uses (see dict.c)# performs a lazy rehashing: the more operation you run into a hash table# that is rehashing, the more rehashing "steps" are performed, so if the# server is idle the rehashing is never complete and some more memory is used# by the hash table.## The default is to use this millisecond 10 times every second in order to# actively rehash the main dictionaries, freeing memory when possible.## If unsure:# use "activerehashing no" if you have hard latency requirements and it is# not a good thing in your environment that Redis can reply from time to time# to queries with 2 milliseconds delay.## use "activerehashing yes" if you don't have such hard requirements but# want to free memory asap when possible.activerehashing yes# The client output buffer limits can be used to force disconnection of clients# that are not reading data from the server fast enough for some reason (a# common reason is that a Pub/Sub client can't consume messages as fast as the# publisher can produce them).## The limit can be set differently for the three different classes of clients:## normal -> normal clients including MONITOR clients# replica -> replica clients# pubsub -> clients subscribed to at least one pubsub channel or pattern## The syntax of every client-output-buffer-limit directive is the following:## client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>## A client is immediately disconnected once the hard limit is reached, or if# the soft limit is reached and remains reached for the specified number of# seconds (continuously).# So for instance if the hard limit is 32 megabytes and the soft limit is# 16 megabytes / 10 seconds, the client will get disconnected immediately# if the size of the output buffers reach 32 megabytes, but will also get# disconnected if the client reaches 16 megabytes and continuously overcomes# the limit for 10 seconds.## By default normal clients are not limited because they don't receive data# without asking (in a push way), but just after a request, so only# asynchronous clients may create a scenario where data is requested faster# than it can read.## Instead there is a default limit for pubsub and replica clients, since# subscribers and replicas receive data in a push fashion.## Both the hard or the soft limit can be disabled by setting them to zero.client-output-buffer-limit normal 0 0 0client-output-buffer-limit replica 256mb 64mb 60client-output-buffer-limit pubsub 32mb 8mb 60# Client query buffers accumulate new commands. They are limited to a fixed# amount by default in order to avoid that a protocol desynchronization (for# instance due to a bug in the client) will lead to unbound memory usage in# the query buffer. However you can configure it here if you have very special# needs, such us huge multi/exec requests or alike.## client-query-buffer-limit 1gb# In the Redis protocol, bulk requests, that are, elements representing single# strings, are normally limited ot 512 mb. However you can change this limit# here.## proto-max-bulk-len 512mb# Redis calls an internal function to perform many background tasks, like# closing connections of clients in timeout, purging expired keys that are# never requested, and so forth.## Not all tasks are performed with the same frequency, but Redis checks for# tasks to perform according to the specified "hz" value.## By default "hz" is set to 10. Raising the value will use more CPU when# Redis is idle, but at the same time will make Redis more responsive when# there are many keys expiring at the same time, and timeouts may be# handled with more precision.## The range is between 1 and 500, however a value over 100 is usually not# a good idea. Most users should use the default of 10 and raise this up to# 100 only in environments where very low latency is required.hz 10# Normally it is useful to have an HZ value which is proportional to the# number of clients connected. This is useful in order, for instance, to# avoid too many clients are processed for each background task invocation# in order to avoid latency spikes.## Since the default HZ value by default is conservatively set to 10, Redis# offers, and enables by default, the ability to use an adaptive HZ value# which will temporary raise when there are many connected clients.## When dynamic HZ is enabled, the actual configured HZ will be used# as a baseline, but multiples of the configured HZ value will be actually# used as needed once more clients are connected. In this way an idle# instance will use very little CPU time while a busy instance will be# more responsive.dynamic-hz yes# When a child rewrites the AOF file, if the following option is enabled# the file will be fsync-ed every 32 MB of data generated. This is useful# in order to commit the file to the disk more incrementally and avoid# big latency spikes.aof-rewrite-incremental-fsync yes# When redis saves RDB file, if the following option is enabled# the file will be fsync-ed every 32 MB of data generated. This is useful# in order to commit the file to the disk more incrementally and avoid# big latency spikes.rdb-save-incremental-fsync yes# Redis LFU eviction (see maxmemory setting) can be tuned. However it is a good# idea to start with the default settings and only change them after investigating# how to improve the performances and how the keys LFU change over time, which# is possible to inspect via the OBJECT FREQ command.## There are two tunable parameters in the Redis LFU implementation: the# counter logarithm factor and the counter decay time. It is important to# understand what the two parameters mean before changing them.## The LFU counter is just 8 bits per key, it's maximum value is 255, so Redis# uses a probabilistic increment with logarithmic behavior. Given the value# of the old counter, when a key is accessed, the counter is incremented in# this way:## 1. A random number R between 0 and 1 is extracted.# 2. A probability P is calculated as 1/(old_value*lfu_log_factor+1).# 3. The counter is incremented only if R < P.## The default lfu-log-factor is 10. This is a table of how the frequency# counter changes with a different number of accesses with different# logarithmic factors:## +--------+------------+------------+------------+------------+------------+# | factor | 100 hits | 1000 hits | 100K hits | 1M hits | 10M hits |# +--------+------------+------------+------------+------------+------------+# | 0 | 104 | 255 | 255 | 255 | 255 |# +--------+------------+------------+------------+------------+------------+# | 1 | 18 | 49 | 255 | 255 | 255 |# +--------+------------+------------+------------+------------+------------+# | 10 | 10 | 18 | 142 | 255 | 255 |# +--------+------------+------------+------------+------------+------------+# | 100 | 8 | 11 | 49 | 143 | 255 |# +--------+------------+------------+------------+------------+------------+## NOTE: The above table was obtained by running the following commands:## redis-benchmark -n 1000000 incr foo# redis-cli object freq foo## NOTE 2: The counter initial value is 5 in order to give new objects a chance# to accumulate hits.## The counter decay time is the time, in minutes, that must elapse in order# for the key counter to be divided by two (or decremented if it has a value# less <= 10).## The default value for the lfu-decay-time is 1. A Special value of 0 means to# decay the counter every time it happens to be scanned.## lfu-log-factor 10# lfu-decay-time 1########################### ACTIVE DEFRAGMENTATION ######################### What is active defragmentation?# -------------------------------## Active (online) defragmentation allows a Redis server to compact the# spaces left between small allocations and deallocations of data in memory,# thus allowing to reclaim back memory.## Fragmentation is a natural process that happens with every allocator (but# less so with Jemalloc, fortunately) and certain workloads. Normally a server# restart is needed in order to lower the fragmentation, or at least to flush# away all the data and create it again. However thanks to this feature# implemented by Oran Agra for Redis 4.0 this process can happen at runtime# in an "hot" way, while the server is running.## Basically when the fragmentation is over a certain level (see the# configuration options below) Redis will start to create new copies of the# values in contiguous memory regions by exploiting certain specific Jemalloc# features (in order to understand if an allocation is causing fragmentation# and to allocate it in a better place), and at the same time, will release the# old copies of the data. This process, repeated incrementally for all the keys# will cause the fragmentation to drop back to normal values.## Important things to understand:## 1. This feature is disabled by default, and only works if you compiled Redis# to use the copy of Jemalloc we ship with the source code of Redis.# This is the default with Linux builds.## 2. You never need to enable this feature if you don't have fragmentation# issues.## 3. Once you experience fragmentation, you can enable this feature when# needed with the command "CONFIG SET activedefrag yes".## The configuration parameters are able to fine tune the behavior of the# defragmentation process. If you are not sure about what they mean it is# a good idea to leave the defaults untouched.# Enabled active defragmentation# activedefrag no# Minimum amount of fragmentation waste to start active defrag# active-defrag-ignore-bytes 100mb# Minimum percentage of fragmentation to start active defrag# active-defrag-threshold-lower 10# Maximum percentage of fragmentation at which we use maximum effort# active-defrag-threshold-upper 100# Minimal effort for defrag in CPU percentage, to be used when the lower# threshold is reached# active-defrag-cycle-min 1# Maximal effort for defrag in CPU percentage, to be used when the upper# threshold is reached# active-defrag-cycle-max 25# Maximum number of set/hash/zset/list fields that will be processed from# the main dictionary scan# active-defrag-max-scan-fields 1000# Jemalloc background thread for purging will be enabled by defaultjemalloc-bg-thread yes# It is possible to pin different threads and processes of Redis to specific# CPUs in your system, in order to maximize the performances of the server.# This is useful both in order to pin different Redis threads in different# CPUs, but also in order to make sure that multiple Redis instances running# in the same host will be pinned to different CPUs.## Normally you can do this using the "taskset" command, however it is also# possible to this via Redis configuration directly, both in Linux and FreeBSD.## You can pin the server/IO threads, bio threads, aof rewrite child process, and# the bgsave child process. The syntax to specify the cpu list is the same as# the taskset command:## Set redis server/io threads to cpu affinity 0,2,4,6:# server_cpulist 0-7:2## Set bio threads to cpu affinity 1,3:# bio_cpulist 1,3## Set aof rewrite child process to cpu affinity 8,9,10,11:# aof_rewrite_cpulist 8-11## Set bgsave child process to cpu affinity 1,10,11# bgsave_cpulist 1,10-11

January 28, 2021 · 57 min · jiezi

关于redis:Redis-实战-09-实现任务队列消息拉取和文件分发

工作队列 P133通过将待执行工作的相干信息放入队列外面,并在之后对队列进行解决,能够推延执行那些耗时对操作,这种将工作交给工作处理器来执行对做法被称为工作队列 (task queue) 。 P133 先进先出队列 P133能够 Redis 的列表构造存储工作的相干信息,并应用 RPUSH 将待执行工作的相干信息推入列表右端,应用阻塞版本的弹出命令 BLPOP 从队列中弹出待执行工作的相干信息(因为工作处理器除了执行工作不须要执行其余工作)。 P134 发送工作 // 将工作参数推入指定工作对应的列表右端func SendTask(conn redis.Conn, queueName string, param string) (bool, error) { count, err := redis.Int(conn.Do("RPUSH", queueName, param)) if err != nil { return false, nil } // 只有胜利推入 1 个才算胜利发送 return count == 1, nil}执行工作 // 一直从工作对应的列表中获取工作参数,并执行工作func RunTask(conn redis.Conn, queueName string, taskHandler func(param string)) { for ; ; { result, err := redis.Strings(conn.Do("BLPOP", queueName, 10)) // 如果胜利获取工作信息,则执行工作 if err != nil && len(result) == 2 { taskHandler(result[1]) } }}以上代码是工作队列与 Redis 交互的通用版本,应用形式简略,只须要将入参信息序列化成字符串传入即可发送一个工作,提供一个解决工作的办法回调即可执行工作。 ...

January 28, 2021 · 3 min · jiezi

关于redis:慕课网20210129-Redis6直播笔记-下多线程哈希slot集群

<div style="margin: 0px auto; color: rgb(85, 85, 85); max-width: 23cm; padding: 1em;"><div style="margin: 0px; padding: 0px;"><div style="padding:8px;"><h3 style="font-family: &quot;PT Sans Narrow&quot;, sans-serif; font-weight: 700; line-height: 1.1em; color: rgb(133, 153, 0); font-size: 1.4em;">io多线程</h3> <p>以前的redis是单线程模型,其实就是多路复用机制,晓得多路复用的来一波6,咱们在架构师课程中讲过,那么netty也有,看过老师相干课程的也应该晓得。这里不多说了。</p> <p>Redis6开始有了IO读写多线程,只不过执行用户的命令和晚期版本也是一样的,都是单线程执行,所以线程平安。</p> <p>咱们先来看一下老版本的单线程:</p> <p>首先读取客户端的命令,读取后执行命令,而后回写给客户端,这个就是一组命令的执行,因为单线程平安,他们会一组一组的去进行执行。</p> <p>他们的读写命令以及执行命令都是在一个线程中执行的,这个线程在redis6中称之为主线程。</p> <p>在这里咱们能够回顾一下netty的reactor的线程模型,也就是多路复用。你能够把这个单线程了解为是一个人,他是酒吧会所的接待员,在门口接待了当前,而后还要领到外面去一个一个的款待他们。</p> <p>咱们能够关上redis.conf配置文件,看一下:默认状况下,是依照老版本的样子,如果要应用多线程,那么开启即可,这里的io-threads就是设置多线程的数量,开启多线程后,整体的性能要比单线程要更高。</p> <p>io-threads设置的数量最大不倡议超过8,晋升的空间不大。另外线程数和服务器的硬件配置也是有关系的。比方4核8g,那么倡议设置2或者3,如果8核倡议设置6或者7,因为肯定要预留,万事兜底万事保底,这一点和nginx的配置也是同样的情理。</p> <p>假如当初io-threads设置为4,那么他的模型就如下:</p> <p>那么在这里,读用户的命令以及执行命令都是在一个线程中执行的,而后写操作是多线程执行。在这里如果比作是一个银行的话,那么读操作相当于是门口的保安,给你测个体温,执行就是店里的大堂经理,会带你去取号,多个写操作就是窗口的办事人员。</p> <p>能够参考一下图:刚刚咱们举例是只有一个人在接待和款待,这个时候接待只有一个人,他只在门口把客人带进外面,外面会有专门的多个招待员来解决这些客人的申请。</p> <h3 style="font-family: &quot;PT Sans Narrow&quot;, sans-serif; font-weight: 700; line-height: 1.1em; color: rgb(133, 153, 0); font-size: 1.4em;">读操作能不能设置多线程呢?</h3> <p>如果想要读操作也变成多线程读的话,那么io-threads-do-reads能够开启,设置为yes就行。这个时候他的模型就是上面这张图:</p> <p>只不过官网阐明,这个多线程读开启的意义不大,不会帮忙很多的。这个时候,还是引入刚刚的例子,客人多了,生意好了,门口的接待员减少了,那么两边接待和款待都是多个员工在解决客人了。</p> <p>那么在这里阐明一点,多线程只针对数据的读写以及协定的解析。真正用户端的命令执行还是单线程,所以是线程平安的。</p> <h3 style="font-family: &quot;PT Sans Narrow&quot;, sans-serif; font-weight: 700; line-height: 1.1em; color: rgb(133, 153, 0); font-size: 1.4em;">Redis集群原理</h3> ...

January 28, 2021 · 2 min · jiezi

关于redis:Redis-实战-08-实现自动补全分布式锁和计数信号量

主动补全 P109主动补全在日常业务中随处可见,应该算一种最常见最通用的性能。理论业务场景必定要包含蕴含子串的状况,其实这在肯定水平上转换成了搜寻性能,即蕴含某个子串的串,且优先展现前缀匹配的串。如果仅蕴含前缀,那么能够应用 Trie 树,但在蕴含其余的状况下,应用数据库/ ES 自身自带查问就足够了。能够依照四种状况(准确匹配、前缀、后缀、蕴含(也可将后两种交融成蕴含)),别离查问后果,直至达到数据条数下限或者全副查问结束。但这种应用办法有毛病:查问次数多、难以分页。不过理论场景中须要补全的状况都只有第一页的数据即可。 主动补全最近联系人 P110需要: 记录最近分割过的 100 集体名,并反对对输出的串进行主动补全。 P110 数据量很小,所以能够在 Redis 中用列表保护最近联系人,而后在内存中进行过滤可主动补全的串。 步骤: P111 保护长度为 100 的最近联系人列表 如果指定的联系人已在列表中,则从列表中移除 (LREM)将指定的联系人增加到列表最后面 (LPUSH)如果增加实现后,列表长度超过 100 ,则对列表进行修剪,仅保留列表 后面的 100 个联系人 (LTRIM)获取整个最近联系人列表,在内存中依据四种状况进行过滤即可通讯录主动补全 P112需要: 有很多通讯录,每个通讯录中有几千个人(仅蕴含小写英文字母),尽量减少 Redis 传输给客户端的数据量,实现前缀主动补全。 P112 思路: 应用有序汇合存储人名,利用有序汇合的个性:当成员的分值雷同时,将依据成员字符串的二进制程序进行排序。如果要查找 abc 前缀的字符串,那么实际上就是查找介于 abbz... 之后和 abd 之前的字符串。所以问题转化为:如何找到第一个排在 abc 之前的元素的排名 和 第一个排在 abd 之前的元素的排名。咱们能够结构两个不在有序汇合中的字符串 (abb{, abc{) 辅助定位,因为 { 是排在 z 后第一个不实用的字符,这样能够保障这两个字符串不存在与有序汇合中,且满足转化后的问题的限度。 P113 综上: 通过将给定前缀的最初一个字符替换为第一个排在该字符前的字符,再再在开端拼接上左花括号,能够失去前缀的前驱 (predecessor) ,通过给前缀的开端拼接上左花括号,能够失去前缀的后继 (successor) 。 字符集:当解决的字符不仅仅限于 a~z 范畴,那么要解决好以下三个问题: P113 将所有字符转换为字节:应用 UTF-8 、 UTF-16 或者 UTF-32 字符编码(留神: UTF-16 和 UTF-32只有大端版本可用于上述办法)找出须要反对的字符范畴,确保所选范畴的后面和前面至多留有一个字符应用位于范畴前后的字符别离代替反引号 ` 和左花括号 {步骤: P114 ...

January 27, 2021 · 2 min · jiezi

关于redis:Redis如何实现分布式阻塞队列

1. Redis分布式锁实现原理分布式锁实质上要实现的指标就是在 Redis 外面占一个“茅坑”,当别的过程也要来占时,发现曾经有人蹲在那里了,就只好放弃或者稍后再试。占坑个别是应用 setnx(set if not exists) 指令,只容许被一个客户端占坑。先来先占, 用完了,再调用 del 指令开释茅坑。死锁问题:如果逻辑执行到两头出现异常了,可能会导致 del 指令没有被调用,这样就会陷入死锁,锁永远得不到开释, 解决这个问题咱们在拿到锁之后,再给锁加上一个过期工夫,比方 5s,这样即便两头出现异常也能够保障 5 秒之后锁会主动开释2. 一般非阻塞锁实现public class RedisLock { private Jedis jedis; public RedisLock(Jedis jedis) { this.jedis = jedis; } public boolean lock(String key) { return jedis.set(key, "", "nx", "ex", 5L) != null; } public void unlock(String key) { jedis.del(key); }}2.1 存在问题如果某一个过程没有拿到锁失去了false的后果那么次过程是否执行当前任务?显然对于个别状况来说咱们的工作都是必须执行的那么此时咱们就要思考该何时执行了,在传统的锁中咱们如果没有拿到锁线程就进入了阻塞状态那么此处咱们是否能够改良同样实现阻塞唤醒机制3. 分布式阻塞锁具体实现3.1 解决思路首先咱们革新lock锁,当不能创立key时就利用以后key阻塞以后线程当某一个线程开释锁时通过redis的pub/sub发送一个音讯音讯内容为key所有应用锁的利用监听lock通道的音讯,在收到音讯时通过key唤醒对应线程3.2具体实现package com.hgy.common.redis;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPubSub;import java.util.HashMap;public class RedisLock extends JedisPubSub { //是否曾经初始化监听 private static volatile boolean isListen = false; //每一个redis的key对应一个阻塞对象 private HashMap<String, Object> blockers = new HashMap<>(); private Jedis jedis; //以后取得锁的线程 private Thread curThread; public RedisLock(Jedis jedis) { this.jedis = jedis; //保障没一个利用只初始化一次监听 if (!isListen) { synchronized (RedisLock.class) { if (!isListen) { // 启动一个线程做音讯监听 new Thread(()->{ new Jedis("192.168.200.128", 6379).subscribe(this, "lock"); }).start(); isListen = true; } } } } public void lock(String key) throws InterruptedException { //循环判断是否可能创立key, 不能则间接wait开释CPU执行权 while (jedis.set(key, "", "nx", "ex", 20L) == null) { synchronized (key) { System.out.println(Thread.currentThread().getName() + "=======" + key); blockers.put(key, key); key.wait(); } } blockers.put(key, key); //可能胜利创立,获取锁胜利记录以后获取锁线程 curThread = Thread.currentThread(); } public void unlock(String key) { //判断是否为加锁的线程执行解锁, 不是则间接疏忽 if( curThread == Thread.currentThread()) { jedis.del(key); //删除key之后须要notifyAll所有的利用, 所以这里采纳发订阅音讯给所有的利用 jedis.publish("lock", key); } } /** * 所有利用接管到音讯后在以后利用中执行对应key的notifyAll办法 * @param channel * @param message */ @Override public void onMessage(String channel, String message) { Object lock = blockers.get(message); if(lock != null) { synchronized (lock) { lock.notifyAll(); } } }}4. 测试指标: 开启两个mian线程, 在第一个中首先暂停3秒而后打印1-100而后线程休眠5秒开释锁并打印最初的毫秒数; main1在执行的同时执行main2,在2中打印开始工夫;最初比对1和2的开始工夫即可验证 ...

January 27, 2021 · 2 min · jiezi

关于redis:Redis-核心篇唯快不破的秘密

天下文治,无坚不摧,唯快不破!学习一个技术,通常只接触了零散的技术点,没有在脑海里建设一个残缺的常识框架和架构体系,没有零碎观。这样会很吃力,而且会呈现一看如同本人会,过后就遗记,一脸懵逼。 跟着「码哥字节」一起吃透 Redis,深层次的把握 Redis 外围原理以及实战技巧。一起搭建一套残缺的常识框架,学会全局观去整顿整个常识体系。 零碎观其实是至关重要的,从某种程度上说,在解决问题时,领有了零碎观,就意味着你能有根据、有章法地定位和解决问题。 Redis 全景图全景图能够围绕两个纬度开展,别离是: 利用维度:缓存应用、集群使用、数据结构的奇妙应用 零碎维度:能够归类为三高 高性能:线程模型、网络 IO 模型、数据结构、长久化机制;高可用:主从复制、哨兵集群、Cluster 分片集群;高拓展:负载平衡Redis 系列篇章围绕如下思维导图开展,这次从 《Redis 唯快不破的机密》一起摸索 Redis 的外围知识点。 唯快不破的机密65 哥前段时间去面试 996 大厂,被问到「Redis 为什么快?」 65 哥:额,因为它是基于内存实现和单线程模型面试官:还有呢? 65 哥:没了呀。很多人仅仅只是晓得基于内存实现,其余外围的起因模凌两可。今日跟着「码哥字节」一起摸索真正快的起因,做一个唯快不破的真男人! Redis 为了高性能,从各方各面都进行了优化,下次小伙伴们面试的时候,面试官问 Redis 性能为什么如此高,可不能傻傻的只说单线程和内存存储了。 依据官网数据,Redis 的 QPS 能够达到约 100000(每秒申请数),有趣味的能够参考官网的基准程序测试《How fast is Redis?》,地址:https://redis.io/topics/benchmarks 横轴是连接数,纵轴是 QPS。此时,这张图反映了一个数量级,心愿大家在面试的时候能够正确的形容进去,不要问你的时候,你答复的数量级相差甚远! 齐全基于内存实现65 哥:这个我晓得,Redis 是基于内存的数据库,跟磁盘数据库相比,齐全吊打磁盘的速度,就像段誉的凌波微步。对于磁盘数据库来说,首先要将数据通过 IO 操作读取到内存里。没错,不管读写操作都是在内存上实现的,咱们别离比照下内存操作与磁盘操作的差别。 磁盘调用栈图 内存操作 内存间接由 CPU 管制,也就是 CPU 外部集成的内存控制器,所以说内存是间接与 CPU 对接,享受与 CPU 通信的最优带宽。 Redis 将数据存储在内存中,读写操作不会因为磁盘的 IO 速度限制,所以速度飞个别的感觉! 最初以一张图量化零碎的各种延时工夫(局部数据援用 Brendan Gregg) ...

January 27, 2021 · 4 min · jiezi

关于redis:原来大厂的Redis分布式锁都这么设计的

1 本地锁罕用的即 synchronize 或 Lock 等 JDK 自带的锁,只能锁住以后过程,仅实用于单体架构服务。 而在分布式多服务实例场景下必须应用分布式锁 2 分布式锁2.1 分布式锁的原理厕所占坑实践可同时去一个中央“占坑”: 占到,就执行逻辑否则期待,直到开释锁可通过自旋形式自旋 “占坑”能够去Redis、DB、任何所有服务都能拜访的中央。 2.2 分布式锁演进一阶段// 占分布式锁,去redis占坑Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", "111");if(lock) { //加锁胜利... 执行业务 Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb(); redisTemplate . delete( key: "lock");//fHßti return dataF romDb ;} else { // 加锁失败,重试。synchronized() // 休眠100ms重试 // 自旋 return getCatalogJsonFromDbwithRedisLock();}复制代码 问题场景setnx占好了坑,然而业务代码异样或程序在执行过程中宕机,即没有执行胜利删除锁逻辑,导致死锁解决方案:设置锁的主动过期,即便没有删除,会主动删除。 阶段二 // 1. 占分布式锁,去redis占坑Boolean lock = redisTemplate.opsForValue().setIfAbsent( "lock", "110")if(lock) { // 加锁胜利...执行业务 // 忽然断电 // 2. 设置过期工夫 redisTemplate.expire("lock", timeout: 30, TimeUnit.SECONDS) ; Map<String, List<Catelog2Vo>> dataFromDb = getDataFromDb(); //删除锁 redisTemplate. delete( key; "lock"); return dataFromDb;} else { // 加锁失败...重试。 synchronized () // 休眠100ms重试 // 自旋的形式 return getCatalogJsonF romDbWithRedisLock();}复制代码问题场景setnx设置好,正要去设置过期工夫,宕机,又死锁解决方案:设置过期工夫和占位必须是原子操作。redis反对应用setNxEx命令 ...

January 27, 2021 · 1 min · jiezi

关于redis:慕课网20210129-Redis6直播笔记-上acl客户端缓存多级缓存

慕课网2021-01-29 Redis直播笔记 - 上(acl/客户端缓存/多级缓存) redis6装置留神点 咱们课程里疏忽了,就不去装置了,仅仅只提供装置文档,redis6的装置其实和redis5装置差不多,只是须要留神gcc的版本须要进步,不然编译会出错。参考慕课网手记地址:https://www.imooc.com/article... acl权限策略根底概念 不晓得大家有没有听过acl,zookeeper中也有,acl就是access control list,权限管制列表,和平时接触的管理系统的权限是一样的,能够限度不同角色的操作权。 在redis6中,咱们能够设置不同的用户,对他们进行受权命令,管制可读可写,限度拜访缓存key的前缀等。这样能够更加进步redis6的数据安全性。因为是对于一些公司的生产库,能够让很多人去连贯查看,就特地有用。然而一般来说都是只有运维或者redis工程师能力拜访的。 大家想一想,晚期版本通过requirepass设置明码,这个不去设置,你的服务器很有可能被攻打,这个咱们架构班的同学有遇到过,被勒索比特币,或者成为肉鸡挖矿。所以这个明码必定要设置。 ACL 存储模式 acl的权限的存储模式能够配置到redis.conf中,也能够内部文件aclfile,我集体偏好后者,这也是官网举荐的形式。(因为aclfile文件产生批改只须要重载acl即可,而conf形式须要重启redis) 咱们能够间接在命令行中创立用户去权限,而后再把用户保留到conf或者aclfile中。命令如下: # 将ACL权限长久化到redis.confconfig rewrite # 将ACL权限长久化到users.aclacl save实操演练开启aclfile,指定门路 创立权限acl文件(留神:须要他前创立acl空文件,否则重启redis会报错) touch /usr/local/redis/users.acl 重启redis并且进入客户端查看过程 ./redis-cli shutdown./redis-server redis.conf./redis-cliauth default # 默认用户无明码或者 ./redis-cli # 能够间接进入ACL的应用查看acl命令帮忙(学习一个新货色,基本上他们都会有帮忙文档的。像在linux中,大多都是help,就有一大堆的命令提醒,前面还有英文的解释,这是最间接的学习形式)acl help置信凡是有一些教训的,这些其实都应该看得懂 1)ACL:命令参数,要以 ACL 结尾2)LOAD:从新加载acl文件,手动批改acl文件后,须要让redis服务从新加载,能力失效3)SAVE:保留以后用户权限配置到acl文件4)LIST:展现用户权限的详细信息5)USERS:展现所有用户名6)SETUSER:设置或者批改用户7)GETUSER:取得用户全新信息8)DELUSER:删除用户以及权限9)CAT:展现所有权限分类,不同的操作归类不同10)CAT <某分类名>:展现某分类具体蕴含哪些操作11)GENPASS:生成明码12)WHOAMI:以后登录者13)LOG:日志 默认没有配置的时候,会有一个default用户,on代表开启,off代表禁用。default为用户名,前面的内容为ACL规定形容,~* 示意所有key,+@all 示意所有命令。所以这个示意用户default开启状态,并且,没有明码而且能够拜访所有命令以及所有数据。 取得所有的用户名 以后登录用户是谁 查看命令的分类: acl cat:显示所有的命令类别 * 查某个类别下有哪些操作,就比方如下危险操作,这些命令都是危险的,对以后redis库可能会造成影响 创立用户当初咱们来创立一下用户 创立或者批改用户,用户名辨别大小写,然而不倡议把同样的用户名分为大小写不同的两个 # 新增默认所有权限的用户ACL SETUSER imooc on >123456 ~* +@all# 新增用户itzixi,明码123456,只能容许拜访order前缀的key,能够应用set和get和acl命令ACL SETUSER itzixi on >123456 ~order* +get +set +acl这个时候关上acl文件是空的,须要执行保留命令保留命令到aclfile ...

January 27, 2021 · 1 min · jiezi

关于redis:Redis持久化-AOF

长久化长久化(Persistence),即把内存中的数据保留到磁盘中。 长久化的实现形式快照式 在某个时刻把所有数据进行残缺备份。 例:MySQL 的 Dump 形式、Redis 的 RDB 形式。 日志式 把用户执行的所有写指令(增删改)备份到文件中,还原数据时只须要把备份的所有指令从新执行一遍即可。 例:MySQL 的 Binlog、Redis 的 AOF、Hbase 的 HLog。 AOF 简介在文章《Redis长久化 - RDB》中提到过,应用 RDB 做长久化,如果 Redis 意外宕机(例如电源中断),可能会失落上一次备份到宕机前这段时间的数据。 为了防止上述问题,能够应用另一种长久化实现形式:AOF 长久化。 配置 AOF 长久化之后,每当 Redis 执行一个扭转数据集的命令, 这个命令就会被追加到 AOF 文件的开端。当 Redis 从新启时,程序就能够通过从新执行 AOF 文件中的命令来达到重建数据集的目标。 AOF长久化的三种策略always 每次有新命令执行就刷新缓冲区,将命令追加到 AOF 文件,速度绝对其余策略慢、IO开销大,然而安全性十分高。 everysec(默认&举荐) 每秒刷新一次缓冲区,将命令追加到 AOF 文件,速度足够快并且在故障时只会失落 1 秒钟的数据。 no 不刷新缓冲区内容,由操作系统来决定什么时候同步数据。最快但也最不平安。 AOF 重写因为 AOF 的运作形式是一直地将命令追加到文件的开端, 所以随着写入命令的一直减少, AOF 文件的体积也会变得越来越大。然而很多命令的执行实际上会笼罩原有命令的后果(如自增 INCR),导致保留原有命令是多余的。 为此,Redis 能够在不打断服务客户端的状况下, 对 AOF 文件进行重建(rebuild)。手动执行 bgrewriteaof 命令, Redis 将生成一个新的 AOF 文件, 这个文件蕴含重建以后数据集所需的起码命令。 ...

January 26, 2021 · 1 min · jiezi

关于redis:Redis-实战-07-复制处理故障事务及性能优化

复制简介 P61关系型数据库通常会应用一个主服务器 (master) 向多个从服务器 (slave) 发送更新,并应用从服务器来解决所有读申请。 Redis 也采纳了同样的办法实现本人的复制个性,并将其用作扩大性能的一种伎俩。 P69 在接管到主服务器发送的数据初始正本 (initial copy of the data) 之后,客户端每次向主服务器进行写入时,从服务器都会实时地失去更新。 P69 复制 P62对于一个正在运行的 Redis 服务器,用户能够通过发送 SLAVEOF NO ONE 命令来让服务器终止复制操作,不再承受主服务器的数据更新;也能够通过发送 SLAVEOF host port 命令来让服务器开始复制一个新的主服务器。 P69 配置选项# 设置本机为指定服务器的从服务器## slaveof <master-host> <master-port># 当主服务器设置了密码保护时(用 requirepass 指定的明码)# 从服务器服务连贯主服务器须要设置相应的明码## masterauth <master-password># 当从服务器 与主服务器失去连贯 或者 正在进行复制 时# yes: 从服务器会持续响应客户端的申请(默认 yes)# no: 除了 INFO 和 SLAVOF 命令之外的任何申请都会# 返回一个谬误 "SYNC with master in progress"#slave-serve-stale-data yes# 从服务器每隔肯定工夫会向主服务器发送 ping# 默认 10 秒## repl-ping-slave-period 10# ping 回复 或 主服务器批量数据传输 超时时长# 默认 60 秒# 确保 repl-timeout 大于 repl-ping-slave-period## repl-timeout 60从服务器连贯主服务器时的步骤 P70步骤主服务器操作从服务器操作1(期待命令进入)连贯(或者重连)主服务器,发送 SYNC 命令2开始执行 BGSAVE ,并应用缓冲区记录 BGSAVE 之后执行所有写命令依据配置选项 (slave-serve-stale-data) 来决定是持续应用现有的数据(如果有的话)来解决客户端的命令申请,还是向客户端返回谬误3BGSAVE 执行结束,向从服务器发送快照文件,并在发送期间持续应用缓冲区记录被执行的写命令抛弃所有旧数据(如果有的话),开始载入主服务器发来的快照文件4快照文件发送结束,开始向从服务器发送存储在缓冲区外面的写命令实现对快照文件的解释操作,像平常一样开始接受命令申请5缓冲区存储的写命令发送结束;从当初开始,每执行一个写命令,就向从服务器发送雷同的写命令执行主服务器发来的所有存储在缓冲区外面的写命令;并从当初开始,承受并执行主服务器传来的每个写命令在理论中最好让主服务器只应用 50% ~ 65% 的内存,留下 30% ~ 45% 的内存用于执行 BGSAVE 命令和创立记录写命令的缓冲区。 P70 ...

January 26, 2021 · 2 min · jiezi

关于redis:有趣的Redis缓存被我写满了该怎么办

Redis是一个内存数据库,当Redis应用的内存超过物理内存的限度后,内存数据会和磁盘产生频繁的替换,替换会导致Redis性能急剧下降。所以在生产环境中咱们通过配置参数maxmemoey来限度应用的内存大小。 当理论应用的内存超过maxmemoey后,Redis提供了如下几种可选策略。 noeviction:写申请返回谬误 volatile-lru:应用lru算法删除设置了过期工夫的键值对volatile-lfu:应用lfu算法删除设置了过期工夫的键值对volatile-random:在设置了过期工夫的键值对中随机进行删除volatile-ttl:依据过期工夫的先后进行删除,越早过期的越先被删除 allkeys-lru:在所有键值对中,应用lru算法进行删除allkeys-lfu:在所有键值对中,应用lfu算法进行删除allkeys-random:所有键值对中随机删除 咱们来具体理解一下lru和lfu算法,这是2个常见的缓存淘汰算法。因为计算机缓存的容量是无限的,所以咱们要删除那些没用的数据,而这两种算法的区别就是断定没用的纬度不一样。 LRU算法 lru(Least recently used,最近起码应用)算法,即最近拜访的数据,后续很大概率还会被拜访到,即是有用的。而长时间未被拜访的数据,应该被淘汰 lru算法中数据会被放到一个链表中,链表的头节点为最近被拜访的数据,链表的尾节点为长时间没有被拜访的数据 lru算法的外围实现就是哈希表加双向链表。链表能够用来保护拜访元素的程序,而hash表能够帮咱们在O(1)工夫复杂度下拜访到元素。 至于为什么是双向链表呢?次要是要删除元素,所以要获取前继节点。数据结构图示如下 应用双向链表+HashMap 双向链表节点定义如下 public class ListNode<K, V> { K key; V value; ListNode pre; ListNode next; public ListNode() {} public ListNode(K key, V value) { this.key = key; this.value = value; } } 封装双向链表的罕用操作 public class DoubleList { private ListNode head; private ListNode tail; public DoubleList() { head = new ListNode(); tail = new ListNode(); head.next = tail; tail.pre = head; ...

January 26, 2021 · 3 min · jiezi

关于redis:Redis持久化-RDB

长久化长久化(Persistence),即把内存中的数据保留到磁盘中。 长久化的实现形式快照式 在某个时刻把所有数据进行残缺备份。 例:MySQL 的 Dump 形式、Redis 的 RDB 形式。 日志式 把用户执行的所有写指令(增删改)备份到文件中,还原数据时只须要把备份的所有指令从新执行一遍即可。 例:MySQL 的 Binlog、Redis 的 AOF、Hbase 的 HLog。 RDB简介默认状况下, Redis 将数据库快照保留在名为 dump.rdb 的二进制文件中。 当 Redis 须要保留 dump.rdb 文件时, 服务器执行以下操作: Redis 调用 forks 派生一个子过程。父过程和子过程同时存在。子过程将以后内存中的数据库快照写入到一个长期 RDB 文件中。当子过程实现对新 RDB 文件的写入后,Redis 用新 RDB 文件替换原来的 RDB 文件。当 Redis 须要复原数据时, Redis 程序能够通过载入 RDB 文件来还原数据库的状态。 RDB 的触发机制save命令 save 命令是一个同步操作命令,会占用 Redis 的主过程。若 Redis 数据十分多时,save 命令执行速度会十分慢,导致阻塞所有客户端的申请。 生产环境不倡议应用 save 命令,能够应用 bgsave 命令代替。 127.0.0.1:6379> saveOKbgsave命令 bgsave 命令是一个异步操作命令,Redis 应用 Linux 零碎的 fock() 生成一个子过程来将数据保留到磁盘,主过程能够持续为客户端提供服务。 ...

January 26, 2021 · 1 min · jiezi

关于redis:面试必问如何实现Redis分布式锁

摘要:明天咱们来聊聊分布式锁这块常识,具体的来看看Redis分布式锁的实现原理。Redis分布式锁的实现原理 一、写在后面 当初面试,个别都会聊聊分布式系统这块的货色。通常面试官都会从服务框架(Spring Cloud、Dubbo)聊起,一路聊到分布式事务、分布式锁、ZooKeeper等常识。 所以咱们这篇文章就来聊聊分布式锁这块常识,具体的来看看Redis分布式锁的实现原理。 说实话,如果在公司里落地生产环境用分布式锁的时候,肯定是会用开源类库的,比方Redis分布式锁,个别就是用Redisson框架就好了,十分的简便易用。 大家如果有趣味,能够去看看Redisson的官网,看看如何在我的项目中引入Redisson的依赖,而后基于Redis实现分布式锁的加锁与开释锁。 上面给大家看一段简略的应用代码片段,先直观的感受一下: 怎么样,下面那段代码,是不是感觉简略的不行! 此外,人家还反对redis单实例、redis哨兵、redis cluster、redis master-slave等各种部署架构,都能够给你完满实现。 二、Redisson实现Redis分布式锁的底层原理 好的,接下来就通过一张手绘图,给大家说说Redisson这个开源框架对Redis分布式锁的实现原理。 (1)加锁机制 咱们来看下面那张图,当初某个客户端要加锁。如果该客户端面对的是一个redis cluster集群,他首先会依据hash节点抉择一台机器。 这里留神,仅仅只是抉择一台机器!这点很要害! 紧接着,就会发送一段lua脚本到redis上,那段lua脚本如下所示: 为啥要用lua脚本呢? 因为一大坨简单的业务逻辑,能够通过封装在lua脚本中发送给redis,保障这段简单业务逻辑执行的原子性。 那么,这段lua脚本是什么意思呢? KEYS[1]代表的是你加锁的那个key,比如说: RLock lock = redisson.getLock("myLock"); 这里你本人设置了加锁的那个锁key就是“myLock”。 ARGV[1]代表的就是锁key的默认生存工夫,默认30秒。 ARGV[2]代表的是加锁的客户端的ID,相似于上面这样: 8743c9c0-0795-4907-87fd-6c719a6b4586:1 给大家解释一下,第一段if判断语句,就是用“exists myLock”命令判断一下,如果你要加锁的那个锁key不存在的话,你就进行加锁。 如何加锁呢?很简略,用上面的命令: hset myLock 8743c9c0-0795-4907-87fd-6c719a6b4586:1 1 通过这个命令设置一个hash数据结构,这行命令执行后,会呈现一个相似上面的数据结构: 上述就代表“8743c9c0-0795-4907-87fd-6c719a6b4586:1”这个客户端对“myLock”这个锁key实现了加锁。 接着会执行“pexpire myLock 30000”命令,设置myLock这个锁key的生存工夫是30秒。 好了,到此为止,ok,加锁实现了。 (2)锁互斥机制 那么在这个时候,如果客户端2来尝试加锁,执行了同样的一段lua脚本,会咋样呢? 很简略,第一个if判断会执行“exists myLock”,发现myLock这个锁key曾经存在了。 接着第二个if判断,判断一下,myLock锁key的hash数据结构中,是否蕴含客户端2的ID,然而显著不是的,因为那里蕴含的是客户端1的ID。 所以,客户端2会获取到pttl myLock返回的一个数字,这个数字代表了myLock这个锁key的残余生存工夫。比方还剩15000毫秒的生存工夫。 此时客户端2会进入一个while循环,不停的尝试加锁。 (3)watch dog主动延期机制 客户端1加锁的锁key默认生存工夫才30秒,如果超过了30秒,客户端1还想始终持有这把锁,怎么办呢? 简略!只有客户端1一旦加锁胜利,就会启动一个watch dog看门狗,他是一个后盾线程,会每隔10秒检查一下,如果客户端1还持有锁key,那么就会一直的缩短锁key的生存工夫。 (4)可重入加锁机制 那如果客户端1都曾经持有了这把锁了,后果可重入的加锁会怎么样呢? 比方上面这种代码: 这时咱们来剖析一下下面那段lua脚本。 第一个if判断必定不成立,“exists myLock”会显示锁key曾经存在了。 第二个if判断会成立,因为myLock的hash数据结构中蕴含的那个ID,就是客户端1的那个ID,也就是“8743c9c0-0795-4907-87fd-6c719a6b4586:1” 此时就会执行可重入加锁的逻辑,他会用: ...

January 26, 2021 · 1 min · jiezi

关于redis:Redis-实战-06-持久化选项

长久化选项简介 P61Redis 提供了两种不同的长久化办法来将数据存储到硬盘外面。 RDB(redis database):能够将某一时刻的所有数据都写入硬盘外面。(保留的是数据自身)AOF(append only file):会在执行命令时,将被执行的写命令复制到硬盘外面。(保留的是数据的变更记录)两种长久化办法既能够同时应用,又能够独自应用,在某些状况下甚至能够两种办法都不应用,具体抉择哪种长久化办法须要依据数据以及利用来决定。 快照长久化 P62配置选项# 长久化触发条件:seconds 秒内至多有 changes 个键被更改# save <seconds> <changes> # # 默认配置以下三个触发长久化的条件# 【注】正文掉所有 save 的配置,就不会开启快照长久化## 900 秒(15 分钟)内至多有 1 个键被更改# 300 秒(5 分钟)内至多有 10 个键被更改# 60 秒(1 分钟)内至多有 10000 个键被更改save 900 1save 300 10save 60 10000# 如果快照长久化开启# yes:后盾长久化操作失败时,Redis 就会进行承受更新操作(默认 yes)# no :后盾长久化操作失败时,Redis 依然能够持续失常工作stop-writes-on-bgsave-error yes# 在进行镜像备份时,是否进行压缩# yes:压缩,会有更多 cpu 耗费,工夫会更长(默认 yes)# no :不压缩,须要更多磁盘空间rdbcompression yes# 数据库文件的文件名dbfilename dump.rdb# 工作目录,数据库文件的地位# AOF(append only file)也会在此目录创立 dir ./如果新的快照文件创建实现之前,Redis 、 零碎或者硬件这三者之中的任意一个解体了,那么 Redis 将失落最近一次胜利创立快照之后写入的所有数据。快照长久化只实用于那些即便失落一部分数据也不会造成问题的程序,而不承受数据损失的程序能够思考应用 AOF 长久化。 P63 ...

January 25, 2021 · 2 min · jiezi

关于redis:Redis知识谱

Redis可基于内存亦可长久化的日志型、Key-Value数据库五种数据结构字符串(String)       与其它编程语言或其它键值存储提供的字符串十分类似,键(key)------值(value) (字符串格局),字符串领有一些操作命令,如:get set del 还有一些比方自增或自减操作等等。redis是应用C语言开发,但C中并没有字符串类型,只能应用指针或符数组的模式示意一个字符串,所以redis设计了一种简略动静字符串(SDS[Simple Dynamic String])作为底实现: 定义SDS对象,此对象中蕴含三个属性: len buf中曾经占有的长度(示意此字符串的理论长度)free buf中未应用的缓冲区长度buf[] 理论保留字符串数据的中央所以取字符串的长度的工夫复杂度为O(1),另,buf[]中仍然采纳了C语言的以0结尾能够间接应用C语言的局部规范C字符串库函数。 空间分配原则:当len小于IMB(1024*1024)时减少字符串调配空间大小为原来的2倍,当len大于等于1M时每次调配 额定多调配1M的空间。 由此能够得出以下个性: redis为字符调配空间的次数是小于等于字符串的长度N,而原C语言中的分配原则必为N。升高了调配次数进步了追加速度,代价就是多占用一些内存空间,且这些空间不会主动开释。二进制平安的高效的计算字符串长度(工夫复杂度为O(1))高效的追加字符串操作。列表(List)         redis对键表的构造反对使得它在键值存储的世界中自成一家,一个列表构造能够有序地存储多个字符串,领有例如:lpush lpop rpush rpop等等操作命令。在3.2版本之前,列表是应用ziplist和linkedlist实现的,在这些老版本中,当列表对象同时满足以下两个条件时,列表对象应用ziplist编码: 列表对象保留的所有字符串元素的长度都小于64字节列表对象保留的元素数量小于512个当有任一条件 不满足时将会进行一次转码,应用linkedlist。 而在3.2版本之后,从新引入了一个quicklist的数据结构,列表的底层都是由quicklist实现的,它联合了ziplist和linkedlist的长处。依照原文的解释这种数据结构是【A doubly linked list of ziplists】意思就是一个由ziplist组成的双向链表。那么这两种数据结构怎么样联合的呢? ziplist的构造          由表头和N个entry节点和压缩列表尾部标识符zlend组成的一个间断的内存块。而后通过一系列的编码规定,进步内存的利用率,次要用于存储整数和比拟短的字符串。能够看出在插入和删除元素的时候,都须要对内存进行一次扩大或缩减,还要进行局部数据的挪动操作,这样会造成更新效率低下的状况。 这篇文章对ziplist的构造讲的还是比拟具体的: https://blog.csdn.net/yellowriver007/article/details/79021049 linkedlist的构造         意思为一个双向链表,和一般的链表定义雷同,每个entry蕴含向前向后的指针,当插入或删除元素的时候,只须要对此元素前后指针操作即可。所以插入和删除效率很高。但查问的效率却是O(n)[n为元素的个数]。 理解了下面的这两种数据结构,咱们再来看看下面说的“ziplist组成的双向链表”是什么意思?实际上,它整体宏观上就是一个链表构造,只不过每个节点都是以压缩列表ziplist的构造保留着数据,而每个ziplist又能够蕴含多个entry。也能够说一个quicklist节点保留的是一片数据,而不是一个数据。总结: 整体上quicklist就是一个双向链表构造,和一般的链表操作一样,插入删除效率很高,但查问的效率却是O(n)。不过,这样的链表拜访两端的元素的工夫复杂度却是O(1)。所以,对list的操作少数都是poll和push。每个quicklist节点就是一个ziplist,具备压缩列表的个性。在redis.conf配置文件中,有两个参数能够优化列表: list-max-ziplist-size 示意每个quicklistNode的字节大小。默认为-2 示意8KBlist-compress-depth 示意quicklistNode节点是否要压缩。默认是0 示意不压缩 哈希(hash)        redis的散列能够存储多个键 值 对之间的映射,散列存储的值既能够是字符串又能够是数字值,并且用户同样能够对散列存储的数字值执行自增操作或者自减操作。散列能够看作是一个文档或关系数据库里的一行。hash底层的数据结构实现有两种: 一种是ziplist,下面曾经提到过。当存储的数据超过配置的阀值时就是转用hashtable的构造。这种转换比拟耗费性能,所以应该尽量避免这种转换操作。同时满足以下两个条件时才会应用这种构造: 当键的个数小于hash-max-ziplist-entries(默认512)当所有值都小于hash-max-ziplist-value(默认64)另一种就是hashtable。这种构造的工夫复杂度为O(1),然而会耗费比拟多的内存空间。汇合(Set)         redis的汇合和列表都能够存储多个字符串,它们之间的不同在于,列表能够存储多个雷同的字符串,而汇合则通过应用散列表(hashtable)来保障自已存储的每个字符串都是各不相同的(这些散列表只有键,但没有与键相关联的值),redis中的汇合是无序的。还可能存在另一种汇合,那就是intset,它是用于存储整数的有序汇合,外面寄存同一类型的整数。共有三种整数:int16_t、int32_t、int64_t。查找的工夫复杂度为O(logN),然而插入的时候,有可能会波及到降级(比方:原来是int16_t的汇合,当插入int32_t的整数的时候就会为每个元素降级为int32_t)这时候会对内存重新分配,所以此时的工夫复杂度就是O(N)级别的了。留神:intset只反对降级不反对降级操作。 intset在redis.conf中也有一个配置参数set-max-intset-entries默认值为512。示意如果entry的个数小于此值,则能够编码成REDIS_ENCODING_INTSET类型存储,节约内存。否则采纳dict的模式存储。 ...

January 25, 2021 · 2 min · jiezi

关于redis:Redis第五章节8种数据类型

目录一、Redis对key的操作二、五种数据类型 String类型List(汇合)Set(汇合)Hash(哈希)Zset(有序汇合)三、三种非凡数据类型 geospatial(地理位置)hyperloglog(长处:占用内存小)Bitmap(位图)一、Redis对key的操作判断key是否存在:exists key_name设置key的过期工夫:expire key_name [过期的工夫值](number类型)查看key的过期工夫:ttl key_name获取所有的key: keys *二、五种数据类型String(字符串)字符串类型操作: 设置值:set key_name value获取值:get key_name追加字符串,如果以后的key不存在就会创立一个新的key: append key_name value获取字符串长度:strlen key_name截取字符串:getrange key_name [start index] [end index]指定的字符串笼罩给定key所贮存的字符串值,笼罩的地位从偏移量 offset(数字类型) 开始:setrange key_name offset value为指定的key设置值及其过期工夫,如果key曾经存在,setex命令将会替换旧的值: setex key_name [expiration time] value先获取值再设置值:getset key_name value数字类型操作: number数字类型自增1:incr key_namenumber数字类型减1:decr key_name减少指定的值:incrby key_name [具体的值]number类型缩小指定的值:decrby key_name key_name [具体的值]number类型批量操作: 批量设置值:mset key_name1 value1 key_name2 value2 key_name3 value3批量获取值: 形式1: mget key_name1 key_name2 key_name3形式2:msetnx key_name1 key_name2 key_name3 //这个是原子性操作,要么全副胜利,要么全副失败。List(汇合)设置值: 右边:lpush key_name value左边:rpush key_name value获取值: 右边: lrange key_name [start index] [end index]lrange key_name 0 -1 获取所有的元素移除数据: ...

January 24, 2021 · 2 min · jiezi

关于redis:Redis-实战-05-Redis-其他命令简介

公布与订阅 P52Redis 实现了公布与订阅(publish/subscribe)模式,又称 pub/sub 模式(与设计模式中的观察者模式相似)。订阅者负责订阅频道,发送者负责向频道发送二进制字符串音讯。每当有音讯被发送至给定频道时,频道的所有订阅者都会接管到音讯。 公布与订阅命令 P52命令格局形容SUBSCRIBESUBSCRIBE channel [channel ...]订阅一个或多个频道UNSUBSCRIBEUNSUBSCRIBE [channel [channel ...]]退订一个或多个频道;没有指定频道,则退订全副频道PUBLISHPUBLISH channel message给指定频道发送音讯,返回接管到音讯的订阅者数量PSUBSCRIBEPSUBSCRIBE pattern [pattern ...]订阅一个或多个模式,与模式匹配的频道均会订阅PUNSUBSCRIBEPUNSUBSCRIBE [pattern [pattern ...]]退订一个或多个模式;没有指定模式,则退订全副模式相干演示代码如下: // 执行公布订阅相干操作(留神:pubSubConn 中的 Conn 对象不能是 conn 对象,即必须建设两个不同的连贯)func executePubSubOperation(pubSubConn redis.PubSubConn, conn redis.Conn) { // 监听频道音讯并输入 go func() { for ; ; { switch result := pubSubConn.Receive().(type) { case redis.Message: // byte 转 string resultMap := map[string]string { "Channel": result.Channel, "Pattern": result.Pattern, "Data": string(result.Data), } handleResult(resultMap, nil) case redis.Subscription: handleResult(result, nil) } } }() // 订阅两个频道(因为 Subscribe 内没有执行 Receive,所以只有 error,没有谬误时就输入 nil) // 订阅者收到相应的音讯订阅信息,别离输入 -> {subscribe channel_1 1} 和 {subscribe channel_2 2} handleResult(nil, pubSubConn.Subscribe("channel_1", "channel_2")) // 订阅两个模式,别离以 _1 和 g_2 为结尾的频道 (因为 PSubscribe 内没有执行 Receive,所以只有 error,没有谬误时就输入 nil) // 订阅者收到相应的音讯订阅信息,别离输入 -> {psubscribe *_1 3} 和 {psubscribe *g_2 4} handleResult(nil, pubSubConn.PSubscribe("*_1", "*g_2")) time.Sleep(time.Second) // 公布音讯到频道 channel_1,输入 -> 2,两个订阅者接管到音讯 // 订阅者别离输入 -> map[Channel:channel_1 Data:channel1 Pattern:] 和 map[Channel:channel_1 Data:channel1 Pattern:*_1] handleResult(conn.Do("PUBLISH", "channel_1", "channel1")) // 公布音讯到频道 channel_2,输入 -> 1,一个订阅者接管到音讯 // 订阅者输入 -> map[Channel:channel_2 Data:channel1 Pattern:] handleResult(conn.Do("PUBLISH", "channel_2", "channel1")) // 退订两个频道(因为 Subscribe 内没有执行 Receive,所以只有 error,没有谬误时就输入 nil) // 订阅者收到相应的音讯退订信息,别离输入 -> {unsubscribe channel_1 3} 和 {unsubscribe channel_2 2} handleResult(nil, pubSubConn.Unsubscribe("channel_1", "channel_2")) // 退订两个频道(因为 Subscribe 内没有执行 Receive,所以只有 error,没有谬误时就输入 nil) // 订阅者收到相应的音讯退订信息,别离输入 -> {punsubscribe *_1 1} 和 {punsubscribe *g_2 0} handleResult(nil, pubSubConn.PUnsubscribe("*_1", "*g_2")) time.Sleep(time.Second)}危险 P54稳定性:旧版 Redis 的客户端读取音讯不够快时,一直积压的音讯就会使 Redis 的缓冲区越来越大,可能导致 Redis 的速度变慢,甚至间接解体,也有使 Redis 可能被操作系统强制杀死。新版 Redis 会主动断开不合乎 client-output-buffer-limit pubsub 配置选项要求的客户端。可靠性:任何网络系统在执行操作时都有可能会遇上断线状况,而断线产生的连贯谬误通常会使得网络连接两端中的其中一端进行从新连贯。如果客户端在执行订阅操作的过程中断线,那么客户端将失落在断线期间发送的所有音讯。排序 P54SORT 命令能够对列表、汇合和有序汇合进行排序 ,能够将 SORT 命令看作使 SQL 中的 order by 子句。 P55 ...

January 24, 2021 · 4 min · jiezi