Redis配置

一. Redis介绍.

  1. Redis介绍.

    Redis的作者是一位意大利人.
    在2004年左右和朋友开发了一个统计的网站LLOOGG,一直使用的是mysql,mysql的性能太烂了,自己研发了一个非关系型数据库,Redis,同年Redis对外开源.
    意大利人刚刚创业写的LLOOGG不管了,直接专心维护Redis. 新浪.
    Redis(全称:Remote Dictionary Server 远程字典服务)是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。

  2. NOSql.

    Not Only SQL -> 非关系型数据库.
    除了关系型数据库都是非关系型数据库.
    关系型数据库: 有表的.
    Mysql.
    Oracle.
    SqlServer.
    DB2…
    非关系型数据库:
    表之间没有关系.
    没有表.
    1. Key-Value型非关系型数据库.
    Redis. M…Cache.
    2. 文档存储的非关系型数据库
    ElasticSearch.
    3. 面向列的非关系型数据库
    HBase.
    4. 图形化的非关系型数据库
    Neo4j.

  3. Redis的优势.

    1. Redis的性能优势.
      读的速度是110000次/s,写的速度是81000次/s 。

    2. Redis是单线程的.
      实现分布式锁.

    3. Redis除了Key-Value的存储结构,还提供了很多其他的存储结构.
      Key-Hash,Key-List,Key-Set,Key-SortedSet

    4. Redis提供了多种持久化的机制.
      RDB – AOF

    5. Redis还提供了集群的搭建,并且不依赖外部环境(5.0以上版本)
      集群时无中心,等等…

    6. 提供了多种原因的API…
      Jedis,卷心菜.

      做缓存.
      做session共享.
      实现分布式锁.

二. 安装Redis.

  1. 安装Redis.

    1. 下载Redis的压缩包.
      wget http://download.redis.io/releases/redis-5.0.7.tar.gz

    2. 解压.
      tar -zxvf redis-5.0.7.tar.gz -C /usr/local

    3. 直接使用C语言的环境去编译并安装Redis.
      cd /usr/local/redis-5.0.7
      make
      make install PREFIX=/usr/local/redis

    4. 启动.
      cd /usr/local/redis/bin
      ./redis-server

    5. 连接.
      单独开启一个ssh连接.
      cd /usr/local/redis/bin
      ./redis-cli -h localhost -p 6379

  2. Redis的配置.
    vi后跳转到指定行 :to 行数

    1. Redis需要占满整个界面保证Redis进程的运行.
      开启守护进程
      daemonize no -> yes (5.0.6 -> 136行)

    2. 远程连接Redis.
      关闭绑定本地的配置
      bind 127.0.0.1 -> 将其注释. (5.0.6 -> 69行)
      关闭redis的保护机制
      protected-mode yes -> no. (5.0.6 -> 88行)

    3. 在windows中使用Redis-DeskTop-Manager连接Redis服务

三. Redis的简单操作命令.

文档: http://doc.redisfans.com/

  1. key.(晨考)

    删除key:
    del key…

    设置生存时间(活多久):
    expire key second

    设置生存时间(活到什么时候):
    expireat key timestamp

    查看redis中存活的全部key:
    keys pattern(前缀*)

    设置生存时间(活多久,毫秒):
    pexpire key milliSecond

    查看当前Key的生存情况:
    ttl key
    当 key 不存在时,返回 -2 。
    当 key 存在但没有设置剩余生存时间时,返回 -1 。
    否则,以秒为单位,返回 key 的剩余生存时间。

  2. String.(晨考)

    设置值:
    set key value
    取值:
    get key
    自增一: (如何key已经存在,那么对应的value必须是一个数值,如果key不存在,设置一个key,值为1)
    incr key
    自减一: (如何key已经存在,那么对应的value必须是一个数值,如果key不存在,设置一个key,值为-1)
    decr key
    自增|自减指定数值:
    incrby|decrby key increment
    自增指定浮点数:
    incrbyfloat key increment
    设置值的同时指定生存时间.
    setex key second value
    分布式锁在操作:
    setnx key value (会返回设置是否成功)
    (set if not exists)
    getset key value
    (先get获取值,再set设置值,解决redis分布式锁的死锁问题)

四. 使用Java连接Redis.

  1. Jedis.

     @Test
       public void test(){
     //1. 建立连接.
     Jedis jedis = new Jedis("192.168.98.98",6379);
    
     //2. 操作.
     //-------------------------------------------------------------
     /*jedis.set("name","李四");         // redis天然幂等操作.
     System.out.println("OK!");*/
    
     //-------------------------------------------
    
     // commons-lang3, spring-context
     // 准备value
     /*User value = new User();
     value.setId(1);
     value.setName("王五");
     // 准备key
     String key = "user";
     //使用工具类序列化操作
     byte[] serializeKey = SerializationUtils.serialize(key);
     byte[] serializeValue = SerializationUtils.serialize(value);
     // 调用jedis存储
     jedis.set(serializeKey,serializeValue);
     System.out.println("OK!!");*/
    
    
     //----------------------------------------------------
    
     //获取redis中存储的byte[]
     /*String key = "user";
     byte[] serializeKey = SerializationUtils.serialize(key);
     // 获取value
     byte[] serializeValue = jedis.get(serializeKey);
     // 反序列化
     User user = (User) SerializationUtils.deserialize(serializeValue);
     System.out.println(user);*/
    
     //-------------------------------------------------------------
     //3. 释放资源.
     jedis.close();
     }
    
  2. JedisPool.

     @Test
       public void test(){
     //1. 创建连接池.
     JedisPool jedisPool = new JedisPool("192.168.98.98",6379);
    
     //2. 通过连接池获取jedis对象
     Jedis jedis = null;
     try {
         jedis = jedisPool.getResource();
    
         //3.  操作.................
         int i = 1 / 0;  //  / by zero
    
     } finally {
         //4. 释放资源
         jedis.close();
     }
    }
    

五. 使用SpringBoot连接Redis.

  1. 创建项目.

  1. 导入依赖.

    spring-boot-starter-data-redis

    spring-boot-starter-data-jpa
    不好用…
    springcloud的主要贡献者,对jpa,hibernate,mybatis
    jpa – 56%
    mybatis – 10%

  2. 编写配置文件.

    spring:
    redis:
    host: 192.168.98.98
    port: 6379

  3. 测试.

     @Autowired
      // 如果不加泛型,默认全部以byte[]的方式存储.
     private RedisTemplate<String,String> redisTemplate;
    
    
     @Test
      public void contextLoads() {
     //1. 指定操作String的数据类型.
     redisTemplate.opsForValue().set("hobby","ctrl",1, TimeUnit.DAYS);
    
    
     //2. 操作key直接使用
     redisTemplate.delete("hobby");
    }
    

六. 进销存使用Redis实现Shiro的session共享.

  1. 实现Shiro的Session共享.

    1. 找到SessionDAO接口.
      Shiro默认使用的的MemorySessionDAO的实现类.
      Shiro默认将session对象存放到了本地的一个ConcurrentHashMap中.

    2. 需要自定义一个SessionDAO的实现类.
      创建了一个POJO类.RedisSessionDAO继承了一个抽象类AbstractSessionDAO.

    3. 重写5个方法.

      1. 创建Session. -> 传入了一个Session.
        //1. 生成一个SessionId.

        //2. 将SessionId和Session绑定到一起.

        //3. 将SessionId和Session存储到redis.

        //4. 返回SessionId.

      2. 读取Session.
        //1. 封装key.

        //2. 去redis中查询session

        //3. 重新设置生存时间

        //4. 返回session

      3. 修改Session.
        //1. 根据session获取sessionId.

        //2. 声明key和value.

        //3. 存储到redis中.

      4. 删除Session.
        //1. 根据session获取sessionId.

        //2. 声明key

        //3. 删除指定的key

      5. 查询全部存活的Session.
        //1. 封装pattern

        //2. 封装返回结果

        //3. 通过keys查询全部存活的key.

        //4. 遍历全部的key

        //通过key获取session,并添加到返回结果

        //5. 返回返回结果

  2. 重写doCreateSession.

    @Override
    protected Serializable doCreate(Session session) {
    //1. 获取一个sessionId – String
    Serializable sessionId = super.generateSessionId(session);
    //2. 将sessionId和session绑定到一起.
    super.assignSessionId(session,sessionId);
    //3. 将sessionId作为key,session作为value存储到redis中,并同时设置生存时间.
    String key = SHIRO_KEY + sessionId;
    redisTemplate.opsForValue().set(key,session,TIME_OUT, TimeUnit.MINUTES);
    //4. 返回sessionId
    return sessionId;
    }

  3. 重写doReadSession.

    // 获取session信息,去Redis中获取
    @Override
    protected Session doReadSession(Serializable sessionId) {
    //1. 封装key.
    String key = SHIRO_KEY + sessionId;
    //2. 去redis中查询session
    Session session = (Session) redisTemplate.opsForValue().get(key);
    //3. 重新设置生存时间.
    redisTemplate.expire(key,TIME_OUT,TimeUnit.MINUTES);
    //4. 返回session
    return session;
    }

  4. 重写updateSession

    // 修改用户信息. 修改Redis中的信息.
    @Override
    public void update(Session session) throws UnknownSessionException {
    //1. 根据session获取sessionId.
    Serializable sessionId = session.getId();
    //2. 声明key和value.
    String key = SHIRO_KEY + sessionId;
    //3. 存储到redis中.
    redisTemplate.opsForValue().set(key,session,TIME_OUT,TimeUnit.MINUTES);
    }

  5. 重写deleteSession

    @Override
    public void delete(Session session) {
    //1. 根据session获取sessionId.
    Serializable sessionId = session.getId();
    //2. 声明key
    String key = SHIRO_KEY + sessionId;
    //3. 删除指定的key
    redisTemplate.delete(key);
    }

  6. 重写getActiveSession

    // 获取全部存活的session
    @Override
    public Collection getActiveSessions() {
    //1. 封装pattern
    String pattern = SHIRO_KEY + “*”;
    //2. 封装返回结果
    Set sessionSet = new HashSet<>();
    //3. 通过keys查询全部存活的key.
    Set keys = redisTemplate.keys(pattern);
    //4. 遍历全部的key
    for (Object key : keys) {
    //通过key获取session,并添加到返回结果
    Session session = (Session) redisTemplate.opsForValue().get(key);
    sessionSet.add(session);
    }
    //5. 返回返回结果
    return sessionSet;
    }

    1. 将SessionDAO配置给Shiro.

2.1 将SessionDAO配置给SecurityManager.

@Bean
    public DefaultWebSecurityManager securityManager(JxcRealm realm, RedisSessionDAO redisSessionDAO){
        //1. 创建DefaultWebSecurityManager
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

        //2. 创建SessionManager
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();

        //3. 将redisSessionDAO设置到sessionManager中
        sessionManager.setSessionDAO(redisSessionDAO);

        //4. 将sessionManager设置给SecurityManager
        securityManager.setSessionManager(sessionManager);

        //5. 注入自定义Realm
        securityManager.setRealm(realm);
        //6. 返回
        return securityManager;
    }
  1. 自定义SessionManager避免频繁访问Redis.

    public class RedisSessionManager extends DefaultWebSessionManager {
    
     @Override
     protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
         //1. 获取sessionId.
         Serializable sessionId = getSessionId(sessionKey);
         if (sessionId == null) {
             return null;
         }
         //2. 先去request域中查询.
         WebSessionKey webSessionKey = (WebSessionKey) sessionKey;
         ServletRequest req = webSessionKey.getServletRequest();
         Session session = (Session) req.getAttribute(sessionId.toString());
         //3. 如果有结果直接返回.
         if(session == null){
             // 去redis中查询retrieveSessionFromDataSource
             session = super.retrieveSessionFromDataSource(sessionId);
             // 将查询到的结果放到request域中.
             req.setAttribute(sessionId.toString(),session);
         }
         //4. 返回session
         return session;
     }
    

    }

配置到shiroConfig中

@Bean
public DefaultWebSecurityManager securityManager(JxcRealm realm, RedisSessionDAO redisSessionDAO){
    //1. 创建DefaultWebSecurityManager
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

    //2. 创建SessionManager
    RedisSessionManager sessionManager = new RedisSessionManager();

    //3. 将redisSessionDAO设置到sessionManager中
    sessionManager.setSessionDAO(redisSessionDAO);
	....
}

本文地址:https://blog.csdn.net/qq_28871287/article/details/108566470

(0)
上一篇 2022年3月21日
下一篇 2022年3月21日

相关推荐