Redis

2019-08-19  本文已影响0人  程序员Darker

1.redis特点

  1. 数据存储:存放在内存,还支持持久化.-存取速度快,并发能力强,数据安全性高
  2. 支持value类型
  3. 支持多个语言客户端
  4. 还支持集群(支持高并发,海量数据)

2.使用场景

  1. 缓存
  2. 计数器
  3. 实时防攻击系统
  4. 需要设置有效期的应用
  5. 自动去重应用
  6. 栈和队列
  7. 消息订阅系统

3.redis的安装

  1. 网址
  1. 下载
  1. 安装启动服务端
  1. 客户端安装启动

4.使用redis-cli.exe操作redis

见操作文档

5.java操作redis

  1. 选择java客户端jedis
  2. 创建普通java项目,导入2个jar
    • jedis-2.5.2.jar
    • commons-pool2-2.2.jar
  3. jedis连接方式操作redis
package cn.wangningbo.redis.client.jedis;

import org.junit.Test;
import redis.clients.jedis.Jedis;

public class JedisHello {
    @Test
    public void test() throws Exception {
        //连接redis
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        //设置key-value
        jedis.set("test", "easy");
        //获取key为test的value
        System.out.println(jedis.get("test"));
        //关闭连接
        jedis.close();
    }
}
  1. 连接池方式操作redis
package cn.wangningbo.redis.client.jedis;

import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisPoolTest {
    @Test
    public void test() throws Exception {
        //创建配置对象
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //空闲时的连接数
        jedisPoolConfig.setMaxIdle(3);
        //最大连接数
        jedisPoolConfig.setMaxTotal(10);
        //创建连接超时 1秒
        jedisPoolConfig.setMaxWaitMillis(1 * 1000);
        //获取连接的时候测试连接是否畅通
        jedisPoolConfig.setTestOnBorrow(true);
        //创建jedis连接池   参数:指定配置,ip,端口
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, "127.0.0.1", 6379);
        //获取jedis
        Jedis jedis = jedisPool.getResource();
        //操作数据
        jedis.set("name", "二狗");
        System.out.println(jedis.get("name"));
        //释放连接
        jedis.close();
        //摧毁连接池
        jedisPool.destroy();
    }
}
  1. 封装工具类
package cn.wangningbo.redis.client.jedis;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public enum JedisUtil {
    INSTANCE;
    private static JedisPool jedisPool;

    static {
        //创建配置对象
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        //空闲时的连接数
        jedisPoolConfig.setMaxIdle(3);
        //最大连接数
        jedisPoolConfig.setMaxTotal(10);
        //创建连接超时 1秒
        jedisPoolConfig.setMaxWaitMillis(1 * 1000);
        //获取连接的时候测试连接是否畅通
        jedisPoolConfig.setTestOnBorrow(true);
        //创建jedis连接池   参数:指定配置,ip,端口
        jedisPool = new JedisPool(jedisPoolConfig, "127.0.0.1", 6379);
    }

    public Jedis getResource() {
        return jedisPool.getResource();
    }
}
  1. 工具类操作redis
package cn.wangningbo.redis.client.jedis;

import org.junit.Test;
import redis.clients.jedis.Jedis;

import java.util.List;

public class JedisOprTest {
    Jedis jedis = JedisUtil.INSTANCE.getResource();

    @Test
    public void testKey() throws Exception {
        //清空数据
        jedis.flushAll();

        System.out.println("判断key为name的key是否存在:" + jedis.exists("name"));
        System.out.println("判断key为age的key是否存在:" + jedis.exists("age"));

        System.out.println("给key为name的key设置value:" + jedis.set("name", "二狗"));
        System.out.println("给key为age的key设置value:" + jedis.set("age", "18"));

        System.out.println("再次判断key为name的key是否存在:" + jedis.exists("name"));
        System.out.println("再次判断key为age的key是否存在:" + jedis.exists("age"));

        System.out.println("删除前key为name的value值:" + jedis.get("name"));
        System.out.println("删除key为name的value值:" + jedis.del("name"));
        System.out.println("删除后key为name的value值:" + jedis.get("name"));
        System.out.println("获取key为age的value值:" + jedis.get("age"));

        //获取所有的key
        jedis.keys("*").forEach(key -> {
            System.out.println(key + "-->" + jedis.get(key));
        });

        //释放连接
        jedis.close();
    }

    @Test
    public void testStringBase() throws Exception {
        //清空数据
        jedis.flushAll();
        //add
        jedis.set("name", "舔狗");
        //get
        System.out.println(jedis.get("name"));
        //update
        jedis.set("name", "二狗");
        //get
        System.out.println(jedis.get("name"));
        //del
        jedis.del("name");
        //get
        System.out.println(jedis.get("name"));
        //jedis.append(key,appStr)追加 字符串拼接
        jedis.set("age", "12");
        System.out.println(jedis.get("age"));
        jedis.append("age", "45");
        //jedis.get() 获取
        System.out.println(jedis.get("age"));

    }

    @Test
    public void testStringBatch() throws Exception {
        //清空数据
        jedis.flushAll();
        //jedis.mset(keyvalue,keyvalue) dd update
        jedis.mset("name", "二狗", "age", "19", "sex", "男");
        jedis.keys("*").forEach(key -> {
            System.out.println(key + "-->" + jedis.get(key));
        });
        //jedis.mget(key1,key2,key3....) //获取多个key的值返回list
        List<String> mget = jedis.mget("name", "sex");
        System.out.println(mget);
        //jedis.del(key1,key2...) del
        jedis.del("name", "sex");
        jedis.keys("*").forEach(key -> {
            System.out.println(key + "-->" + jedis.get(key));
        });
    }

    @Test
    public void testStringAdvanceOpr() throws Exception {
        //清空数据
        jedis.flushAll();
        //设置一个key-value
        jedis.set("age", "19");
        System.out.println(jedis.get("age"));
        //jedis.incr()
        jedis.incr("age");
        System.out.println(jedis.get("age"));
        //jedis.incrBy()
        jedis.incrBy("age", 5);
        System.out.println(jedis.get("age"));
        //jedis.setex(key,time,value) //设置值得时候同时设置过期时间
        jedis.setex("name", 10, "奈斯");
        System.out.println(jedis.get("name"));
        Thread.sleep(12 * 1000);
        System.out.println(jedis.get("name"));
        System.out.println(jedis.exists("name"));
    }

    //事务四个特性
    // 1 原子性:一个事务中,多个操作是不可分割的,要么都成功,要么都失败.
    // 2 一致性:一个事务中,多个操作如果有一个失败了,其他要进行回滚保持数据一致性.
    // 3 隔离性:事务是隔离的,多个事务不会相互影响
    // 4 连续性(持续性):事务一旦开始,不能中止.
    @Test
    public void test() throws Exception {
        //手动回滚
    }
}

6.面试题

  1. 项目中那些地方用到Redis?
    • 缓存、计数器、实时防攻击系统、设置有效期的应用、自动去重应用、栈和队列、消息订阅系统!
  2. 使用什么来操作Redis?
    • 可以操作redis的客户端有很多种。比如:java、php、js、C/C++、C#、python等。
    • 我选择了java,java可操作redis的也有很多种。比如:Redisson、jedis等等很多种!
    • 我使用过jedis操作redis!
  3. 你使用过memcached?
    • 没有。但是我使用过redis。
    • redis与mencached的相同点:都是key-valueNosql,数据存储在内容中,读写效率高,都支持存储过期。
    • redis与mencached的不相同点:
      • 1)redis支持持久化.可以进行aof及rdb数据持久化到磁盘,从而进行数据备份或数据恢复等操作,较好的防止数据丢失的手段。。
      • 2)redis支持存储类型更多
      • 3)redis支持pub/sub消息订阅机制,可以用来进行消息订阅与通知。
      • 4)支持简单的事务需求,但业界使用场景很少,并不成熟
  4. 你为什么要使用reids?
    • 1)数据存储:存放在内存,还支持持久化.-存取速度快,并发能力强,数据安全性高
    • 2)支持value类型
    • 3)支持多个语言客户端
    • 4)还支持集群(支持高并发,海量数据)
  5. redis怎么实现栈和队列?
    • 队列和堆栈都可以用Redis的list数据类型实现,因为list支持以下操作
    • lpush/rpush,从左侧/右侧追加元素
    • lpop/rpop,从左侧/右侧弹出元素
    • llen,获取队列的长度
    • lindex,获取某个位置的元素
  6. 事务四大特性?
    • 1 原子性:一个事务中,多个操作是不可分割的,要么都成功,要么都失败.
    • 2 一致性:一个事务中,多个操作如果有一个失败了,其他要进行回滚保持数据一致性.
    • 3 隔离性:事务是隔离的,多个事务不会相互影响
    • 4 连续性(持续性):事务一旦开始,不能中止.
  7. 为什么要使用连接池?
    • 1)资源重用。由于数据库连接得到重用,避免了频繁创建、释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增进了系统运行环境的平稳性(减少内存碎片以及数据库临时进程/线程的数量)。
    • 2)更快的系统响应速度。数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而缩减了系统整体响应时间。
    • 3)新的资源分配手段。对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接的配置,实现数据库连接池技术,几年钱也许还是个新鲜话题,对于目前的业务系统而言,如果设计中还没有考虑到连接池的应用,那么…….快在设计文档中加上这部分的内容吧。某一应用最大可用数据库连接数的限制,避免某一应用独占所有数据库资源。
    • 4)统一的连接管理,避免数据库连接泄漏。在较为完备的数据库连接池实现中,可根据预先的连接占用超时设定,强制收回被占用连接。从而避免了常规数据库连接操作中可能出现的资源泄漏。一个最小化的数据库连接池实现:
  8. 说一下redis是怎么存储数据的?
    • redis为了考虑效率,保存数据在内容中.并且考虑数据安全性,还做数据持久化,如果满足保存策略,就会把内存的数据保存到数据rdb文件,还来不及保存那部分数据存放到aof更新日志中。在加载时,把两个数据做一个并集。
  9. redis数据满了时会怎么办?
    • 会执行淘汰策略
    • 淘汰一些数据,达到redis数据都是有效的。选择合适的淘汰策略进行淘汰。
    • 1)volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
    • 2)volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
    • 3)volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
    • 4)allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
    • 5)allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
    • 6)no-enviction(驱逐):禁止驱逐数据
    • redis 确定驱逐某个键值对后,会删除这个数据并,并将这个数据变更消息发布到本地(AOF 持久化)和从机(主从连接)。
上一篇 下一篇

猜你喜欢

热点阅读