Redis6快速入门(二)

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis6快速入门(二)

四、配置文件介绍



4.1 Units单位


配置大小单位,开头定义了一些基本的度量单位,只支持bytes,不支持bit


大小写不敏感


17.png


4.2 INCLUDES包含


18.png


类似jsp中的include,多实例的情况可以把公用的配置文件提取出来


4.3 网络相关配置


4.3.1 bind

默认情况bind=127.0.0.1只能接受本机的访问请求


不写的情况下,无限制接受任何ip地址的访问


生产环境肯定要写你应用服务器的地址;服务器是需要远程访问的,所以需要将其注释掉


如果开启了protected-mode,那么在没有设定bind ip且没有设密码的情况下,Redis只允许接受本机的响应


保存配置,停止服务,重启启动查看进程,不再是本机访问了。


19.png


4.3.2 protected-mode

将本机访问保护模式设置 no


20.png


4.3.3 port

端口号,默认 6379

21.png


4.3.4 timeout

一个空闲的客户端维持多少秒会关闭,0表示关闭该功能。即永不关闭


22.png


4.3.5 tcp-keepalive

对访问客户端的一种心跳检测,每个n秒检测一次。


单位为秒,如果设置为0,则不会进行Keepalive检测,建议设置成60


23.png


4.4 GENERAL通用


4.4.1 daemonize

是否为后台进程,设置为yes


守护进程,后台启动


24.png


4.4.2 pidfile

存放pid文件的位置,每个实例会产生一个不同的pid文件


25.png


4.4.3 loglevel

指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为notice


四个级别根据使用阶段来选择,生产环境选择notice 或者warning


26.png


4.5 SECURITY安全


4.5.1 设置密码

27.png


访问密码的查看、设置和取消


在命令中设置密码,只是临时的。重启redis服务器,密码就还原了。


永久设置,需要再配置文件中进行设置。


28.png


4.6 LIMITS限制


4.6.1 maxclients


设置redis同时可以与多少个客户端进行连接。

默认情况下为10000个客户端。

如果达到了此限制,redis则会拒绝新的连接请求,并且向这些连接请求方发出“max number of clients reached”以作回应。


29.png

4.6.2 maxmemory

建议必须设置,否则,将内存占满,造成服务器宕机


设置redis可以使用的内存量。一旦到达内存使用上限,redis将会试图移除内部数据,移除规则可以通过maxmemory-policy来指定。


如果redis无法根据移除规则来移除内存中的数据,或者设置了“不允许移除”,那么redis则会针对那些需要申请内存的指令返回错误信息,比如SET、LPUSH等。


但是对于无内存申请的指令,仍然会正常响应,比如GET等。如果你的redis是主redis(说明你的redis有从redis),那么在设置内存使用上限时,需要在系统中留出一些内存空间给同步队列缓存,只有在你设置的是“不移除”的情况下,才不用考虑这个因素。


30.png


4.6.3 maxmemory-policy

volatile-lru:使用LRU算法移除key,只对设置了过期时间的键;(最近最少使用)

allkeys-lru:在所有集合key中,使用LRU算法移除key

volatile-random:在过期集合中移除随机的key,只对设置了过期时间的键

allkeys-random:在所有集合key中,移除随机的key

volatile-ttl:移除那些TTL值最小的key,即那些最近要过期的key

noeviction:不进行移除。针对写操作,只是返回错误信息


31.png


五、Redis的发布和订阅


Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。


Redis 客户端可以订阅任意数量的频道。


客户端可以订阅频道如下图


32.png


当给这个频道发布消息后,消息就会发送给订阅的客户端


33.png


5.1 测试

打开一个客户端订阅channel1


SUBSCRIBE channel1


34.png


打开另一个客户端,给channel1发布消息hello


35.png


返回的1是订阅者数量


打开第一个客户端可以看到发送的消息


36.png


注:发布的消息没有持久化,如果在订阅的客户端收不到hello,只能收到订阅后发布的消息


六、Redis新数据类型


6.1 Bitmaps


现代计算机用二进制(位) 作为信息的基础单位, 1个字节等于8位, 例如“abc”字符串是由3个字节组成, 但实际在计算机存储时将其用二进制表示, “abc”分别对应的ASCII码分别是97、 98、 99, 对应的二进制分别是01100001、 01100010和01100011,如下图


37.png


合理地使用操作位能够有效地提高内存使用率和开发效率。


Redis提供了Bitmaps这个“数据类型”可以实现对位的操作:


(1) Bitmaps本身不是一种数据类型, 实际上它就是字符串(key-value) , 但是它可以对字符串的位进行操作。


(2) Bitmaps单独提供了一套命令, 所以在Redis中使用Bitmaps和使用字符串的方法不太相同。 可以把Bitmaps想象成一个以位为单位的数组, 数组的每个单元只能存储0和1, 数组的下标在Bitmaps中叫做偏移量。


38.png


6.1.1 命令

setbit


(1)格式


setbit设置Bitmaps中某个偏移量的值(0或1)


39.png


*offset:偏移量从0开始


(2)实例


每个独立用户是否访问过网站存放在Bitmaps中, 将访问的用户记做1, 没有访问的用户记做0, 用偏移量作为用户的id。


设置键的第offset个位的值(从0算起) , 假设现在有20个用户,userid=1, 6, 11, 15, 19的用户对网站进行了访问, 那么当前Bitmaps初始化结果如图


40.png


unique:users:20201106代表2020-11-06这天的独立访问用户的Bitmaps


41.png


注:


很多应用的用户id以一个指定数字(例如10000) 开头, 直接将用户id和Bitmaps的偏移量对应势必会造成一定的浪费, 通常的做法是每次做setbit操作时将用户id减去这个指定数字。


在第一次初始化Bitmaps时, 假如偏移量非常大, 那么整个初始化过程执行会比较慢, 可能会造成Redis的阻塞。


2、getbit


(1)格式


getbit<key><offset>获取Bitmaps中某个偏移量的值


42.png


获取键的第offset位的值(从0开始算)


(2)实例


获取id=8的用户是否在2020-11-06这天访问过, 返回0说明没有访问过:


43.png


注:因为100根本不存在,所以也是返回0


3、bitcount


统计字符串被设置为1的bit数。一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的位上进行。start 和 end 参数的设置,都可以使用负数值:比如 -1 表示最后一个位,而 -2 表示倒数第二个位,start、end 是指bit组的字节的下标数,二者皆包含。


(1)格式


bitcount<key>[start end] 统计字符串从start字节到end字节比特值为1的数量


44.png


(2)实例


计算2022-11-06这天的独立访问用户数量


45.png


start和end代表起始和结束字节数, 下面操作计算用户id在第1个字节到第3个字节之间的独立访问用户数, 对应的用户id是11, 15, 19。


46.png


6.2 HyperLogLog


在工作当中,我们经常会遇到与统计相关的功能需求,比如统计网站PV(PageView页面访问量),可以使用Redis的incr、incrby轻松实现。


但像UV(UniqueVisitor,独立访客)、独立IP数、搜索记录数等需要去重和计数的问题如何解决?这种求集合中不重复元素个数的问题称为基数问题。


解决基数问题有很多种方案:


(1)数据存储在MySQL表中,使用distinct count计算不重复个数


(2)使用Redis提供的hash、set、bitmaps等数据结构来处理


以上的方案结果精确,但随着数据不断增加,导致占用空间越来越大,对于非常大的数据集是不切实际的。


什么是基数?


比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。


6.2.1 命令


1、pfadd


(1)格式


pfadd <key>< element> [element ...] 添加指定元素到 HyperLogLog 中


47.png


(2)实例


48.png


将所有元素添加到指定HyperLogLog数据结构中。如果执行命令后HLL估计的近似基数发生变化,则返回1,否则返回0。


2、pfcount


(1)格式


pfcount<key> [key ...] 计算HLL的近似基数,可以计算多个HLL,比如用HLL存储每天的UV,计算一周的UV可以使用7天的UV合并计算即可


49.png


(2)实例


50.png


3、pfmerge


(1)格式


pfmerge<destkey><sourcekey> [sourcekey ...] 将一个或多个HLL合并后的结果存储在另一个HLL中,比如每月活跃用户可以使用每天的活跃用户来合并计算可得


51.png


七、Jedis测试


7.1 导包

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.3.0</version>
</dependency>


7.2 各种测试

package com.caq.jedis;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import java.util.List;
import java.util.Set;
public class JedisDemo1 {
    public static void main(String[] args) {
        //创建jedis对象
        Jedis jedis = new Jedis("172.20.10.9", 6379);
        //测试
        String ping = jedis.ping();
        System.out.println(ping);
    }
    //    操作zset
    @Test
    public void demo05() {
        Jedis jedis = new Jedis("172.20.10.9", 6379);
        jedis.zadd("china",100d,"shanghai");
        Set<String> china = jedis.zrange("china", 0, -1);
        System.out.println(china);
        jedis.close();
    }
    // 操作hash
    @Test
    public void demo04() {
        Jedis jedis = new Jedis("172.20.10.9", 6379);
        jedis.hset("demo04", "age", "20");
        String hget = jedis.hget("demo04", "age");
        System.out.println(hget);
        jedis.close();
    }
    //    操作set
    @Test
    public void demo03() {
        Jedis jedis = new Jedis("172.20.10.9", 6379);
        jedis.sadd("demo03", "lucy");
        jedis.sadd("demo03", "monkey");
        Set<String> name = jedis.smembers("demo03");
        System.out.println(name);
        jedis.close();
    }
    //操作list
    @Test
    public void demo02() {
        Jedis jedis = new Jedis("172.20.10.9", 6379);
        jedis.lpush("demo02", "lucy", "jack", "tom");
        List<String> key1 = jedis.lrange("demo02", 0, -1);
        System.out.println(key1);
        jedis.close();
    }
    //操作key
    @Test
    public void demo1() {
        //创建redis对象
        Jedis jedis = new Jedis("172.20.10.9", 6379);
//        Set<String> keys = jedis.keys("*");
//        keys.forEach(x-> System.out.println(x));
//        添加
//        jedis.set("name","jack");
//        String name = jedis.get("name");
//        添加多个key
        jedis.mset("k1", "v1", "k2", "v2");
        List<String> mget = jedis.mget("k1", "k2");
        System.out.println(mget);
        jedis.close();
    }
}


7.3 连接Redis注意事项


禁用Linux的防火墙:Linux(CentOS7)里执行命令


systemctl stop/disable firewalld.service


redis.conf中注释掉bind 127.0.0.1 ,然后 protected-mode no


7.4 手机验证码实例


要求:


1、输入手机号,点击发送后随机生成6位数字码,2分钟有效


2、输入验证码,点击验证,返回成功或失败


3、每个手机号每天只能输入3次


package com.caq.jedis;
import redis.clients.jedis.Jedis;
import java.util.Random;
public class PhoneCode {
    public static void main(String[] args) {
        //模拟验证码发送
//        verifyCode("342352132");
        //校验
        getRedisCode("342352132", "833731");
    }
    //1 生成6位数字验证码
    public static String getCode() {
        Random random = new Random();
        String code = "";
        for (int i = 0; i < 6; i++) {
            int rand = random.nextInt(10);
            code += rand;
        }
        return code;
    }
    //2 每个手机每天只能发送三次,验证码放到redis中,设置超时时间
    public static void verifyCode(String phone) {
//        连接redis
        Jedis jedis = new Jedis("10.216.54.73", 6379);
//        拼接key
//        手机发送次数key
        String countKey = "VerityCode" + phone + ":count";
//        验证码key
        String codeKey = "VerityCode" + phone + ":code";
//        每个手机每天只能发送三次
        String count = jedis.get(countKey);
        if (count == null) {
//            没有发送次数,第一次发送
//            设置发送次数是1
            jedis.setex(countKey, 24 * 60 * 60, "1");
        } else if (Integer.parseInt(count) <= 2) {
//            发送次数+1
            jedis.incr(countKey);
        } else if (Integer.parseInt(count) > 2) {
//            发送三次,不能再发送
            System.out.println("今天发送次数已经超过三次");
            jedis.close();
            return;
        }
        //发送验证码放到redis里面
        String vcode = getCode();
        jedis.setex(codeKey, 120, vcode);
        jedis.close();
    }
    //    3 验证码校验
    public static void getRedisCode(String phone, String code) {
        //从redis获取验证码
        Jedis jedis = new Jedis("10.216.54.73", 6379);
        //验证码key
        String codeKey = "VerityCode" + phone + ":code";
        String redisCode = jedis.get(codeKey);
        //判断
        if (redisCode.equals(code)) {
            System.out.println("success");
        } else {
            System.out.println("fail");
        }
        jedis.close();
    }
}


八、 Redis与Spring Boot整合


8.1 引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- spring2.X集成redis所需common-pool2-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.1</version>
</dependency>


8.2 配置文件

spring:
  redis:
    #Redis服务器地址
    host: 10.216.54.73
    #Redis服务器连接端口
    port: 6379
    #Redis数据库索引(默认为0)
    database: 0
    #连接超时时间(毫秒)
    timeout: 1800000
    lettuce:
      pool:
        #连接池最大连接数(使用负值表示没有限制)
        max-active: 20
        #最大阻塞等待时间(负数表示没限制)
        max-wait: -1
        #最大阻塞等待时间(负数表示没限制)
        max-idle: 5
        #连接池中的最小空闲连接
        min-idle: 0


8.3 测试

package com.caq.boot.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@EnableCaching
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setConnectionFactory(factory);
//key序列化方式
        template.setKeySerializer(redisSerializer);
//value序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
//value hashmap序列化
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        return template;
    }
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();
        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }
}


RedisTestController中添加测试方法


package com.caq.boot.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/redisTest")
public class RedisTestController {
    @Autowired
    private RedisTemplate redisTemplate;
    @GetMapping
    public String testRedis(){
        //设置值到redis
        redisTemplate.opsForValue().set("name","lucy");
//        从redis获取值
        String name = (String) redisTemplate.opsForValue().get("name");
        return name;
    }
}
相关文章
|
存储 NoSQL 算法
Redis系列学习文章分享---第十篇(Redis快速入门之附近商铺+用户签到+UV统计)
Redis系列学习文章分享---第十篇(Redis快速入门之附近商铺+用户签到+UV统计)
149 0
|
存储 NoSQL Redis
Redis系列学习文章分享---第九篇(Redis快速入门之好友关注--关注和取关 -共同关注 -Feed流实现方案分析 -推送到粉丝收件箱 -滚动分页查询)
Redis系列学习文章分享---第九篇(Redis快速入门之好友关注--关注和取关 -共同关注 -Feed流实现方案分析 -推送到粉丝收件箱 -滚动分页查询)
161 0
|
消息中间件 负载均衡 NoSQL
Redis系列学习文章分享---第七篇(Redis快速入门之消息队列--List实现消息队列 Pubsub实现消息队列 stream的单消费模式 stream的消费者组模式 基于stream消息队列)
Redis系列学习文章分享---第七篇(Redis快速入门之消息队列--List实现消息队列 Pubsub实现消息队列 stream的单消费模式 stream的消费者组模式 基于stream消息队列)
257 0
|
JSON NoSQL Redis
Redis 作为向量数据库快速入门指南
Redis 作为向量数据库快速入门指南
1077 1
|
存储 NoSQL 关系型数据库
Redis系列学习文章分享---第一篇(Redis快速入门之初始Redis--NoSql+安装redis+客户端+常用命令)
Redis系列学习文章分享---第一篇(Redis快速入门之初始Redis--NoSql+安装redis+客户端+常用命令)
268 1
|
NoSQL Java Redis
Redis16-RedisTemplate快速入门,max -idle,min-idle,max-wait,用set的方法,opsForValue().set的方法
Redis16-RedisTemplate快速入门,max -idle,min-idle,max-wait,用set的方法,opsForValue().set的方法
|
Java Redis 数据安全/隐私保护
Redis13的Java客户端-Jedis快速入门,建立连接的写法,ip地址,设置密码密码,选择库的写法
Redis13的Java客户端-Jedis快速入门,建立连接的写法,ip地址,设置密码密码,选择库的写法
|
存储 NoSQL Java
Redis系列学习文章分享---第八篇(Redis快速入门之达人探店--发布探店笔记 + 查看探店笔记 + 点赞功能 + 点赞排行榜)
Redis系列学习文章分享---第八篇(Redis快速入门之达人探店--发布探店笔记 + 查看探店笔记 + 点赞功能 + 点赞排行榜)
123 0
|
缓存 NoSQL Java
Redis系列学习文章分享---第四篇(Redis快速入门之Java客户端--商户查询缓存+更新+双写一致+穿透+雪崩+击穿+工具封装)
Redis系列学习文章分享---第四篇(Redis快速入门之Java客户端--商户查询缓存+更新+双写一致+穿透+雪崩+击穿+工具封装)
179 0
|
存储 NoSQL Java
Redis系列学习文章分享---第三篇(Redis快速入门之Java客户端--短信登录+session+验证码+拦截器+登录刷新)
Redis系列学习文章分享---第三篇(Redis快速入门之Java客户端--短信登录+session+验证码+拦截器+登录刷新)
285 0

热门文章

最新文章

下一篇
开通oss服务