Redis是什么?

Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set 有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。


安装与基础使用

Redis官方网站:点击前往Redis官网网站

MAC系统直接采用HomeBrew的下载方式

在控制台输入

brew install redis

进入redis服务

redis-cli

在Java上的运用

Redis控制台命令行就不在这里赘述了,可以前往CSDN学习
下面是直接在Java项目中进行操作

连接测试

public static void main(String[] args) {
    // 创建 Redis 对象
    Jedis jedis = new Jedis("127.0.0.1",6379);
    // 测试连接状态
    String ping = jedis.ping();
    System.out.println(ping);
    // 关闭连接
    jedis.close();
}

存储操作

@Test
public void demo1() {
    Jedis jedis = new Jedis("127.0.0.1",6379);

    // 单次set
    jedis.set("name","lucy");
    String name = jedis.get("name");
    System.out.println(name);

    // 一次性多次set
    jedis.mset("k1","v1","k2","v2");
    List<String> mget = jedis.mget("k1", "k2");
    System.out.println(mget);

    // 将所有的key输出
    Set<String> keys = jedis.keys("*");
    for (String key : keys) {
        System.out.println(key);
    }
    jedis.close();
}

集群操作

@Test
public void clusterTest() {
    Set<HostAndPort> set = new HashSet<>();
    set.add(new HostAndPort("127.0.0.1",6379));

    JedisCluster jedisCluster = new JedisCluster(set);
    jedisCluster.set("k1","v1");
    System.out.println(jedisCluster.get("k1"));
}

集群提供了什么好处?

  1. 实现扩容
  2. 分摊压力
  3. 无中心配置 相对简单

集群的不足

  1. 多键操作是不被支持的
  2. 多键的Redis事务是不被支持的,Lua脚本不被支持
  3. 由于集群方案出现比较晚,很多公司已经采用了其他的集群方案,而代替或者客户端分片的方案想要迁移至RedisCluster,需要整体迁移而不是逐步过渡,复杂度较大

手机验证码小案例

发送一个电话号,系统会给根据电话号来刷新一个6位数字的验证码,过期时间为120s
同一个电话号码24小时内只可以刷新3个验证码
根据电话号码来存储对应的key,一个是次数countKey,用来存储24小时内进行了几次刷新
另外一个是codeKey,用来存储刷新的验证码是什么,最后进行判断

生成验证码

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;
}

发送验证码

public static void verifyCode(String phone) {
    // 连接 redis
    Jedis jedis = new Jedis("127.0.0.1",6379);
    // 拼接key 手机发送次数key
    String countKey = "VerifyCode"+phone+":count";
    // 验证码key
    String codeKey = "VerifyCode"+phone+":code";
    // 每个手机每天只能发送三次
    String count = jedis.get(countKey);
    // 当次数达到了 用limitFlag作为是否超过的标识
    boolean limitFlag = false;
    if (count == null) {
        jedis.setex(countKey,24*60*60,"1");
    } else if (Integer.parseInt(count) <= 2) {
        jedis.incr(countKey);
    } else {
        System.out.println("今天的发送次数已经超过了三次");
        limitFlag = true;
        jedis.close();
    }

    // 发送的验证码要放到redis里面
    if (!limitFlag) {
        String vcode = getCode();
        jedis.setex(codeKey,120,vcode);
        System.out.println("[DEBUG] 你刷新了一个验证码: "+vcode+" ("+jedis.get(countKey)+"/3)");
        jedis.close();
    }

}

校验验证码

public static void getRedisCode(String phone,String code) {
    // 从redis中获取验证码
    Jedis jedis = new Jedis("127.0.0.1",6379);
    // 按照自己的规则
    String codeKey = "VerifyCode"+phone+":code";
    String redisCode = jedis.get(codeKey);
    // 判断
    if (redisCode == null) {
        System.out.println("[!] System Error");
    } else {
        if (redisCode.equals(code)) {
            System.out.println("[!] Verify success");
        } else {
            System.out.println("[!] Verify failed");
        }
    }
    jedis.close();
}

测试方法

@Test
public void send() {
    // 模拟发送验证码
    verifyCode("123456");
}

@Test
public void verify() {
    // 模拟判断
    getRedisCode("123456","231305");
}

如果能坚持不懈地进行适当的运动,可把人的运动能力的减退平均推迟八至九年,这一点是毫无疑问的。 ——沙法德
最后修改:2023 年 01 月 09 日
如果觉得我的文章对你有用,请随意赞赏