网站怎么做动态切图,网站标准规范建设,镇江大港信息港,wordpress轮播主题RedisExample
课程介绍
目标是提供一个高效、可靠的学习和实践Redis的环境。我们将通过搭建Redis集群、实现缓存数据的持久化存储、制定缓存数据的淘汰策略以及同步缓存数据等步骤来深入了解和学习Redis的特性和功能。通过这个项目#xff0c;你可以掌握Redis的核心概念和技…RedisExample
课程介绍
目标是提供一个高效、可靠的学习和实践Redis的环境。我们将通过搭建Redis集群、实现缓存数据的持久化存储、制定缓存数据的淘汰策略以及同步缓存数据等步骤来深入了解和学习Redis的特性和功能。通过这个项目你可以掌握Redis的核心概念和技术并能够熟练地将其应用到实际的开发工作中。无论你是初学者还是有一定经验的开发者都可以从这个项目中获得收获和成长。欢迎加入我们的行列一起学习Redis 源码地址 RedisExample: 目标是提供一个高效、可靠的学习和实践Redis的环境。我们将通过搭建Redis集群、实现缓存数据的持久化存储、制定缓存数据的淘汰策略以及同步缓存数据等步骤来深入了解和学习Redis的特性和功能。通过这个项目你可以掌握Redis的核心概念和技术并能够熟练地将其应用到实际的开发工作中。无论你是初学者还是有一定经验的开发者都可以从这个项目中获得收获和成长。欢迎加入我们的行列一起学习Redis (gitee.com)https://gitee.com/bseaworkspace/redis-example 第一章.Redis介绍
Redis 是一个开源BSD 许可的内存中的数据结构存储系统它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构如 字符串strings 散列hashes 列表lists 集合sets 有序集合sorted sets 与范围查询 bitmaps hyperloglogs 和 地理空间geospatial 索引半径查询。 Redis 内置了 复制replicationLUA 脚本Lua scripting LRU 驱动事件LRU eviction事务transactions 和不同级别的 磁盘持久化persistence 并通过 Redis 哨兵Sentinel和自动 分区Cluster提供高可用性high availability。
Redis Java 客户端
Jedis、Lettuce和Redisson介绍和区别
Jedis
Jedis是Redis的Java实现客户端提供了比较全面的Redis命令的支持。 使用阻塞的I/O方法调用同步程序流需要等到socket处理完I/O才能执行不支持异步操作。 Jedis客户端实例不是线程安全的需要通过连接池来使用Jedis。 适用场景需要全面支持Redis命令的场景。
Lettuce
Lettuce是高级Redis客户端用于线程安全同步、异步和响应使用支持集群、Sentinel、管道和编码器。 基于Netty框架的事件驱动的通信层其方法调用是异步的。Lettuce的API是线程安全的所以可以操作单个Lettuce连接来完成各种操作。 Lettuce能够支持redis4需要java8及以上。是基于netty实现的与redis进行同步和异步的通信。 适用场景需要高并发和线程安全性的场景。
Redisson
Redisson实现了分布式和可扩展的Java数据结构例如分布式锁、分布式集合等并可通过Redis支持延迟队列。 基于Netty框架的事件驱动的通信层其方法调用是异步的。Redisson的API是线程安全的所以可以操作单个Redisson连接来完成各种操作。 支持哨兵、集群、管道、自动重新连接和Redis数据模型等高级特性。 适用场景需要分布式和可扩展功能的场景。在选择时需要根据具体需求和场景进行选择。
第二章.Redis 安装
Windows 下安装
下载地址https://github.com/tporadowski/redis/releases。 双击 redis-server.exe Linux 源码安装
下载地址http://redis.io/download下载最新稳定版本。
本教程使用的最新文档版本为 2.8.17下载并安装
# wget http://download.redis.io/releases/redis-6.0.8.tar.gz
# tar -xzvf redis-6.0.8.tar.gz
# cd redis-6.0.8
# make
执行完 make 命令后redis-6.0.8 的 src 目录下会出现编译后的 redis 服务程序 redis-server还有用于测试的客户端程序 redis-cli
下面启动 redis 服务
# cd src
# ./redis-server
注意这种方式启动 redis 使用的是默认配置。也可以通过启动参数告诉 redis 使用指定配置文件使用下面命令启动。
# cd src
# ./redis-server ../redis.conf
redis.conf 是一个默认的配置文件。我们可以根据需要使用自己的配置文件。
启动 redis 服务进程后就可以使用测试客户端程序 redis-cli 和 redis 服务交互了。 比如
# cd src
# ./redis-cli
redis set foo bar
OK
redis get foo
bar
Ubuntu apt 命令安装 在 Ubuntu 系统安装 Redis 可以使用以下命令:
# sudo apt update
# sudo apt install redis-server
启动 Redis
# redis-server
查看 redis 是否启动
# redis-cli
以上命令将打开以下终端redis 127.0.0.1:6379
127.0.0.1 是本机 IP 6379 是 redis 服务端口。现在我们输入 PING 命令。redis 127.0.0.1:6379 ping
PONG
第三章. Redis的数据结构
Redis支持以下五种数据结构
String字符串最简单的类型可以理解为与Memcached一模一样的类型一个key对应一个value。List列表由若干个字符串元素组成的集合每个字符串元素都是按照插入顺序排序的。Set集合由不重复且无序的字符串元素组成的。Hash散列可以存储多个键值对之间的映射键的类型必须为字符串而值的类型既可以是字符串也可以是数字但是值必须是唯一的不可重复。Sorted Sets有序集合和散列类似主要区别是有序集合是按照值进行自动排序的。
第四章. Redis缓存特性
速度快读写性能 10W/s当然了和机器配置也有关系为什么快呢内存操作C语言实现离操作系统API更近单线程架构务必不要记错避免了多线程竞争带来的损耗。IO多路复用协议简单。支持持久化虽然是交互时是内存操作但提供数据落盘机制防止断电产生的数据丢失问题。支持主从复制多副本 Master-Slave 节点支持高可用 HA哨兵sentinel机制实现高可用保证节点故障自动发现和故障转移支持多客户端语言Java、Python、C等。
第五章. Redis使用场景
缓存数据库之前加缓存降低数据库读写压力排行榜按照热度排名、按照发布时间排名计数器播放数、浏览数社交网络赞、踩、粉丝、下拉刷新消息队列发布订阅
第六章. Redis客户端-Jedis
jedis客户端是目前使用最广泛的一款 java 客户端也是老牌的 Redis 的 Java 实现客户端。
优点
比较全面的提供了 Redis 的操作特性也就是说你能用 redis 命令操作的Jedis 包都也给你封装好了直接使用即可 使用广泛易上手
缺点
Jedis 客户端实例不是线程安全的需要借助连接池来管理和使用 Jedis 使用阻塞的I/O且其方法调用都是同步的程序流需要等到 sockets 处理完 I/O 才能执行不支持异步
Jedis对各种数据类型的API列表
String类型
set(String key, String value)设置键为字符串值。get(String key)获取指定键的值。getSet(String key, String value)设置键为字符串值并返回旧值。append(String key, String value)将值追加到指定键的末尾。substr(String key, int start, int end)获取指定键的子字符串。incr(String key)将指定键的值加1。decr(String key)将指定键的值减1。mset(String... keysvalues)同时设置多个键值对。mget(String... keys)获取多个键的值。
Hash类型
hset(String key, String field, String value)在哈希表中设置字段和值。hget(String key, String field)获取哈希表中指定字段的值。hgetAll(String key)获取哈希表中所有字段和值。hdel(String key, String... fields)删除哈希表中指定的字段。
List类型
lpush(String key, String... values)将一个或多个值插入到列表的头部。rpush(String key, String... values)将一个或多个值插入到列表的尾部。lpop(String key)移除并返回列表的第一个元素。rpop(String key)移除并返回列表的最后一个元素。llen(String key)返回列表的长度。
Set类型
sadd(String key, String... values)将一个或多个值添加到集合中。srem(String key, String... values)从集合中移除一个或多个值。spop(String key)从集合中随机移除并返回一个元素。scard(String key)返回集合中的元素个数。sismember(String key, String member)判断给定的元素是否存在于集合中。
Sorted Set类型
zadd(String key, double score, String member)将一个成员及其分值添加到有序集合中。zrangeByScore(String key, double startScore, double endScore)返回有序集合中指定分值范围内的成员。zrem(String key, String... members)从有序集合中移除指定的成员。zcard(String key)返回有序集合中的成员个数。
Jedis String(字符串) 实例
import redis.clients.jedis.Jedis;public class RedisStringJava {public static void main(String[] args) {//连接本地的 Redis 服务Jedis jedis new Jedis(localhost);System.out.println(连接成功);//设置 redis 字符串数据jedis.set(name, test);// 获取存储的数据并输出System.out.println(redis 存储的字符串为: jedis.get(name));}
}
第七章. Jedis Pipeline
Jedis的pipeline实现基于Redis的协议规范可以将多个命令发送到Redis服务器并且无需等待每个命令的回复而是在所有命令都发送完毕后一次性获取所有的回复。
具体实现上Jedis将多个命令放入一个列表中然后通过pipeline.sync()或pipeline.close()将所有命令一次性发送到Redis服务器。在服务器端所有的命令会被依次执行并记录每个命令的执行结果。当所有的命令都执行完毕后Jedis会一次性获取所有的执行结果并返回给客户端。
因此Jedis pipeline的实现原理可以总结为将多个命令打包成一个请求发送到服务器然后在服务器端依次执行这些命令并记录每个命令的执行结果。最后将所有的执行结果打包成一个响应返回给客户端。
使用Jedis pipeline可以提高效率因为它可以减少客户端和服务器之间的网络通信开销特别是在需要执行大量的读写操作时。同时pipeline模式还可以保证事务的原子性适用于需要执行一系列读写操作的业务场景。
Jedis的pipeline主要有以下特点
线程安全Jedis的pipeline是基于连接池的因此它是线程安全的可以在多个线程之间共享和并发使用同一个pipeline。批量处理pipeline模式可以将多个命令一次性发送到服务器减少了网络通信的开销。特别是当需要执行大量的读写操作时pipeline模式可以显著提高性能。事务处理pipeline模式支持事务可以在多个命令组成的管道中实现原子性操作。如果中间任何一个命令失败整个管道都会回滚不会执行失败命令之后的命令。连接管理使用pipeline模式时多个命令被缓存到本地然后一次性发送到服务器而不是每执行一个命令就向服务器发送请求这可以减少客户端与服务器之间的交互次数。
Jedis的pipeline支持所有基本的Redis命令包括但不限于以下类型
字符串命令例如SET, GET, MSET, MGET等。哈希表命令例如HSET, HGET, HMSET, HMGET等。列表命令例如LPUSH, RPUSH, LPOP, RPOP等。集合命令例如SADD, SMEMBERS等。有序集合命令例如ZADD, ZRANGE等。数据库命令例如SELECT, MOVE, DEL等。事务命令例如MULTI, EXEC, DISCARD等。Lua脚本命令例如EVAL, EVALSHA等。 请注意不是所有的命令都支持pipeline方式执行比如一些需要多个步骤才能完成的操作像SUBSCRIBE、PSUBSCRIBE、PUBLISH等命令就不支持pipeline方式执行。对于这些不支持pipeline的命令你只能一个个单独发送并等待响应。更多细节可以参考Jedis的官方文档或源码。
第八章. Redis缓存策略
Cache Aside、Read Through、Write Through 和 Write Back 的步骤过程如下
Cache Aside
读取数据时先查询缓存如果命中缓存则直接返回数据。如果未命中缓存则查询数据库并将查询结果放入缓存。更新数据时先删除缓存中的数据再更新数据库中的数据。
Read Through
读取数据时先查询缓存如果命中缓存则直接返回数据。如果未命中缓存则查询数据库并将查询结果放入缓存。更新数据时先查询数据库将要更新的数据放入缓存中并更新数据库中的数据。
Write Through
读取数据时先查询缓存如果命中缓存则直接返回数据。如果未命中缓存则查询数据库并将查询结果放入缓存。更新数据时先查询数据库将要更新的数据放入缓存中并更新数据库中的数据。
Write Back
读取数据时先查询缓存如果命中缓存则直接返回数据。如果未命中缓存则查询数据库并将查询结果放入缓存。更新数据时只更新缓存将缓存中的数据标记为脏数据需要同步到数据库的数据并不立即同步到数据库中。
Cache Aside、Read Through、Write Through 和 Write Back 都是缓存策略它们有各自的优缺点和使用场景。
Cache Aside 策略
优点
实现简单易于理解和实现。
不需要使用缓存服务代理对业务代码无侵入。
缺点
需要自己维护数据更新后的逻辑对业务代码有侵入。
在更新数据时需要先查询缓存再查询数据库增加了查询的开销。
使用场景适用于轻量级应用对数据一致性要求不高的场景。
Read Through 策略
优点
实现了缓存和数据库的同步避免了脏读和重复查询的问题。
减少了数据库的负载压力提高了查询效率。
缺点
需要使用缓存服务代理对业务代码有侵入。
在高并发的情况下可能会出现竞争问题需要使用锁或者其他同步机制来保证数据的一致性。
使用场景适合需要频繁使用缓存的应用例如电商网站、新闻网站等。
Write Through 策略
优点
在更新数据时缓存服务代理会先更新缓存再更新数据库减少了更新时的开销。
保证了数据的一致性和完整性减少了数据不一致的问题。
缺点
需要使用缓存服务代理对业务代码有侵入。
在高并发的情况下可能会出现竞争问题需要使用锁或者其他同步机制来保证数据的一致性。
使用场景适合对数据一致性要求较高的场景例如银行系统、交易系统等。
Write Back 策略
优点
在更新数据时只更新缓存然后异步更新数据库提高了性能。
在写入数据时不会立即同步到数据库中减少了同步的开销。
缺点
如果缓存宕机或者应用程序崩溃可能会导致数据丢失。
在高并发的情况下可能会出现竞争问题需要使用锁或者其他同步机制来保证数据的一致性。
使用场景适合对数据一致性要求不高的场景例如电商网站、新闻网站等。在使用时需要注意缓存的容量限制和更新频率问题。
第九章. Redis Modules
RediSearch一个功能齐全的搜索引擎模块用于在Redis中实现全文搜索。RedisJSON对JSON类型的原生支持可以存储、查询和操作JSON对象。RedisTimeSeries时序数据库支持可以用于存储时间序列数据支持灵活的时间窗口和采样操作。RedisGraph图数据库支持可以用于构建和查询图结构。RedisBloom概率性数据的原生支持可以用于快速过滤和查找数据。RedisGears可编程的数据处理模块可以用于构建分布式数据处理管道。RedisAI机器学习的实时模型管理和部署模块可以用于实现机器学习和人工智能应用。RedisML推荐系统模块可以用于构建推荐算法和推荐系统。Redis-cell限流模块可以用于限制Redis操作的频率和次数。
RediSearch
Redis Search 是一个 Redis 模块它为 Redis 添加了全文搜索功能。它使用 Redis 协议提供了一种简单而高效的方式来执行全文搜索查询并返回匹配的结果。
Redis Search 模块支持以下功能
创建和更新索引可以使用 Redis Search 模块创建索引并将数据添加到索引中。索引可以使用不同的字段和属性进行定义以便对数据进行分类和过滤。搜索查询可以使用 Redis Search 模块执行搜索查询并返回匹配的结果。搜索查询可以使用不同的查询类型和过滤条件来缩小搜索范围并提高搜索效率。排序和分页Redis Search 模块支持对搜索结果进行排序和分页。可以根据相关性、日期或其他字段对结果进行排序并可以选择返回特定数量的结果。聚合和分组Redis Search 模块支持对搜索结果进行聚合和分组。可以对结果进行分组计算总和、平均值等统计信息并可以执行其他聚合操作。过滤器Redis Search 模块支持使用过滤器来缩小搜索范围。可以根据特定条件过滤结果例如根据日期、地理位置或其他属性进行过滤。动态更新Redis Search 模块支持动态更新索引和数据。可以随时添加、更新或删除数据而无需停止或重新创建整个索引。 要使用 Redis Search需要安装 Redis Search 模块并将其加载到 Redis 服务器中。然后可以使用 Redis 命令行客户端或 Redis 客户端库与 Redis Search 模块进行交互执行创建索引、添加数据、执行搜索查询等操作。
使用 Jedis 和 Redis Search以下是相应的示例代码
java
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Response;
import redis.clients.jedis.Tuple;
import redissearch.ResponseStream;
import redissearch.SearchCommandBuilder;
import redissearch.SearchCommand;
import redissearch.SearchableField; import java.util.HashMap;
import java.util.Map; public class RedisSearchDemo { private static final String INDEX_NAME demo_index; private static final String KEYWORD search; public static void main(String[] args) { // 创建 Redis 连接 Jedis jedis new Jedis(localhost); // 创建索引 SearchableField field new SearchableField(keyword, null, SearchableFieldOptions.builder().build()); jedis.createIndex(INDEX_NAME, field); // 添加数据到索引中 MapString, Object data1 new HashMap(); data1.put(id, doc1); data1.put(keyword, KEYWORD); data1.put(name, Document 1); jedis.addDocumentToIndex(INDEX_NAME, data1); MapString, Object data2 new HashMap(); data2.put(id, doc2); data2.put(keyword, KEYWORD); data2.put(name, Document 2); jedis.addDocumentToIndex(INDEX_NAME, data2); // 执行查询并处理结果 SearchCommand searchCommand new SearchCommandBuilder() .addIndex(INDEX_NAME) .search(KEYWORD) .build(); ResponseStreamTuple responseStream jedis.executeWithStream(searchCommand); responseStream.forEach(response - { System.out.println(ID: response.get(id)); System.out.println(Name: response.get(name)); System.out.println(); }); }
}
在这个示例中我们首先创建了一个 Redis 连接然后使用 Jedis 的 createIndex 方法创建一个索引用于存储文档数据。接下来我们使用 addDocumentToIndex 方法将文档数据添加到索引中。然后我们使用 SearchCommandBuilder 构建一个搜索命令并指定要搜索的索引和关键字。最后我们使用 executeWithStream 方法执行搜索命令并通过 ResponseStream 处理搜索结果。每个搜索结果包含文档的 ID 和名称。
RedisJSON
Redis最佳实践
1.优雅的key结构
Redis的Key虽然可以自定义但最好遵循下面的几个最佳实践约定
遵循基本格式[业务名称]:[数据名]:[id] 长度不超过44字节 不包含特殊字符 例如我们的登录业务保存用户信息其key可以设计成如下格式
这样设计的好处
可读性强 避免key冲突 方便管理 更节省内存 key是string类型底层编码包含int、embstr和raw三种。embstr在小于44字节使用 采用连续内存空间内存占用更小。当字节数大于44字节时会转为raw模式存储在raw模式下 内存空间不是连续的而是采用一个指针指向了另外一段内存空间在这段空间里存储SDS内容 这样空间不连续访问的时候性能也就会收到影响还有可能产生内存碎片
2.拒绝BigKey
BigKey通常以Key的大小和Key中成员的数量来综合判定例如
Key本身的数据量过大一个String类型的Key它的值为5 MB Key中的成员数过多一个ZSET类型的Key它的成员数量为10,000个 Key中成员的数据量过大一个Hash类型的Key它的成员数量虽然只有1,000个但这些成员的Value值总大小为100 MB 那么如何判断元素的大小呢redis也给我们提供了命令 推荐值
单个key的value小于10KB 对于集合类型的key建议元素数量小于1000
2.1 BigKey的危害
网络阻塞对BigKey执行读请求时少量的QPS就可能导致带宽使用率被占满导致Redis实例乃至所在物理机变慢 内存倾斜BigKey所在的Redis实例内存使用率远超其他实例无法使数据分片的内存资源达到均衡 Redis阻塞对元素较多的hash、list、zset等做运算会耗时较旧使主线程被阻塞 CPU压力对BigKey的数据序列化和反序列化会导致CPU的使用率飙升影响Redis实例和本机其它应用
2.2 如何发现BigKey
1、redis-cli --bigkeys 利用redis-cli提供的–bigkeys参数可以遍历分析所有key并返回Key的整体统计信息与每个数据的Top1的big key
2、scan 扫描 自己编程利用scan扫描Redis中的所有key利用strlen、hlen等命令判断key的长度
scan 命令调用完后每次会返回2个元素第一个是下一次迭代的光标第一次光标会设置为0当最后一次scan 返回的光标等于0时表示整个scan遍历结束了第二个返回的是List一个匹配的key的数组
3、第三方工具 利用第三方工具如 Redis-Rdb-Tools 分析RDB快照文件全面分析内存使用情况 https://github.com/sripathikrishnan/redis-rdb-tools
2.3 如何删除BigKey
BigKey内存占用较多即便时删除这样的key也需要耗费很长时间导致Redis主线程阻塞引发一系列问题
redis 3.0 及以下版本 如果是集合类型则遍历BigKey的元素先逐个删除子元素最后删除BigKey Redis 4.0以后 Redis在4.0后提供了异步删除的命令unlink
3. 选择恰当的数据类型
例1比如存储一个User对象我们有三种存储方式 ①方式一json字符串
user:1 {“name”: “Jack”, “age”: 21} 优点实现简单粗暴 缺点数据耦合不够灵活
②方式二字段打散
user:1:name Jack user:1:age 21 优点可以灵活访问对象任意字段 缺点占用空间大、没办法做统一控制
③方式三hash推荐
user:1 name jack age 21 优点底层使用ziplist空间占用小可以灵活访问对象的任意字段 缺点代码相对复杂
例2假如有hash类型的key其中有100万对field和valuefield是自增id这个key存在什么问题如何优化 存在的问题
hash的entry数量超过500时会使用哈希表而不是ZipList内存占用较多
可以通过hash-max-ziplist-entries配置entry上限。但是如果entry过多就会导致BigKey问题 ①方案一 拆分为string类型
key value id:0 value0 ..... ..... id:999999 value999999 存在的问题
string结构底层没有太多内存优化内存占用较多 想要批量获取这些数据比较麻烦
②方案二 拆分为小的hash将 id / 100 作为key 将id % 100 作为field这样每100个元素为一个Hash key field value key:0 id:00 value0 ..... ..... id:99 value99 key:1 id:00 value100 ..... ..... id:99 value199 .... key:9999 id:00 value999900 ..... ..... id:99 value999999
4. 批处理优化
1、Pipeline 1.1 客户端与redis服务器的交互过程 单个命令的执行流程
N条命令的执行流程
redis处理指令是很快的主要花费的时候在于网络传输。于是乎很容易想到将多条指令批量的传输给redis
1.2 批量操作命令 Redis提供了很多Mxxx这样的命令可以实现批量插入数据例如mset、hmset 但是对于像 list、set、zset相关的数据结构没有对应的批处理命令
利用mset批量插入10万条数据
Test
void testMxx() {String[] arr new String[2000];int j;long b System.currentTimeMillis();for (int i 1; i 100000; i) {j (i % 1000) 1; //左移一位相当于乘以2arr[j] test:key_ i;arr[j 1] value_ i;if (j 0) {jedis.mset(arr);}}long e System.currentTimeMillis();System.out.println(time: (e - b));
}
1.3 批量操作命令Pipeline MSET虽然可以批处理但是却只能操作部分数据类型因此如果有对复杂数据类型的批处理需要建议使用Pipeline
Test
void testPipeline() {// 创建管道Pipeline pipeline jedis.pipelined();long b System.currentTimeMillis();for (int i 1; i 100000; i) {// 放入命令到管道pipeline.set(test:key_ i, value_ i);if (i % 1000 0) {// 每放入1000条命令批量执行pipeline.sync();}}long e System.currentTimeMillis();System.out.println(time: (e - b));
}
2、集群下的批处理 如MSET或Pipeline这样的批处理需要在一次请求中携带多条命令而此时如果Redis是一个集群那批处理命令的多个key必须落在一个插槽中否则就会导致执行失败。
这个时候我们可以找到4种解决方案
5.服务器端优化 - 持久化配置
用来做缓存的Redis实例尽量不要开启持久化功能 建议关闭RDB持久化功能RDB容易使用AOF持久化 设置合理的rewrite阈值避免频繁的bgrewrite 配置no-appendfsync-on-rewrite yes禁止在rewrite期间做aof避免因AOF引起的阻塞 部署有关建议
Redis实例的物理机要预留足够内存应对fork和rewrite 单个Redis实例内存上限不要太大例如4G或8G。可以加快fork的速度、减少主从同步、数据迁移压力 不要与CPU密集型应用部署在一起 不要与高硬盘负载应用一起部署。例如数据库、消息队列
6.服务器端优化 - 慢查询优化
1、什么是慢查询 并不是很慢的查询才是慢查询而是在Redis执行时耗时超过某个阈值的命令称为慢查询
慢查询的危害由于Redis是单线程的所以当客户端发出指令后他们都会进入到redis底层的queue来执行如果此时有一些慢查询的数据就会导致大量请求阻塞从而引起报错所以我们需要解决慢查询问题。
慢查询的阈值可以通过配置指定 slowlog-log-slower-than慢查询阈值单位是微秒。默认是10000建议10001毫秒
慢查询会被放入慢查询日志中日志的长度有上限可以通过配置指定 slowlog-max-len慢查询日志本质是一个队列的长度。默认是128建议1000
修改这两个配置可以使用config set命令
2、如何查看慢查询 知道了以上内容之后那么咱们如何去查看慢查询日志列表呢
slowlog len查询慢查询日志长度 slowlog get [n]读取n条慢查询日志 slowlog reset清空慢查询列表
7.服务器端优化-命令及安全配置
Redis会绑定在0.0.0.0:6379这样将会将Redis服务暴露到公网上而Redis如果没有做身份认证会出现严重的安全漏洞 漏洞重现方式https://cloud.tencent.com/developer/article/1039000
漏洞出现的核心的原因有以下几点
Redis未设置密码 利用了Redis的config set命令动态修改Redis配置 使用了Root账号权限启动Redis 所以如何解决呢我们可以采用如下几种方案 为了避免这样的漏洞这里给出一些建议
Redis一定要设置密码 禁止线上使用下面命令keys、flushall、flushdb、config set等命令。可以利用rename-command禁用。 bind限制网卡禁止外网网卡访问 开启防火墙 不要使用Root账户启动Redis 尽量不是有默认的端口
8.Redis内存划分和内存配置
当Redis内存不足时可能导致Key频繁被删除、响应时间变长、QPS不稳定等问题。当内存使用率达到90%以上时就需要我们警惕并快速定位到内存占用的原因。
有关碎片问题分析 Redis底层分配并不是这个key有多大他就会分配多大而是有他自己的分配策略比如8,16,20等等假定当前key只需要10个字节此时分配8肯定不够那么他就会分配16个字节多出来的6个字节就不能被使用这就是我们常说的 碎片问题
9.服务器端集群优化-集群还是主从
集群虽然具备高可用特性能实现自动故障恢复但是如果使用不当也会存在一些问题
集群完整性问题 集群带宽问题 数据倾斜问题 客户端性能问题 命令的集群兼容性问题 lua和事务问题
问题1、在Redis的默认配置中如果发现任意一个插槽不可用则整个集群都会停止对外服务
大家可以设想一下如果有几个slot不能使用那么此时整个集群都不能用了我们在开发中其实最重要的是可用性所以需要把如下配置修改成no即有slot不能使用时我们的redis集群还是可以对外提供服务
问题2、集群带宽问题
集群节点之间会不断的互相Ping来确定集群中其它节点的状态。每次Ping携带的信息至少包括
插槽信息 集群状态信息 集群中节点越多集群状态信息数据量也越大10个节点的相关信息可能达到1kb此时每次集群互通需要的带宽会非常高这样会导致集群中大量的带宽都会被ping信息所占用这是一个非常可怕的问题所以我们需要去解决这样的问题
解决途径
避免大集群集群节点数不要太多最好少于1000如果业务庞大则建立多个集群。 避免在单个物理机中运行太多Redis实例 配置合适的cluster-node-timeout值
问题3 命令的集群兼容性问题
有关这个问题咱们已经探讨过了当我们使用批处理的命令时redis要求我们的key必须落在相同的slot上然后大量的key同时操作时是无法完成的所以客户端必须要对这样的数据进行处理这些方案我们之前已经探讨过了所以不再这个地方赘述了。
问题4 lua和事务的问题
lua和事务都是要保证原子性问题如果你的key不在一个节点那么是无法保证lua的执行和事务的特性的所以在集群模式是没有办法执行lua和事务的
问题5 那我们到底是集群还是主从
单体Redis主从Redis已经能达到万级别的QPS并且也具备很强的高可用特性。如果主从能满足业务需求的情况下所以如果不是在万不得已的情况下尽量不搭建Redis集群
学习资料
Redis官网:http://redis.io/Redis官方文档:http://redis.io/documentationRedis教程:https://www.runoob.com/redis/redis-tutorial.htmlRedis下载:http://redis.io/downloadredis英文文档 https://redis.io/topics/data-typesredis中文文档 http://www.redis.cn/documentation.博客 https://blog.csdn.net/h356363/category_8930846.html
QA 相关问题
http, socket ,tcp的区别
HTTP、Socket和TCP是网络通信中常用的协议和技术它们各自扮演着不同的角色。
HTTP协议HTTP是Hypertext Transfer Protocol超文本传输协议的简称它是互联网上应用最为广泛的一种网络协议。HTTP协议用于浏览器和服务器之间的通信它规定了浏览器如何向服务器发送请求以及服务器如何将响应返回给浏览器。HTTP协议是基于应用层的协议它提供了一种具体的方式来传输和接收数据。SocketSocket是对TCP/IP协议的封装和应用它是支持TCP/IP协议的网络通信的基本操作单元。在网络通信过程中Socket用于端点的抽象表示它包含了进行网络通信所必需的五种信息连接使用的协议、本地主机的IP地址、本地进程的协议端口、远地主机的IP地址和远地进程的协议端口。程序员使用Socket进行网络通信时需要对TCP/IP协议进行操作Socket则提供了一个TCP的接口。可以说Socket是对TCP/IP协议的应用层封装。TCP协议TCPTransmission Control Protocol传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议。它通过在发送方和接收方之间建立虚连接提供了一种可靠的数据传输服务能够确保数据在传输过程中的正确性和可靠性。TCP协议对应于传输层它在网络通信过程中负责数据的传输和控制它可以确保数据在传输过程中不丢失、不重复、不错乱。
总结来说HTTP协议、Socket和TCP协议各自有不同的特点和作用。HTTP协议用于规定浏览器和服务器之间的通信规则Socket是对TCP/IP协议的应用层封装用于网络通信的基本操作TCP协议则负责数据的传输和控制确保数据在传输过程中的可靠性和正确性。