当前位置: 首页 > news >正文

做网站多少钱 佛山wordpress 学习插件

做网站多少钱 佛山,wordpress 学习插件,建筑工程公司宣传册设计样本,wordpress获取菜单链接目录 今日良言#xff1a;满怀憧憬#xff0c;阔步向前 一、基础命令 1.1 通用命令 1.2 五大基本类型的命令 1.2.1 String 1.2.2 Hash 1.2.3 List 1.2.4 Set 1.2.5 Zset 二、过期策略以及单线程模型 2.1 过期策略 2.2 单线程模型 2.3 Redis 效率为什么这么高 三…目录 今日良言满怀憧憬阔步向前 一、基础命令 1.1 通用命令 1.2 五大基本类型的命令 1.2.1 String 1.2.2 Hash 1.2.3 List 1.2.4 Set 1.2.5 Zset 二、过期策略以及单线程模型 2.1 过期策略 2.2 单线程模型 2.3 Redis 效率为什么这么高 三、Java 客户端操作 Redis 四、Spring 操作 Redis 今日良言满怀憧憬阔步向前 一、基础命令 1.1 通用命令 “一个优秀的命令”不仅会使得企业相关软件卡死而且会让程序猿“成功” 带走自己的年终奖若出于某些目的性的行为可能会喜提银手镯一副吃上国家饭比如“故意删库跑路”。那么作为一个兢兢业业的程序猿在操作 redis 的时候该如何避免自己的年终奖被一波带走呢接下来可要仔细学习下面这些命令。 keys 首先keys 隆重登场。 语法 keys pattern keys 返回所有满足样式pattern的key同时它也支持如下统配样式。 h?llo  可以替换成任意字符比如匹配hallo、hbllo.... h*llo * 可以替换0个或多个相同字符比如匹配hllo、heeello h[ae]llo  匹配包含[ ] 括号中的字符的key比如匹配hallo、hello h[^e]llo 匹配除了e 字符的key比如匹配hallo、hbllo.. 但是不包含hello h[a-f]llo 匹配包含 a-f 区间的字符比如:hallo、hbllo、hfllo  示例 命令有效版本1.0.0之后 时间复杂度ON 返回值匹配 pattern 的所有key 在生产环境上一般都会禁止使用keys命令尤其是 keys * 这个大杀器因为 keys * 这个命令会查询 redis 所有的 key生产环境上的 key 可能会非常的多而 redis 是一个单线程的服务器执行 keys 的时间非常长会导致 redis 服务器被阻塞了无法给其它的客户端提供服务这样的后果是灾难性的redis 经常会被用于缓存是替数据库抵挡大量的请求万一 keys * 将 redis 阻塞住了此时其它的查询 redis 操作就超时了此时这些请求会直接查询数据库大量请求同时访问数据库可能会导致数据库宕机如果程序猿没有及时发现且没有及时恢复的话年终奖就被一波带走了更严重的话工作也就没有了。 exists 判断某个key是否存在 语法 exists key [key....]            【一次性可以判断多个key】 示例 命令有效版本1.0.0之后 时间复杂度O1 返回值key 存在的个数 del 删除指定的key 语法 del  key [key....]          【一次性可以删除多个key】 示例 命令有效版本1.0.0之后 时间复杂度O1 返回值删除的 key 的个数 expire  为指定的key添加秒级的过期时间 语法 expire key seconds 示例 命令有效版本1.0.0之后 时间复杂度O1 返回值1表示设置成功0表示设置失败 ttl time to live   获取指定key的过期时间秒级 思考题这里的 ttl 和 IP 协议报头中的字段 TTL 有什么区别 这里的ttl 获取的是时间单位秒。而 IP 协议中的 TTL 不是用时间衡量的而是用次数。  语法 ttl key 示例 命令有效版本1.0.0之后 时间复杂度O1 返回值剩余过期时间。 -1 表示没有关联过期时间-2 表示 key 不存在 注expire 和 ttl 命令都有对应的支持毫秒为单位的版本pexpire 和 pttl type 返回 key 对应的数据类型 语法 type key 示例 命令有效版本 1.0.0之后 时间复杂度O1 返回值 none、string、list、set、zset、hash、stream  以上就是 redis 中几个基本的全局命令熟练掌握有助于把握年终奖哦。 1.2 五大基本类型的命令 本小节主要介绍 redis 中的五大基本类型的命令及其内部编码和使用场景 1.2.1 String 首先介绍一下 String类型。 字符串类型是 Redis 最基础的数据类型注此String 非彼 String(java)。 Redis 所有的 key 都是字符串只是 value 的类型有所差异。 Redis 中的字符串直接是按照二进制的方式进行存储的不会做任何的编码转换存啥取啥。Redis 不仅可以存二进制数据图片、音频、视频...还可以存整数、文本数据、JSon、xml、普通的文本字符串... 由于二进制数据音视频的体积比较大于是 Redis 对于 String 类型的 value 进行了大小限制最大为512MB主要是为了控制单个值对内存的占用确保 Redis 的性能。因为 Redis 是单线程模型希望进行的操作都是比较快速如果操作过大的 value可能会影响整个 Redis 的响应时间。 从三个方面来介绍 1命令 set 将String类型的 value 设置到 key 中如果 key 已经存在则覆盖 key 的value值包括不同数据类型 语法 set key value [expiration EX seconds|PX milliseconds] [NX|XX] 上述语法格式说明 [ ]相当于一个独立的单元表示可选项可有可无其中 | 表示 或者 的意思多个只能选择一个[ ] 和 [ ] 之间可以同时存在  示例 命令有效版本1.0.0之后 时间复杂度O(1) 返回值 设置成功返回OK。set 如果指定了 nx 或者 xx 但条件不满足set 不会执行返回nil set 命令支持多种选项来影响它的行为 EX seconds 使用秒作为单位设置 key 的过期时间。 PX milliseconds : 使用毫秒作为单位设置 key 的过期时间 NX当 key 不存在的时候才设置。 XX当 key存在的时候才设置覆盖 value 值 示例 这里是设置了key2 的 value 值为v2并且通过ex设置过期时间为10s并且只有当 key2 不存在的时候才设置。 10s 后 key2 过期此时查询结果返回 (nil): 注 由于上述带选项的 set 命令可以被 setnx、setex、psetex 等命令代替所以之后的版本中Redis 可能进行合并。  get 获取对应的 key 的 value 值如果 key 不存在返回 nil如果 value 的数据类型不是 String会报错 语法 get key 示例 命令有效版本1.0.0之后 时间复杂度O1 返回值key 对应 value nil 或者 报错 mget 一次性获取多个 key 的值如果对应的 key 不存在或者对应的数据类型不是 String返回 nil 语法 mget key[key1 key2 ....] 示例 命令有效版本 1.0.0 之后 时间复杂度 ONN是 key 的个数 返回值对应 value 的列表 mset 一次性设置多个 key 的值 语法 mset key v1 key2 v2 .... 示例 命令有效版本1.0.1 时间复杂度 ON N 是 key 的个数 返回值永远是 OK mset 和 mget 是操作一组键值对批量操作 mget 和 get 的区别 如图所示使用mget/mset 可以很好的减少网络时间提高相较于 n 次 get/set 的性能要高使用批量操作可以有效地提高业务处理效率但是需要注意批量操作也是有弊端的每次批量发送的键的数量并不是毫无节制的这会使得单一命令执行时间过长进而导致 redis 阻塞。 setnx  在 key 不存在的情况下设置 key-value 语法 setnx key 示例 命令有效版本1.0.0 之后 时间复杂度O1 返回值设置成功返回 1设置失败返回 0 setex 给 key 设置 value同时设置过期时间其效果相当于 set key value 后 expire seconds 语法 setex key seconds value 示例 命令有效版本1.0.0之后 时间复杂度O1 返回值永远都是OK psetex 是设置毫秒级别的过期时间语法setex相同 setnx、setex、psetex 是针对 set 的一些常用命令进行了缩写这样的好处就是让操作更符合人的直觉让使用者的学习成本更低。 接下来介绍一些加减 value 的操作 incr 将 key 对应的 string 表示的数字加1。如果 key 不存在则视为 key 对应的 value 是 0若 key 对应的 string 不是一个整数或者范围超过了 64位有符号整数则报错。 语法 incr key 示例 命令有效时间1.0.0之后 时间复杂度O1 返回值integer 类型加完后的值 incrby 将 key 对应的 string 表示的数字加上对应的值。如果 key 不存在则视为 key 对应的 value 是 0若 key 对应的 string 不是一个整数或者范围超过了 64位有符号整数则报错。 语法 incrby key decrement 示例 命令有效版本1.0.0之后 时间复杂度O1 返回值integer 类型加完后的值 decr 将 key 对应的 string 表示的数字减1。如果 key 不存在则视为 key 对应的 value 是 0若 key 对应的 string 不是一个整数或者范围超过了 64位有符号整数则报错。 语法 decr key 示例 命令有效版本1.0.0之后 时间复杂度O1 返回值integer 减完之后的值 decrby 将 key 对应的 string 表示的数字减去对应的值。如果 key 不存在则视为 key 对应的 value 是 0若 key 对应的 string 不是一个整数或者范围超过了 64位有符号整数则报错。 语法 decrby key decrement 示例 命令有效版本1.0.0之后 时间复杂度O(1) 返回值integer 类型减完之后的值 incrbyfloat 将 key 对应的 string 表示的浮点数加上对应的值。如果对应的值是负数则视为减去对应的值。如果 key 不存在则视为 key 对应的 value 是 0。如果 key 对应的不是 string或者不是⼀个浮点数则报 错。允许采用科学计数法表⽰浮点数。 语法 incrbyfloat key increment 示例 命令有效版本2.6.0之后 时间复杂度O1 返回值加/减完之后的值 append 如果 key 存在并且是 String 类型命令会将 value 追加到原有 string 的后边。如果 key 不存在则效果等同于 set 命令。 语法 append key  value 示例 命令有效版本2.0.0之后 时间复杂度O1.追加的字符串一般较短可以视为O1 返回值追加完后 string 的长度 getrange 返回 key 对应的 value 的子串由 start 和 end 确定左闭右闭。可以使用负数表示-1 代表倒数第一个字符-2 代表倒数第二个字符其他的与之类似。超过范围的偏移量会根据 value 的长度调整成正确的值。 语法 getrange key start end 示例 命令有效版本2.4.0之后 时间复杂度ON.N是[start,end]区间的长度由于这个区间较短一般视为O1 返回值string 类型的字符串 setrange 覆盖字符串的一部分从指定的偏移量开始 语法 setrange key offset value 示例 命令有效版本2.0.0之后 时间复杂度ON. N为 value 的长度由于一般给定的 value 较短通常视为O(1)。 返回值替换后的 string 长度 strlen 获取指定的 key 的长度如果 key 不是 String 类型会报错如果 key 不存在返回0 语法 strlen key 示例 命令有效版本2.2.0 之后 时间复杂度O1 返回值对应的 string 的长度key 不存在返回0 2内部编码 字符串类型的编码有三种 int8个字节的长整数embstr小于等于39个字节的字符串raw大于39个字节的字符串 redis 会根据当前 value 的类型和长度动态决定使用哪种内部编码实现 注从 redis 4.0开始当 value 的字节数小于等于44是embstr大于44字节是raw 通过如下命令可以查看当前内部编码 object encoding key 示例 3使用场景 缓存Cache功能 redis 可以当做缓冲层mysql 作为存储层此时绝大部分请求的数据都是从 redis 中获取。由于 redis 支持高并发所以缓存通常可以起到加速读写和降低后端压力的作用。 计数功能 许多应用都会使用 redis 作为计数的基础工具它可以实现快速计数查询缓存的功能同时数据可以异步处理或者落地到其他数据源。例如视频网站的播放次数可以使用 redis 来完成用户每播放一次数据相应的视频播放数就会自增1。 共享会话 ⼀个分布式 Web 服务将用户的 Session 信息例如用户登录信息保存在各自的服务器中但这样会造成⼀个问题出于负载均衡的考虑分布式服务会将用户的访问请求均衡到 不同的服务器上并且通常无法保证用户每次请求都会被均衡到同⼀台服务器上这样当用户刷新一次访问是可能会发现需要重新登录这个问题用户无法容忍的为了解决这个问题可以使用 redis 将用户的 Session 信息进行集中管理在这种模式下只要保证 redis 是高可用和可扩展的无论用户被均衡到哪台 Web 服务器上都可以集中从 redis 中查询、更新 Session 信息。 手机验证码 很多应用出于安全考虑会在每次登录时让用户输入手机号并且配合给手机发送验证码然后让用户再次输入收到的验证码进行验证从而确认是否是用户本人为了短信接口不会频繁访问会限制用户每分钟获取验证码的频率例如一分钟不能超过五次。 以上是 String 类型的相关介绍。 1.2.2 Hash 接下来介绍 Hash 哈希类型。 在 redis 中Hash 类型是指值本身又是一个键值对结构如下图 哈希类型中的映射关系通常称为 field-value用于区分 redis 的整体键值对key - value 1命令 hset 设置 hash 中指定字段field的值value 语法 hset key field value [field value....]   可设置多组  示例 命令有效版本2.0.0之后 时间复杂度插入一组 field 为O1插入多组为 ON 返回值 添加的字段field的个数 hget 获取指定字段field的值value 语法 hget key field 示例 命令有效版本2.0.0之后 时间复杂度O(1) 返回值 field 对应的值。如果键 key 或者 field 不存在返回nill hexists 判断 hash 中是否有指定的字段field 语法 hexists key field 示例 命令有效版本2.0.0之后 时间复杂度O(1) 返回值 存在返回1否则0 hdel 删除 hash 中指定的字段field 语法 hdel key field [field...]   可以删除多组 示例 命令有效版本2.0.0之后 时间复杂度删除一个为O(1)删除 N 个为ON 返回值 本次删除的 field 的个数 hkeys 获取 hash 中所有字段field 语法 hkeys key 示例 命令有效版本2.0.0之后 时间复杂度ONN是 field 的个数 返回值 字段列表 hvals 获取 hash 中所有的值 语法 hvals key 示例 命令有效版本2.0.0之后 时间复杂度ONN是 field 的个数 返回值 值列表 hgetall 获取所有字段field以及其对应的值 语法 hgetall key 示例 命令有效版本2.0.0之后 时间复杂度ONN是 field 的个数 返回值 字段和对应的值 hmget 一次性获取 hash 中多个字段的值查询结果中的 value 的顺序和 field 的顺序相匹配 语法 hmget key field  [field] 实例 命令有效版本2.0.0之后 时间复杂度只查询⼀个元素为 O(1), 查询多个元素为 O(N), N 为查询元素个数. 返回值 字段对应的值或者nill 看到这里各位程序员们是不是有疑问有没有 hmset可以一次性设置多个 field 和 value 呢什么没有那不行没有也得有不然小马怎么凑字数弱弱的调侃一句 答案是有的但是并不需要。因为 hset 可以一次性设置多个 field 和 value。如下图 注 1在上述的hkeyshvalshgetall 都是存在一定风险的当 hash 中元素过多时执行的时间比较长从而阻塞 redis。 2如果只想获取部分 field 可以使用 hmget 如果一定要获取所有的 field可以尝试命令 hscan该命令采用渐进式遍历哈希类型也就是敲一次命令遍历一小部分再敲一次命令再遍历一小部分连续执行多次就可以完成整个的遍历过程了化整为零。 hlen 获取 hash 中所有字段的个数 语法 hlen key 示例 命令有效版本2.0.0之后 时间复杂度O1 返回值 字段个数 hsetnx 在字段不存在的情况下设置 hash 中的字段和值 语法 hsetnx key field value 示例 命令有效版本2.0.0之后 时间复杂度O1 返回值 1设置成功0设置失败 hincrby 将 hash 中字段对应的值添加指定的值 语法 hincrby key field increment 示例 命令有效版本2.0.0之后 时间复杂度O1 返回值 该字段对应的值变化后的值如果对应的值不是整数类型会报错 hincrbyfloat 将 hash 中字段对应的值添加指定的浮点数 语法 hincrbyfloat key field increment 示例 命令有效版本2.6.0之后 时间复杂度O1 返回值 该字段对应的值变化后的值如果对应的值不是整数类型会报错 以上就是 Hash 类型的命令。 2内部编码 Hash 类型的内部编码有两种 ziplist压缩列表   hashtable哈希表 当哈希类型元素个数小于hash-max-ziplist-entries 配置默认是512个且同时所有值小于 hash-max-ziplist-value 配置默认是64字节时redis 会使用 ziplist 作为哈希的内部编码ziplist 使用更加紧凑的结构实现多个元素的连续存储所以在节省内存方面比hashtable更加优秀。 当哈希类型不满足 ziplist 的条件时redis 会使用 hashtable 作为哈希的内部编码因为此时 ziplist 的读写效率会下降而 hashtable 的读写时间复杂度都是O1。 上述配置在 redis.conf 文件中都可以查看并进行修改 示例 3使用场景 作为缓存 String 也是可以作为缓存使用的但存储结构化的数据类似于数据库 表 这样的结构使用 hash 类型更合适一些。如下 以上就是 Hash 类型的相关介绍。 1.2.3 List 接下来介绍 List 类型List 用来存储多个有序的字符串列表中的每个字符串称为元素element一个列表最多可以存储2^32 - 1 个元素。在 redis 中可以对列表两端插入push和弹出pop还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是一种比较灵活的数据结构它可以充当栈和队列的角在实际开发中有很多应用场景。如下图 1命令 lpush 将一个或者多个元素插入到队列的左侧头插 语法 lpush key element  [element....]   示例 命令有效版本1.0.0之后 时间复杂度插入一个元素O1插入多个元素ONN为元素的个数 返回值插入后 list 的长度 lpushx key 存在时插入一个或者多个元素到队列的左侧头插key 不存在返回0 语法 lpushx key element[element...] 示例 命令有效版本2.0.0之后 时间复杂度插入一个元素O1插入多个元素ONN为元素的个数 返回值插入后 list 的长度 rpush 将一个或者多个元素插入到队列的右侧尾插 语法 rpush key element[element..] 示例 命令有效版本1.0.0之后 时间复杂度插入一个元素O1插入多个元素ONN为元素的个数 返回值插入后 list 的长度 rpushx key 存在时插入一个或者多个元素到队列的右侧尾插key 不存在返回0 语法 rpushx key element[element...] 示例 命令有效版本2.0.0之后 时间复杂度插入一个元素O1插入多个元素ONN为元素的个数 返回值插入后 list 的长度 lrange 获取 start 和 end 区间内的元素左闭右闭 语法 lrange key start stop 示例 命令有效版本1.0.0之后 时间复杂度ON 返回值指定区间的元素 lpop 从 list 左侧取出元素头删 语法 lpop key  示例 命令有效版本1.0.0之后 时间复杂度O1 返回值取出的元素或者nill rpop 从 list 右侧取出元素尾删 语法 lpop key 示例 命令有效版本1.0.0之后 时间复杂度O1 返回值取出的元素或者nill lindex 获取从左边数第 index 位置的元素 语法 lindex key index 示例 命令有效版本1.0.0之后 时间复杂度O1 返回值取出的元素或者nill linsert 在指定元素前/后插入元素 语法 linsert key before| after pivot element 示例 注如果这里指定的值有多个linsert 插入的时候按照从左到右找到第一个符合指定值的位置即可。 命令有效版本2.2.0之后 时间复杂度ON 返回值插入后 list 的长度插入失败返回 -1 llen 获取 list 的长度 语法 llen key 示例 命令有效版本1.0.0之后 时间复杂度O1 返回值list 的长度 lrem 从左到右删除指定元素可以指定删除的个数 语法 lrem key count element 示例 对于这里的 count 要分情况讨论 count 0 : 从头到尾进行删除指定元素                   删除了前两个 1 count 0 : 从尾到头进行删除执行元素                    删除了最后一个 2 count 0 : 删除所有指定元素                   删除了所有的 3 命令有效版本1.0.0之后 时间复杂度ON N 是删除元素的个数 返回值删除元素的个数 ltrim  保留 start 和 stop 区间内的所有元素区间外的元素全部删除 语法 ltrim key start stop 示例 以上是 list 类型的一些基本命令接下来介绍一下阻塞版本的命令。 blpop 和 brpop 是 lpop 和 rpop 的阻塞版本和对应的非阻塞版本的作用基本一致除了 当列表中无元素时阻塞版本会根据 timeout 阻塞一段时间而非阻塞版本会立即返回 nill在阻塞期间redis 可以执行其它命令但要求执行该命令的客户端会表现为阻塞状态。 blpop lpop 的阻塞版本 语法 blpop key[key..] timeout 示例 当 list 有元素时 当 list 无元素时会阻塞 如果当前客户端执行 blpop 命令时阻塞了在阻塞期间其它客户端往这个 list 中插入了数据当前客户端此时就会获取元素不再阻塞 客户端1 客户端2 当客户端 2 的命令执行后客户端 1将返回结果不再阻塞 命令有效版本1.0.0之后 时间复杂度O1 返回值取出的元素或者nill brpop rpop 的阻塞版本 语法 brpop key[key..] timeout 示例 与blpop 操作一样这里不进行实操掩饰铁子们自己动手实操老话说的好眼过千遍不如受过一遍好吧其实是我懒得敲了 0.0 命令有效版本1.0.0之后 时间复杂度O1 返回值取出的元素或者nill 以上就是 List 类型的相关命令介绍 2内部编码 在 reids 3.2版本之前List 类型的内部编码有两种 ziplist (压缩列表)linkedlist(链表) ziplist 把数据按照更紧凑的压缩形式进行表示可以做到节省空间但是当元素个数多了操作起来效率会降低。当列表的元素个数小于 list-max-ziplist-entries 配置默认是512个同时列表中每个元素的长度都小于 list-max-ziplist-entries 配置默认是64字节时redis 会选用ziplist 来作为内部编码。 当列表类型无法满足 ziplist 的条件时redis 会使用 linkedlist 作为列表的内部实现。 在 redis 3.2版本开始内部编码采用 quicklist quicklist 相当于是链表和压缩列表的组合整体还是一个链表双向链表链表的每个节点是一个压缩列表。quicklist的行为可以通过配置参数list-max-ziplist-size来调整该参数决定了压缩列表的最大大小。当元素数量超过这个配置值时Redis会创建一个新的压缩列表节点。 3使用场景 消息队列 每次只有一个消费者能抢到该元素对于三个消费者来说谁先执行 brpop 命令谁就先拿到这个元素。  以上就是对 List 类型的相关介绍。 1.2.4 Set 接下来介绍 Set集合 类型 集合类型也是保存多个字符串类型的元素的但和列表元素有所不同主要有以下区别 1.元素之间是无序的 2.元素不允许重复 一个集合最多可以存储 2^32 -1 个元素。 Redis 除了支持集合内的增删改查操作还支持集合间的并集、交集、差集。集合类型的结构如下图 老样子先来介绍命令 1命令 sadd 将一个元素或者多个元素添加到 set 中无法添加重复元素 语法 sadd key member [member...] 示例 只添加成功了三个元素 命令有效版本1.0.0 之后 时间复杂度O1 返回值本次添加成功的元素的个数 将 set 中的元素称为 member smembers 获取 set 中的所有元素元素之间是无序的。 语法 smembers key 示例 命令有效版本1.0.0 之后 时间复杂度O1 返回值集合中的所有元素 sismember 判断某个元素在不在 set 中 语法 sismember key member 示例 命令有效版本1.0.0 之后 时间复杂度O1 返回值在返回1不在或者 key 不存在返回0 scard 获取 set 中的元素个数 语法 scard key 示例 命令有效版本1.0.0 之后 时间复杂度O1 返回值set 中元素的个数 spop 随机删除并返回一个或者多个元素 语法 spop key [count] 示例 命令有效版本1.0.0 之后 时间复杂度ON N是count 返回值取出的元素 smove 移动元素将一个元素从源 set 中取出并放入到目标set 中 语法: smove source destination member         示例 命令有效版本1.0.0 之后 时间复杂度O1  返回值1 表示成功0 表示失败 srem 将指定的元素从 set 中删除 语法 srem key member[smember...] 示例 命令有效版本1.0.0 之后 时间复杂度ON  N 是待删除元素的个数 返回值本次删除元素的个数 以上是集合内部的操作接下来介绍集合间的操作交集 并集 差集。 在小学或许初中时数学老师就教过我们这个概念这里简单举一个例子 集合一1 2 3  4       集合二 1 4 5 6 交集两个集合都有的元素1  4 并集两个集合所有的元素去除重复元素 1 2 3 4 5 6 差集         集合一对集合二求差集2 3         集合二对集合一求差集5 6 接下来介绍相关命令 并集操作 sunion 获取给定 set 的并集中的元素 语法 sunion key [key...] 示例 命令有效版本1.0.0 之后 时间复杂度ONN是给定的所有集合总的元素个数  返回值并集的元素 sunionstore 获取给定的 set 的并集并保存到目标 set 中 语法 sunionstore destination key [key...] 示例 命令有效版本1.0.0 之后 时间复杂度ONN是给定的所有集合总的元素个数  返回值并集的元素个数 交集操作 sinter 获取给定 set 的交集元素 语法 sinter key[key..] 示例 命令有效版本1.0.0 之后 时间复杂度ONN是给定的所有集合总的元素个数  返回值交集的元素 sinterstore 获取给定的 set 的交集并保存到目标 set 中 语法 sinterstore destination key[key...] 示例 命令有效版本1.0.0 之后 时间复杂度ONN是给定的所有集合总的元素个数  返回值交集的元素个数 差集操作 sdiff 获取给定 set 的差集中的元素 语法 sdiff key[..] 示例 命令有效版本1.0.0 之后 时间复杂度ONN是给定的所有集合总的元素个数  返回值差集的元素 sdiffstore 获取给定的 set 的差集并保存到目标 set 中 语法 sdiffstore destination key[key..] 示例 命令有效版本1.0.0 之后 时间复杂度ONN是给定的所有集合总的元素个数  返回值差集的元素个数 以上就是 Set 类型的相关命令。 2内部编码 Set 类型的内部编码有两种 intset整数集合hashtable哈希表   当集合中的元素都是整数并且元素的个数小于set-max-intset-entries 配置默认512个时redis 会选用 intset 作为集合的内部实现从而减少内存的使用。   当集合类型不满足 intset 的条件时redis 会使用 hashtable 作为集合的内部实现。 上述配置在redis.conf 文件中依旧可以找到 3使用场景 保存用户标签 Set 比较典型的使用场景就是标签例如用户1对美女感兴趣用户2对体育类感兴趣这些特征都可以抽象成标签可以分析清楚用户特征以后再投其所好推送用户喜欢的内容。同时有了这些标签数据以后就可以得到喜欢同一个标签的用户通过 set 的交集操作这些数据对于增强用户体验和用户黏度非常有帮助。 计算用户之间的共同好友 基于“集合求交集”可以计算出用户之间的共同好友基于这个还可以做一些好友推荐比如A和B是好友A和C是好友B和C和D都是好友系统就会把D推荐给A。 以上就是对于 Set 类型的相关介绍。 1.2.5 Zset 最后介绍 Zset有序集合。 这里的有序指的是升序/降序通过给 zset 中的 member 同时引入一个属性分数 score 浮点类型来作为排序规则每个 member 都会安排一个分数进行排序的时候就根据 score 的大小来进行升序/降序 排序。 对于 set 集合来说其 member 是无序的且不能重复而 zset 保留了 member 不能重复的特点同时根据 score 来维护有序性。 以三国中的武将的武力值来理解 Zset 的结构 1命令 zadd 添加或者更新指定的元素以及关联的分数到 zset 中分数应该符合 double 类型inf/-inf 作为正负极限也是合法的。 语法 zadd key[NX | XX ] [GT | LT] [CH] [INCR] score member [score member...] member 和 score 称为一个 “pair”这个“pair” 与键值对key-value不同键值对中是有明确的“角色区分”谁是键谁是值是明确的一定是根据“键”找“值”而对于有序集合来说既可以通过 member 找到对应的 score又可以通过 score 找到匹配的 member。 解释一下这里的一些选项 [NX | XX] XX当member存在时才进行修改不会添加新的member。 NX当member不存在时才进行添加 member操作不会修改已经存在的 member。 不加上述这两个选项的时候如果当前 member 不存在此时就会创建新的 member 如果当前 member 已经存在此时就会更新分数。 [GT | LT] LTless than更新分数时如果给定的新分数小于当前的分数此时更新成功否则不更新。 GTgreater than更新分数时如果给定的新分数大于当前的分数此时更新成功否则不更新。 这个选项在 redis 6.2 版本引入由于小马的 redis 版本更早因此这个选项不做演示铁铁们自己尝试一波。 [CH] 本来zadd 命令的返回值是新添加到有序集合的 member 数量而当指定了 CH 选项时返回值将更改为发生变化的成员总数这包括新添加的成员以及修改了分数的已有成员。如果命令中执行的成员的分数和现有的成员拥有相同的分数则这些成员不计入变化的成员内。 总的来说CH 选项提供了对 zadd 命令返回值的额外控制使得用户能够获得有关数据变化的更精确信息特别是在需要跟踪或记录数据变动情况时非常有用。 [INCR] 对指定成员member的分数进行增加。 举例 不加任何选项 使用 NX 使用 XX 使用CH 这里小马想要修改 zhansgan 的分数为 99.6查询结果竟然是99.5999999...这是为什么呢 redis 会扣分好吧其实并不是 真实原因是因为浮点数在计算机中的表示和存储方式导致的精度问题某些十进制小数无法精确地用二进制表示因此会出现一些舍入误差。 使用 [INCR] 命令有效版本1.2.0之后 时间复杂度OlogN  返回值本次添加成功的元素的个数 zcard 获取 zset 中的元素个数 语法 zcard key 示例 命令有效版本1.2.0之后 时间复杂度O1 返回值zset 中的元素个数 zcount 返回分数在 min 和 max 之间的元素个数默认情况下min 和 max 都是包含在内的可以不包含。 语法 zcount key min max 示例 以上是边界包含的情况下面演示不包含边界的情况。 在以前的学习中对于区间而言( 表示开区间不包含[ 表示闭区间包含那么redis 这里也是这样吗动手实践操作一下毕竟时间是检验真理的唯一标准如下图 WTF竟然报错 那么到底如何排除边界呢 经过一番学习没想到这里的排除边界设计竟如此 0 疼如下图 一个好的设计应当是符合直觉的让人能够望文生义越符合直觉则学习成本越低显然上述这个设计并不是一个好的设计但是由于大牛们已经设计好了我们只能遵守这样的规则只能将错就错。 可能会有铁铁有疑惑为什么经过这么长时间的演变没有人提出来修改呢 这里关乎到兼容性由于 redis 已广泛使用一旦在新版本中引入和之前版本不兼容的特性成本是非常高的。 zset 内部会记录每个元素当前的“排行”/“次序”查询到元素就直接知道了该元素的“次序”就可以直接把 max 对应的元素次序和 min 对应的元素次序下标相减这样就可以得到这个区间内的元素个数。 在浮点数中有两个特殊的数值inf 表示无穷大-inf表示负无穷大zset 中也支持 命令有效版本2.0.0之后 时间复杂度OlogN 返回值满足条件的元素个数 zrange 返回指定区间中的元素分数按照升序带上选项 WITHSCORES 会将分数也带上。 语法 zrange key start stop [withscores] 示例 命令有效版本1.2.0之后 时间复杂度OlogNM 返回值区间内的元素列表 zrevrange 返回指定区间中的元素分数按照降序带上WITHSCORES 可以显示分数。 语法 zrevrange key start stop [WITHSCORES] 示例 命令有效版本1.2.0之后 时间复杂度OlogNM 返回值区间内的元素列表 zrangebyscore 返回分数在 min 和 max 之间的分数默认情况下包含 min 和 max (该命令可能在6.2.0之后废弃并且功能合并到 zrange 中 语法 zrangebyscore key min max [WITHSCORES] 示例 排除边界 zpopmax 删除并返回分数最高的 count 个元素 语法 zpopmax key [count]     不写count 默认返回一个 示例 如果存在多个元素分数相同同时为最大值此时执行zpopmax命令仍然删除其中一个元素分数虽然是主要因素但是当分数相同时会按照 member 字符串的字典序决定先后。 命令有效版本5.0.0之后 时间复杂度OlogN* M 返回值分数和元素列表 bzpopmax  zpopmax的阻塞版本类似与 List 类型中的 blpop brpop。 有序集合也可以视为是一个“优先级队列”每个 key 都是一个有序集合阻塞也是在有序集合为空的时候出发当有其它客户端往有序集合中插入元素时获取元素停止阻塞。 语法 bzpopmax key [key..] timeout timeout 表示最多阻塞时长单位是s,支持小数形式0.1表示100ms 示例 客户端1 此时阻塞 客户端2,往key有序集合中插入数据 查看客户端1停止阻塞返回分数最大的数据 命令有效版本5.0.0之后 时间复杂度OlogN 返回值弹出的元素和分数         zpopmin 删除有序集合中分数最小的元素 语法 zpopmin key[count] 示例 命令有效版本5.0.0之后 时间复杂度OlogN* M 返回值分数和元素列表 bzpopmin zpopmin 的阻塞版本 语法 bzpopmin key[key...] timeout 示例 客户端1阻塞 客户端2添加元素 查看客户端1 命令有效版本5.0.0之后 时间复杂度OlogN 返回值分数和元素列表 zrank 返回指定元素的排名升序zrank得到的下标是从前往后算的 语法 zrank key member 示例 命令有效版本2.0.0之后 时间复杂度OlogN 返回值排名 zrevrank 返回指定的元素的排名降序 语法 zrevrank key member 示例 命令有效版本2.0.0之后 时间复杂度OlogN 返回值排名 zscore 返回指定 member 的分数 语法 zscore key member 示例 命令有效版本1.2.0之后 时间复杂度O1 返回值分数member 不存在返回nill zrem  删除指定的元素 语法 zrem key member[member...] 示例 命令有效版本1.2.0之后 时间复杂度OM*logN 返回值删除成功的 member 的个数 zremrangebyrank 删除指定区间中元素左闭右闭 语法 zremrange key start stop 示例 命令有效版本2.0.0之后 时间复杂度OMlogN M 是区间的元素个数 返回值本次操作删除的元素个数 zremrangebyscore 按照分数删除指定范围的元素左闭右闭 语法 zremrangebyscore key min max 示例 不排除边界 排除边界 命令有效版本1.2.0之后 时间复杂度OMlogN M 是区间的元素个数 返回值本次操作删除的元素个数 zincrby  为指定元素关联的分数添加指定值 语法 zincrby key increment member 示例   zincrby 不仅仅只修改分数也能移动元素为孩子保持整个有序集合始终保持升序。 命令有效版本1.2.0之后 时间复杂度OlogN 返回值添加后元素的分数 以上是有序集合内部的操作命令从 redis 6.2开始支持集合间操作即 交集 并集 差集对应的命令分别是 zinter  zunion  zdiff 。 由于小马的 redis 是 5版本因此这几个命令不做介绍原理和 Set 类型集合间操作相同版本匹配的烙铁可以尝试一波。 这里介绍另外两个集合间操作 zinterstore  求交集操作结果保存在另一个 key 中 语法 zinterstore destination numkeys key [key..] [WEIGHTS weight [weight...]] [AGGREGATE SUM | MIN | MAX] 解释一下上述一些选项 numkeys 整数描述了后面有几个key参与交集运算这里主要是为了明确后面的选项是从哪里开始避免选项和 keys 混淆 WEIGHTS 权重有序集合是带有分数的此处的权重相当于一个系数会乘以当前的分数。 [AGGREGATE SUM | MIN | MAX] 求交集时如果 member 相同进行合并之后的最终分数的计算方法sum 表示求和max 表示取最大min表示取最小。 示例 key1 和 key2中的元素 执行 zinterstore 命令 由于 key1 的zhangsan的分数是10乘以1还是10key2 的zhangsan的分数是15乘以2是30最终求和于是 key3 的zhangsan的分数就是 10 30 40 再来一个示例 不指定权重 命令有效版本2.0.0之后 时间复杂度O(N*K)O(M*log(M)) N 是输入的有序集合中, 最小的有序集合的元素个数; K 是输入了几个有序集合; M 是最终结果的有序集合的元素个数 返回值目标集合中的元素个数 zunionstore 求并集和 zinterstore 用法基本一致 这里不做介绍铁铁们自己来尝试眼过千遍不如手过一遍对吧 小提示 以上就是有序集合的相关命令。 2内部编码 有序集合的内部编码主要有两种 ziplist压缩列表skiplist跳表 当有序集合的元素个数小于 zset-max-ziplist-entries 配置默认128个同时每个元素的值都小于zset-max-ziplist-value 配置64字节时redis 会用ziplist 来存储节省空间。 当不满足 ziplist 条件时也就是元素过多或者单个元素的体积较大时会使用 skiplist 来进行存储。  上述配置文件在 redis.conf 依旧可以找到 对跳表不理解的铁子可以阅读以下文章进行理解 跳表Skip List-CSDN博客 3使用场景 zset 最关键的应用场景是排行榜系统。如下 1.微博热榜 2.游戏天梯排行 3.成绩排行 对于排行榜系统而言其关键要点就是用来排行的“分数”是实时变化的使用 zset 来完成上述操作非常简单。比如游戏天梯排行只需要把玩家信息和对应分数给放到有序集合中即可这样就会自动生成一个排行榜随时可以按照排行下标、按照分数进行范围查询随着分数的改变也可以方便比较zincrby 修改分数排行也会自动调整。 以上就是 redis 的 Zset 类型的相关介绍。 补充 渐进式遍历 在前面已经提到过keys 一次性把 redis 中的所有 key 都获取到这个操作比较危险可能一下得到太多的 key阻塞 redis 服务器。 通过渐进式遍历就可以做到既能够获取到所有的 key同时又不会阻塞 redis 服务器。这里的渐进式遍历并不是一次获取到所有的 key而是每一次执行一次命令只获取其中的一小部分这样的话就保证这次操作不会太卡要想得到所有的 key就需要遍历很多次了多次执行渐进式遍历命令即可。 渐进式遍历其实是一组命令这一组命令的使用方法是一样的其中代表命令是 scan 语法 scan cursor [MATCH pattern] [COUNT count] cursor 是指光标指向了当前遍历的位置光标设置成 0 表示这次遍历是从头开始获取cursor 不能理解成下标cursor 不是一个连续递增的整数它仅仅只是一个字符串而 redis 服务器知道这个光标对应的元素位置。 [MATCH pattern]  和 keys 的 pattern 一样。 [COUNT count] 限制此次遍历能够获取到多少个元素默认是10但是这里的 count 和 mysql 中的 limit 并不一样limit 是准确的限制获取的个数而 count 只是给 redis 服务器一个“提示/建议”写入的 count 和实际返回的 key 的个数不一定是完全相同的但是不会差很多。 示例 返回值的第一部分表示下次光标的位置为0表示结束第二部分是此次渐进式遍历获取到的 key 。 渐进式遍历在遍历过程中不会在服务器存储人任何状态信息此时的遍历是随时可以终止的不会对服务器产生任何的副作用。 渐进式遍历 scan 虽然解决了阻塞问题但是如果在遍历期间键有所变化增加、删除、修改可能导致遍历键的重复遍历或者遗漏。 二、过期策略以及单线程模型 2.1 过期策略 在前面介绍过的 expire 命令中什么没有印象了赶紧回去复习一下下会发现当设置了过期时间以后超过过期时间再查 key 发现这个 key 被删除了。 本小节就来介绍一下redis 的 key 的过期策略是什么实现的。 一个 redis 中可能同时存在很多很多 key这些 key 可能有很大一部分都有过期时间此时redis 服务器怎么知道哪些 key 已经过期要删除哪些 key 还没过期 如果直接遍历所有的 key 显然效率非常低是不可取行为。 redis 整体的策略是 1定期删除 每隔一定时间扫描一定数量的数据库的expires字典抽取其中一部分key进行验证过期时间并清除其中已经过期的key需要保证这个抽取的时间要足够快。 这里对于定期删除的时间有明确要求因为 redis 是单线程的程序主要的任务是处理客户端的命令如果扫描过期key的时间太长了就可能导致正常处理命令请求就阻塞了也就是产生了类似于 key * 这样的效果。 2惰性删除 假设一个key已经到过期时间了但是暂时还没有删除这个 key key 还存在当后面访问正好用到了此时这次访问就会让 redis 服务器触发删除 key 的操作同时返回一个 nil。 redis 同时使用了这两种过期策略 每隔100ms 就随机抽取一定数量的 key 来检查和删除。 在获取某个 key 的时候redis 会检查一下这个 key 如果设置了过期时间并且已经过期了此时就会删除。 具体内容可以查看 Redis 官方文档对于过期 key 给出的解释 EXPIRE | Redis 2.2 单线程模型 本小节主要介绍 redis 的单线程模型。 redis 只使用一个线程处理所有的命令请求。这里并不是说 redis 服务器进程内部只有一个线程其实也有多个线程只是多个线程都是在处理网络IO。 假设有当前场景 两个 redis 客户端同时针对 redis 服务器中的同一个 key 值进行操作此时在多线程下可能会发生线程安全问题。 博主之前的博客介绍过线程安全问题 线程安全问题-CSDN博客 幸运的是虽然上述客户端请求是“并发”的但是 redis 服务器由于是单线程模型保证了收到的这多个请求是串行执行的。即使多个请求同时到达 redis 服务器也是要先在队列中进行排队的等待 redis 服务器从队列中逐个取出里面的命令再执行从微观上将redis 服务器是串行执行这多个命令的。 举例来说这就相当于是学生时代每逢周内中午开饭当开饭铃声下课铃声响起时干饭人大军浩浩荡荡冲向食堂假设只有一个食堂且只有一个窗口此时从宏观上看一群人同时到达食堂并发执行微观上到了食堂以后需要在窗口前进行排队排到了才进行打饭串行执行 redis 能够使用单线程模型很好工作的原因主要是因为redis 的核心业务逻辑都是短平快的不太消耗 cpu 资源也就无需多核了。 2.3 Redis 效率为什么这么高 在前面的小节中介绍了 redis 是单线程模型那么铁铁们是否有这样的疑问 既然 redis 是单线程模型为什么相较于数据库MySQL它的执行效率如此之快 究其原因主要有以下几点 1. redis 访问内存数据库访问硬盘。 2. redis 的核心功能比数据库的核心功能更简单。     数据库对于数据的增删改查都有复杂的功能支持这样的功能势必会花费更大的开销。比如针对插入删除操作数据库有各种约束这些约束会导致数据库做额外的功能。而 redis干的活少 提供的功能相较于MySQL等数据库少了很多。 3.单线程模型避免了一些不必要的线程竞争开销。    redis 的每个基本操作都是短平快的也就是简单操作一下内存数据不是特别消耗 cpu 资源的操作因此即使搞多个线程也提升不大。 4. redis 处理网络 IO 的时候使用了 epoll 这样的 IO 多路复用机制。     通过 IO 多路复用机制就可以使得一个线程管理多个 socket。     针对 TCP 来说每次要服务一个客户端都需要给这个客户端安排一个 socket 。一个服务器服务多个客户端同时有很多个 socket但是这些 socket 并非每时每刻都在传输数据可能有些“摸鱼”的 socket很多情况下每个客户端和服务器之间的通信并不是很频繁因此不通信的 socket 都是出于静默状态同一时刻只有少数 socket 是活跃的。    对于 IO 多路复用C 可以直接使用 Linux 原生的 epoll api而 Java 可以使用 NIO (标准库提供的一组类底层就是封装了 epoll)。    举例简单解释一下 epoll     假设大四老学长小马今日要和寝室的两位室友买饭回寝室吃室友1简简单单一份蛋炒饭室友2热热的肉夹馍小马老马家的羊头。     此时想要解决带饭回寝室吃这个需求有如下几种解决方案     第一种小马决定跑腿先去买蛋炒饭等饭好了带上再去买肉夹馍等肉夹馍好了带上去买老马家的羊头等羊头好了以后带回寝室一起吃饭。     第二种 三人一起去买饭各自买各自的然后带回寝室。     第三种 小马又决定跑腿先去买蛋炒饭等蛋炒饭的过程去买肉夹馍买完肉夹馍马不停蹄奔向老马家的羊头。下单好了以后小马找了个位置坐了下来等待三家店的老板通知帅哥你的订单好了。     分析上述三种情况第一种相当于一个线程执行操作阻塞后等待执行效率最低第二种多个线程执行操作效率非常高但是系统开销大了第三种使用 IO 多路复用机制一个线程执行多个客户端操作效率非常高。     对于第三种情况来说能够高效完成这三件事的前提是这三件事的交互并不频繁大部分时间都在等而例子中老板通知帅哥你的订单好了对应的就是 epoll 事件通知/回调机制。      三、Java 客户端操作 Redis 本小结主要介绍Java语言的 Redis 客户端的使用方法。 首先来认识一下 redis 自定义的应用层协议RESP 官网链接如下Redis serialization protocol specification | Docs 这里翻译部分重点信息。  redis 的请求-响应模型是一问一答的形式也就是客户端给服务器发送一个请求服务器返回一个响应。 客户端给服务器发送的是 redis 命令也就是前面介绍的若干命令是以 bluk string 数组的形式发送的。  服务器返回的响应针对不同的命令返回结果不一样有的命令返回一个ok有的命令可能返回整数有的命令可能返回数组。 当了解了 redis 的 RESP 协议以后就可以实现客户端程序了。 Java 生态中封装 RESP 协议实现的 redis 的客户端是有很多的小马这里使用的是 jedisjedis 提供的 api 命令 和 redis 命令高度一致。 jedis 可以通过 maven 中央仓库下载。创建一个 Maven 项目引入依赖 !-- https://mvnrepository.com/artifact/redis.clients/jedis -- dependency     groupIdredis.clients/groupId     artifactIdjedis/artifactId     version4.4.6/version /dependency 在编写代码之前需要注意以下关键点 由于是在 windows 系统上idea通过 redis 客户端来访问 redis 服务器linux 云服务器需要通过云服务器的外网 IP 来访问到 linux 服务器如下图  这里只修改成外网 IP 还是不够的6379 端口默认是被云服务器的防火墙给保护起来的不能被外面访问到。但是防火墙一保护不光黑客用户自己也访问不到因此可以通过在云服务器后台防火墙开放6379端口使得用户可以访问到但是当 Redis 的端口一旦公开到网上就特别容易被入侵小马就被折磨过很多个日夜。 因此是否有方法既不用开放 redis 端口用户自己又能够通过外网访问。 答案是有的。 这里主要有两种方法 1直接让 java 程序也在 linux 上运行。      此时客户端和服务器在同一主机上就不涉及跨主机访问但是这就需要程序员自己将代码打成可执行的 jar 包然后把 jar 包拷贝到 linux 服务器上执行。但是上述这种操作手工实现比较麻烦虽然可以通过一些第三方插件来简化上述步骤但是实际操作还是比较麻烦。因此更推荐第二种方法。 2配置 ssh 端口转发隧道、端口映射把云服务器的 redis 端口映射到本地主机。       在 windows 主机上可以通过一些终端xshell、finallshell...远程登录到 linux 服务器此时终端登录到 linux 云服务上使用 ssh 协议基于 tcp 的应用层协议端口号默认是 22ssh 功能非常强大其中很重要的一个特性就是能够支持端口转发相当于通过 ssh 的22端口来传递其他端口数据。初衷是想通过 windows 主机访问云服务器的 6379 端口此时就可以构造一个特殊的 ssh 数据报把要访问的 redis 请求放到 ssh 数据报里如下图 这个数据报就会通过 22 端口发送给 linux 服务器服务器的 ssh 服务器程序就能够解析出上述的数据报然后把数据报交给 6379 端口的程序。 由于一个 linux 主机上存在的服务器有很多ssh 也可能需要给多个端口传递数据为了区分不同的端口往往会把服务器的端口在本地用另外一个端口进行表示。比如想访问 linux 服务器上的 6379 端口就可以借助 ssh 协议将这个 6379 端口映射到 windows 主机上的端口假设8888端口如下图 此时客户端的程序如果访问 127.0.0.1:8888 就相当于是访问到 linux 服务器的 6379 端口了。 因此只需要进行简单的配置后续把云服务器的端口当成一个本地的端口使用即可。 具体配置操作如下以 finalshell为例 当 ssh 连接上了以后端口转发才会生效ssh 断开端口转发失效可以使用 netstat 命令查看本地 8888 端口是否被绑定。 当断开 ssh 连接会发现 8888 端口未被绑定 需要注意当配置了端口转发之后要断开之前的连接重新连接才能生效。 通过上述操作在后续 Java 代码中通过 127.0.0.18888 就能操作到云服务器的 redis 了同时外面的客户端是无法直接访问到云服务器的 6379 的。 经过上述铺垫就可以开始紧张刺激的敲代码环节了。 先写一个Demo验证 import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;/*** author 26568* date 2024-05-04 20:03*/ public class RedisDemo {public static void main(String[] args) {// 连接到 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);// 从 redis 连接池中取出一个连接连接用完后需要释放// 此处的释放不一定是真的关闭 tcp 连接而是放回到池子中// 这里使用 try with resource 语法进行资源释放try(Jedis jedis jedisPool.getResource()) {String pong jedis.ping();System.out.println(pong);}} }查看执行结果 说明程序成功运行。 这里还需要注意的一点是除了配置 ssh 端口映射之外要修改 redis.conf 中的配置要配置绑定的ip以及关闭保护模式 接下来演示 redis 的一些通用命令 get 和 set import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.params.SetParams;/*** author 26568* date 2024-05-04 20:03*/ public class RedisDemo {public static void main(String[] args) {// 连接到 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try(Jedis jedis jedisPool.getResource()) {test1(jedis);}}private static void test1(Jedis jedis) {System.out.println(get 和 set 的使用);// 清空数据库避免上一组残留的测试数据影响这一组的测试结果jedis.flushAll();jedis.set(key,111);jedis.set(key2,222);// 还可以设置过期时间SetParams setParams new SetParams();// 指定10 s后过期setParams.ex(10);// 当key存在的时候进行修改setParams.xx();jedis.set(key,333,setParams);String value jedis.get(key);System.out.println(value value);} }exists 和 del import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.params.SetParams;/*** author 26568* date 2024-05-04 20:03*/ public class RedisDemo {public static void main(String[] args) {// 连接到 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try(Jedis jedis jedisPool.getResource()) {test1(jedis);}}private static void test1(Jedis jedis) {System.out.println(exists 和 del 的使用);// 清空数据库jedis.flushAll();jedis.set(key1,111);jedis.set(key2,222);jedis.set(key3,333);boolean result jedis.exists(key1);System.out.println(reslut result);// 删除 key// del 支持删除多个 keylong ret jedis.del(key,key1,key2);System.out.println(ret ret);result jedis.exists(key3);System.out.println(reslut result);} }keys 命令 import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.params.SetParams;import java.util.Set;/*** author 26568* date 2024-05-04 20:03*/ public class RedisDemo {public static void main(String[] args) {// 连接到 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try(Jedis jedis jedisPool.getResource()) {test1(jedis);}}private static void test1(Jedis jedis) {System.out.println(keys 的使用);// 清空数据库jedis.flushAll();jedis.set(key1,111);jedis.set(hello,world);SetParams params new SetParams();params.ex(20);params.nx();jedis.set(three,00000,params);// 使用 keys 命令// redis 的 key 是不能重复的并且顺序没有要求SetString set1 jedis.keys(*);System.out.println(set1: set1);SetString set2 jedis.keys(k?y1);System.out.println(set2: set2);} }expire 和  ttl import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.params.SetParams;import java.util.Set;/*** author 26568* date 2024-05-04 20:03*/ public class RedisDemo {public static void main(String[] args) {// 连接到 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try(Jedis jedis jedisPool.getResource()) {test1(jedis);}}private static void test1(Jedis jedis) {System.out.println(expire 和 ttl 的使用);// 清空数据库jedis.flushAll();jedis.set(key1,value1);jedis.expire(key1,5);long ttl jedis.ttl(key1);System.out.println(ttl: ttl);// 阻塞 3 秒try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}ttl jedis.ttl(key1);System.out.println(ttl: ttl);} }type  import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.params.SetParams;import java.util.HashMap; import java.util.Map; import java.util.Set;/*** author 26568* date 2024-05-04 20:03*/ public class RedisDemo {public static void main(String[] args) {// 连接到 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try(Jedis jedis jedisPool.getResource()) {test1(jedis);}}private static void test1(Jedis jedis) {System.out.println(expire 和 ttl 的使用);// 清空数据库jedis.flushAll();// String 类型jedis.set(key1,value1);String type jedis.type(key1);System.out.println(type type);// List 类型jedis.lpush(key2,111,222,333);type jedis.type(key2);System.out.println(type type);// Hash 类型MapString,String map new HashMap();map.put(f1,hhh);map.put(f2,aaaa);jedis.hset(key3,map);type jedis.type(key3);System.out.println(type type);// 集合类型jedis.sadd(key4,zhangsan,lisi);type jedis.type(key4);System.out.println(type type);// 有序集合类型MapString,Double scoreMembers new HashMap();scoreMembers.put(xiaoma,99.45);scoreMembers.put(libai,88.50);jedis.zadd(key5,scoreMembers);type jedis.type(key5);System.out.println(type type);} }接下来介绍一下 String 类型的一些命令 1.get 和 set 2.mget 和 mset 3.getrange 和 setrange 4.append 5.incr 和 decr  mget 和 mset import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.List;/*** author 26568* date 2024-05-05 11:00*/ public class RedisString {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try(Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(mget 和 mset);// 清空数据库jedis.flushAll();jedis.mset(key1,111,key2,222,key3,333);// 不存在的 key 会返回 nullListString reslut jedis.mget(key1,key2,key3,key4);System.out.println(result: reslut);} }getrange 和 setrange import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.List;/*** author 26568* date 2024-05-05 11:00*/ public class RedisString {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try(Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(getrange 和 setrange);// 清空数据库jedis.flushAll();jedis.set(key,abcdefghijklmn);// 获取范围内(闭区间)的字符串String reslut jedis.getrange(key,3,6);System.out.println(result: reslut);// 从指定位置开始修改字符串jedis.setrange(key,0,world);reslut jedis.get(key);System.out.println(result: reslut);} }append import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.List;/*** author 26568* date 2024-05-05 11:00*/ public class RedisString {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try(Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(append);// 清空数据库jedis.flushAll();jedis.set(key,hello);// 拼接jedis.append(key,world);// 获取完整字符串String result jedis.getrange(key,0,-1);System.out.println(resut: result);} }incr 和 decr  import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.List;/*** author 26568* date 2024-05-05 11:00*/ public class RedisString {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try(Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(incr 和 decr);// 清空数据库jedis.flushAll();jedis.set(key,100);// 1long result jedis.incr(key);System.out.println(result: result);String value jedis.get(key);System.out.println(value: value);// -1result jedis.decr(key);System.out.println(result: result);value jedis.get(key);System.out.println(value: value);} }List 类型的命令 1.lpush 和 lrange 2.rpush 、rpop、lpop 3.blpop、brpop 4.llen lpush 和 lrange import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.List;/*** author 26568* date 2024-05-05 11:17*/ public class RedisList {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try (Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(lpush 和 lrange);// 清空数据库jedis.flushAll();jedis.lpush(key,111,222,333,444);ListString reslut jedis.lrange(key,0,2);System.out.println(result: reslut);} }rpush 、rpop、lpop import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.List;/*** author 26568* date 2024-05-05 11:17*/ public class RedisList {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try (Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(rpush 、rpop、lpop);// 清空数据库jedis.flushAll();jedis.rpush(key,111,222,333);ListString result jedis.lrange(key,0,-1);System.out.println(result: result);String value1 jedis.rpop(key);System.out.println(value1: value1);String value2 jedis.lpop(key);System.out.println(value2: value2);} }blpop、brpop import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.List;/*** author 26568* date 2024-05-05 11:17*/ public class RedisList {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try (Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(blpop 和 brpop);// 清空数据库jedis.flushAll();// 返回结果是一个二元组一个是从哪个 key对应的list删除一个是要删除的元素是什么ListString results jedis.blpop(3,key);System.out.println(results[0]: results.get(0));System.out.println(results[1]: results.get(1));} }这里报空指针异常是因为3秒后返回一个空list因此会发生空指针异常。 设置阻塞时间久一点在这个期间往 key 中插入元素。 此时阻塞停止返回结果 brpop 和 blpop 操作几乎一样这里不在赘述。  llen import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.List;/*** author 26568* date 2024-05-05 11:17*/ public class RedisList {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try (Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(llen);// 清空数据库jedis.flushAll();jedis.lpush(key,111,222,333);long len jedis.llen(key);System.out.println(len len);} }接下来介绍 Set 类型的一些命令 1.sadd 和 smembers 2.sismember 3.scard 4.spop 5.sinter 和 sinterstore sadd 和 smembers import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.Set;/*** author 26568* date 2024-05-05 19:29*/ public class RedisSet {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try (Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(sadd 和 smembers);// 清空当前数据库jedis.flushDB();// 不会添加重复元素long result jedis.sadd(key,zhangsan,lisi,wangwu,wangwu);System.out.println(result result);SetString list jedis.smembers(key);System.out.println(list: list);} }sismember import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.Set;/*** author 26568* date 2024-05-05 19:29*/ public class RedisSet {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try (Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(sismember);// 清空当前数据库jedis.flushDB();// 不会添加重复元素long result jedis.sadd(key,zhangsan,lisi,wangwu,wangwu);System.out.println(result result);boolean flag jedis.sismember(key,zhangsan);System.out.println(flag: flag);flag jedis.sismember(key,hhhhhh);System.out.println(flag: flag);} }scard import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.Set;/*** author 26568* date 2024-05-05 19:29*/ public class RedisSet {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try (Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(scard);// 清空当前数据库jedis.flushDB();// 不会添加重复元素long result jedis.sadd(key,zhangsan,lisi,wangwu,wangwu);System.out.println(result result);long len jedis.scard(key);System.out.println(len: len);} }spop import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.Set;/*** author 26568* date 2024-05-05 19:29*/ public class RedisSet {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try (Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(spop);// 清空当前数据库jedis.flushDB();// 不会添加重复元素long count jedis.sadd(key,zhangsan,lisi,wangwu,wangwu);System.out.println(result count);// 这里随机取出 memberString result jedis.spop(key);System.out.println(result: result);} }sinter 和 sinterstore import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.Set;/*** author 26568* date 2024-05-05 19:29*/ public class RedisSet {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try (Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(sinter 和 sinterstore);// 清空当前数据库jedis.flushDB();// 不会添加重复元素jedis.sadd(key1,zhangsan,lisi,wangwu,wangwu);jedis.sadd(key2,wangwu,zhangsan,xiaoma);SetString results jedis.sinter(key1,key2);System.out.println(results: results);long len jedis.sinterstore(key3,key1,key2);System.out.println(len: len);SetString members jedis.smembers(key3);System.out.println(members: members);} }接下来介绍 Hash 类型 1.hset 和 hget 2.hexists 和 hdel 3.hkeys 和 hvals 4.hmget 和 hmset hset 和 hget import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.HashMap; import java.util.Map;/*** author 26568* date 2024-05-05 19:48*/ public class RedisHash {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try(Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(hset 和 hget);// 清空数据库jedis.flushAll();jedis.hset(key,f1,111);// 还可以通过map添加MapString,String hash new HashMap();hash.put(f2,222);jedis.hset(key,hash);String value jedis.hget(key,f1);System.out.println(value value);} }hexists 和 hdel import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.HashMap; import java.util.Map;/*** author 26568* date 2024-05-05 19:48*/ public class RedisHash {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try(Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(hexists 和 hdel);// 清空数据库jedis.flushAll();jedis.hset(key,f1,111);boolean result jedis.hexists(key,f1);System.out.println(result: result);long len jedis.hdel(key,f1,f2);System.out.println(len : len);} }hkeys 和 hvals import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set;/*** author 26568* date 2024-05-05 19:48*/ public class RedisHash {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try(Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(hkeys 和 hvals);// 清空数据库jedis.flushAll();jedis.hset(key,f1,111);jedis.hset(key,f2,222);SetString fields jedis.hkeys(key);ListString vals jedis.hvals(key);System.out.println(fields: fields);System.out.println(vals: vals);} }hmget 和 hmset import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool;import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set;/*** author 26568* date 2024-05-05 19:48*/ public class RedisHash {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try(Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(hmset 和 hmget);// 清空数据库jedis.flushAll();MapString,String hash new HashMap();hash.put(f1,111);hash.put(f2,222);// 只能传mapjedis.hmset(key,hash);ListString results jedis.hmget(key,f1,f2);System.out.println(results: results);} }最后介绍一下 Zset 类型的一些命令 1.zadd 和 zrange 2.zcard 和 zscore 3.zrem 和 zrank zadd 和 zrange import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.resps.Tuple;import java.util.HashMap; import java.util.List; import java.util.Map;/*** author 26568* date 2024-05-05 20:09*/ public class RedisZSet {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try (Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(zadd 和 zrange);// 清空数据库jedis.flushAll();jedis.zadd(key,88.5,zhangsan);// 也可以使用 mapMapString,Double map new HashMap();map.put(lisi,65.2);map.put(zhaoliu,46.6);jedis.zadd(key,map);ListString members jedis.zrange(key,0,-1);System.out.println(members: members);ListTuple memberWithScores jedis.zrangeWithScores(key,0,2);System.out.println(memberWithScores: memberWithScores);// 获取单个元素String member memberWithScores.get(0).getElement();double score memberWithScores.get(0).getScore();System.out.println(member: member, scorescore);} }zcard 和 zscore import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.resps.Tuple;import java.util.HashMap; import java.util.List; import java.util.Map;/*** author 26568* date 2024-05-05 20:09*/ public class RedisZSet {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try (Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(zcard 和 zscore);// 清空数据库jedis.flushAll();jedis.zadd(key,88.5,zhangsan);// 也可以使用 mapMapString,Double map new HashMap();map.put(lisi,65.2);map.put(zhaoliu,46.6);jedis.zadd(key,map);long len jedis.zcard(key);System.out.println(len len);Double score jedis.zscore(key,zhangsan);System.out.println(score score);} }zrem 和 zrank import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.resps.Tuple;import java.util.HashMap; import java.util.List; import java.util.Map;/*** author 26568* date 2024-05-05 20:09*/ public class RedisZSet {public static void main(String[] args) {// 连接 redis 服务器JedisPool jedisPool new JedisPool(tcp://127.0.0.1:8888);try (Jedis jedis jedisPool.getResource()) {test(jedis);}}private static void test(Jedis jedis) {System.out.println(zrem 和 zrank);// 清空数据库jedis.flushAll();jedis.zadd(key,88.5,zhangsan);// 也可以使用 mapMapString,Double map new HashMap();map.put(lisi,65.2);map.put(zhaoliu,46.6);jedis.zadd(key,map);long n jedis.zrem(key,zhangsan);System.out.println(n n);ListTuple memberWithScores jedis.zrangeWithScores(key,0,-1);System.out.println(memberWithScores: memberWithScores);// 使用包装类型接收如果不存在 返回 nullnull 无法转成 long 基本数据类型Long index jedis.zrank(key,zhaoliu);System.out.println(index index);} }以上就是 Java 客户端操作 Redis 的知识点介绍关于命令只介绍了一些比较重要的命令还有很多命令没有涉及到铁铁们可以自己多多尝试 。 四、Spring 操作 Redis 接下来就是本篇最后一节。 先创一个 Spring 项目 这里需要注意添加如下依赖 在配置文件中添加如下配置 创建一个 Controller 类如下 Spring 是通过StringRedisTemplate 来操作 redis。 最原始的提供的类是 RedisTemplateStringRedisTemplate 是 RedisTemplate 的子类专门用来处理文本数据的而 RedisTemplate 既可以处理二进制数据又可以处理文本数据ByteArrayRedisTemplate 用来处理二进制数据。 StringTemplate 这个类提供的方法相比于之前的 Jedis 中的各种方法存在比较大的差异。主要是通过如下一些方法获得操作 Reids 基本数据类型的对象 当获取到这些对象以后就可以使用这些对象提供的方法操作 redis。 String 类型命令 package com.example.demo;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;/*** 测试 redis 的各种方法都通过这个 Controller 提供的 http 接口来触发* author 26568* date 2024-05-06 19:58*/ RestController public class RedisController {Autowiredprivate StringRedisTemplate redisTemplate;GetMapping(/testString)public String testString() {redisTemplate.opsForValue().set(key1,111);redisTemplate.opsForValue().set(key2,222);redisTemplate.opsForValue().set(key3,333);String value redisTemplate.opsForValue().get(key2);System.out.println(value value);return OK,String;}}输入网址 查看控制台打印信息 List 类型命令 提供的命令如下 在之前使用 Jedis 操作各个类型时第一步操作是清除数据库RdisTemplate 主要是通过提供的execute 方法来执行 Redis 的原生命令此时就可以执行清除数据库操作。 execute 的方法是一个函数式接口相当于一个回调函数在回调里写要执行的 redis 的命令这个回调就会被 RedisTemplate 内部进行执行。 这里的 RedisConnection 就代表了 Redis 连接对标Jedis 对象。 代码如下 package com.example.demo;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;/*** 测试 redis 的各种方法都通过这个 Controller 提供的 http 接口来触发* author 26568* date 2024-05-06 19:58*/ RestController public class RedisController {Autowiredprivate StringRedisTemplate redisTemplate;GetMapping(/testList)public String testString() {// 清除数据库// 此处使用 lambda 表达式redisTemplate.execute((RedisConnection connection) - {// execute 要求回调方法中必须写 return 语句// 这个回调返回的对象就会作为 execute 本身的返回值// 通过connection 就可以执行 redis 的一些原生命令类似 Jedisconnection.flushAll();return null;});redisTemplate.opsForList().leftPush(key,111);redisTemplate.opsForList().leftPush(key,222);redisTemplate.opsForList().leftPush(key,333);String value redisTemplate.opsForList().rightPop(key);System.out.println(value value);return OK,List;}}输入网址 查看控制台打印信息 Set 类型命令 package com.example.demo;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;import java.util.Set;/*** 测试 redis 的各种方法都通过这个 Controller 提供的 http 接口来触发* author 26568* date 2024-05-06 19:58*/ RestController public class RedisController {Autowiredprivate StringRedisTemplate redisTemplate;GetMapping(/testSet)public String testString() {// 清空数据库redisTemplate.execute((RedisConnection connection) - {connection.flushAll();return null;});// 添加元素 相当于 sadd 命令redisTemplate.opsForSet().add(key,111,222,333);// 获取所有 member 相当于 smembers 命令SetString results redisTemplate.opsForSet().members(key);System.out.println(results: results);// 判断在 key 中是否有member 相当于sismember 命令 Boolean exists redisTemplate.opsForSet().isMember(key,111);System.out.println(exists: exists);// Set 中 member 的个数 相当于 scard命令Long count redisTemplate.opsForSet().size(key);System.out.println(count: count);// 删除 member 相当于srem 命令redisTemplate.opsForSet().remove(key,111,333);results redisTemplate.opsForSet().members(key);System.out.println(results: results);return OK,Set;}}输入网址 查看控制台打印信息 Hash 类型 package com.example.demo;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;import java.util.Set;/*** 测试 redis 的各种方法都通过这个 Controller 提供的 http 接口来触发* author 26568* date 2024-05-06 19:58*/ RestController public class RedisController {Autowiredprivate StringRedisTemplate redisTemplate;GetMapping(/testHash)public String testString() {// 清空数据库redisTemplate.execute((RedisConnection connection) - {connection.flushAll();return null;});// 添加元素 相当于 hset 命令redisTemplate.opsForHash().put(key,f1,111);redisTemplate.opsForHash().put(key,f2,222);redisTemplate.opsForHash().put(key,f3,333);// 获取值(返回的是 Object 类型需要转换 相当于 hget 命令String value (String) redisTemplate.opsForHash().get(key,f2);System.out.println(value value);// 判断field是否存在 相当于 hexistsBoolean exists redisTemplate.opsForHash().hasKey(key,f3);System.out.println(exists: exists);// 获取field 个数 相当于 hlenLong count redisTemplate.opsForHash().size(key);System.out.println(count count);// 删除 field 相当于 hdelredisTemplate.opsForHash().delete(key,f1,f2);count redisTemplate.opsForHash().size(key);System.out.println(count count);return OK,Hash;}}输入网址 查看控制台打印信息 ZSet 类型 package com.example.demo;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ZSetOperations; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;import java.util.Set;/*** 测试 redis 的各种方法都通过这个 Controller 提供的 http 接口来触发* author 26568* date 2024-05-06 19:58*/ RestController public class RedisController {Autowiredprivate StringRedisTemplate redisTemplate;GetMapping(/testZSet)public String testString() {// 清空数据库redisTemplate.execute((RedisConnection connection) - {connection.flushAll();return null;});// 添加元素 相当于 zadd 命令redisTemplate.opsForZSet().add(key,zhangsan,88.1);redisTemplate.opsForZSet().add(key,lisi,77.5);redisTemplate.opsForZSet().add(key,wangwu,65.41);// 获取区间内的 member 相当于 zrange 命令SetString members redisTemplate.opsForZSet().range(key,0,-1);System.out.println(members: members);// 获取区间内的 member 包括分数 相当于 zrange key stop stop withscoresSetZSetOperations.TypedTupleString memberWithScores redisTemplate.opsForZSet().rangeWithScores(key,0,-1);System.out.println(memberWithScores: memberWithScores);// 根据 member 获取 score 相当于 zscore 命令Double score redisTemplate.opsForZSet().score(key,lisi);System.out.println(score score);// 删除 member 相当于 zrem 命令redisTemplate.opsForZSet().remove(key,zhangsan);// 获取 member 个数 相当于 zcard 命令Long size redisTemplate.opsForZSet().size(key);System.out.println(size: size);// 获取 member 下标 相当于 zrank 命令Long rank redisTemplate.opsForZSet().rank(key,lisi);System.out.println(rank rank);return OK,ZSet;}}输入网址 查看控制台打印信息; 以上就是 Spring 操作 Redis 的简单命令介绍。 详细的命令可以查看官网 https://github.com/spring-projects/spring-data-redis 以上就是本篇博客的所有内容如有帮助倍感欣喜如有错误烦请指正。 Redis 三部曲的最后一曲敬请期待疯狂写作ing
http://www.dnsts.com.cn/news/277542.html

相关文章:

  • 苏州网站网站建设有口碑的网站建设
  • 网站建设专业导航网站wordpress获取首页id
  • 网站建设费用怎么做分录建设网站建设多少钱
  • 网站空间购买哪家好中国第一作文网官网
  • 企业网站源码免费带数据库东莞网站建设哪家
  • 北京的餐饮网站建设化学产品在哪个网站做推广最好
  • pycharm 网站开发软件开发专业就业
  • 自己做视频会员网站怎样开电商平台
  • 怎么做网站投放广告的代理商软件工程名词解释
  • 陶瓷网站策划书如何让网站被谷歌收录
  • 瓷器网站怎么做葫芦岛建设信息网站
  • 网店代运营就是个坑百度seo网站优化怎么做
  • 如何做区块链网站宁波seo基础入门
  • 制作好的网页怎么变成网站网站 app微信三合一
  • 网站开发技术现状几何背景生成网站
  • 有哪些档案网站wordpress 文档管理系统
  • 北京网站建立优化关键词方法
  • 网站开发 前端 外包wordpress主题seven柒比贰
  • 服务外包网站设计营销型网站域名
  • 织梦如何做几种语言的网站口碑营销的成功案例
  • 可以做试卷的网站英语wordpress插件云采集
  • 三亚做网站哪家好湖南企业竞价优化服务
  • 易企营销型网站建设企业做wps的网站赚钱
  • 昌平网站设计个人网页背景图片
  • 做外贸 访问国外网站 怎么办服务app开发公司
  • 如何设计营销型网站建设青岛建站模板制作
  • 网站优化自己做该怎么做用织梦做网站调用乱码
  • 沈阳网站维护网站建站哪个公司好一点
  • 惠州网站建设技术外包网站开发详细设计模板
  • 百度网站建设目标动易网站建设工作室