java technology --Redis API in-depth analysis (two)

1. Storage data (intra-coded)

(1)Redis内部使用一个redisObject对象来表示所有的key和value
     <1>redisObject主要的信息包括数据类型(type) ,编码方式(encoding) ,数据指针(ptr),虚拟内存(vm)
     <2>type代表一个value对象具体是何种数据类型(5种之一),encoding是不同数据类型在redis内部式
(2)将不同数据结构的数据编码成二进制数据存储在内存中

2. Operation of data (command, protocol)

(1)Redis-cli:客户端命令
     <1>Redis提供了redis-cli  可以在命令行操作数据
     <2>Redis是一种基于键值对的NoSQL数据库,它的5种数据结构都是健值对中的值
     <3>对于键来说有一些通用命令
       1.keys *:查看所有健
       2.dbsize:健总数
       3.exists key:检查健是否存在
       4.del key [key ...]:删除键
       5.expire key seconds:键过期
       6.type key:键的数据结构类型
       7.object encoding key:值的内部编码
(2)客户端通信协议RESP
     <1>Redis 定制了RESP协议实现客户端与服务端的正常交互,这是一种基于TCP协议之上简单高效的协议
     <2>jedis实现了RESP协议
(3)Redis客户端:jedis(相当于MySQL的jdbc)用来连接客户端与服务端的桥梁
     <1>获取jedis
       <dependency>
           <groupId>redis.clients</groupId>
           <artifactId>jedis</artifactId>
           <version>2.9.0</version>
           <type>jar</type>
           <scope>compile</scope>
       </dependency>
     <2>Jedis基本使用
        // 创建连接
       Jedis jedis = new Jedis("localhost", 6379);
        // 存储数据,key="foo",value="bar"
       jedis.set("foo", "bar");
       // 获取数据
       String value = jedis.get("foo");
       //使用完后释放资源
       jedis.close();
    <3>Jedis的使用
     1.Redis作为缓存数据库理论上和MySQL一样需要客户端和服务端建立起来连接进行相关操作
     2.使用MySQL的时候都会使用一款开源的连接池,例如C3P0.
     3.Jedis连接Redis缓存库,有两种方式:直连,使用缓存池(实际开发中使用缓存池)
   <4>使用Jedis直连
     1.直连会消耗大量的数据库资源,每新建一个连接,使用后断开连接,这显然不是高效的
     2.客户端连接Redis使用的是TCP协议,直连的方式每次需要建立TCP连接
     3.直连的方式无法限制Jedis对象的个数,在极端情况下可能会造成连接泄露
   <5>使用Jedis缓存池
     1.使用连接池的方式对Redis连接进行管理,使用完后不需要释放资源,交于缓存池即可
     2.所有Jedis对象先放在池子中每一次需要的时候连接Redis,只需要在池子中借,用完了再归还给池子  
     3.借用和归还操作是在本地进行的,只有少量的并发同步开销,远远小于新建TCP连接的开销
     4.连接池的形式可以有效的保护和控制资源的使用
   <6>JedisPool缓存池基本使用:有两种方式
     1.连接池配置实例化代码:获取配置文件属性值
        第一步:/*读取jedis.properties配置文件*/
    static{
        ResourceBundle rb = ResourceBundle.getBundle("jedis");
        maxtotal = Integer.parseInt(rb.getString("maxtotal"));
        maxwaitmillis = Integer.parseInt(rb.getString("maxwaitmillis"));
        host = rb.getString("host");
        port = Integer.parseInt(rb.getString("port"));
    }
       第二步:/*创建连接池*/
    static{
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(maxtotal);
        jedisPoolConfig.setMaxWaitMillis(maxwaitmillis);
        JedisPool jedisPool= new JedisPool(jedisPoolConfig,host,port);
    }
       第三步:/*获取jedis*/
    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
      第四步: /*关闭Jedis*/
    public static void close(Jedis jedis){
        if(jedis!=null){
            jedis.close();
        }
      第五步:/*调用JedisPool获取Jedis实例*/
         //获取redis客户端连接
        Jedis jedis = jedisPoolUtils.getJedis();
        //从缓存池获取缓存实例对象
        String userJson = jedis.get("user");
        //2从redis中查数据,判断否为null
        if (userJson == null || userJson .length() == 0) {
            //redis中没有数据
            System.out.println("redis无数据,执行查库操作");
            //查询数据并且存入redis
            List<User> user = userDao.findAll();
            //将list序列化为json
            ObjectMapper mapper = new ObjectMapper();
            try {
                userJson = mapper.writeValueAsString(user);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
           //将json数据存入redis
            jedis.set("user", userJson );
            //归还jedis连接
            jedis.close();
        } else {
            System.out.println("redis中有数据,走缓存查询");
        }
        return userJson;
     2.通过spring注入进行配置
     第一步:/*二级缓存引入类:第三方缓存Redis,实现官方提供的默认Redis接口Cache*/
public class RedisCache implements Cache {
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    private String id;
    private static JedisConnectionFactory jedisConnectionFactory;
    public RedisCache(final String id) {
        if (id == null) {
            throw new IllegalArgumentException("Cache instances require an ID");
        }
        this.id = id;}
    public String getId() {
        return this.id;}
        //存入缓存
    public void putObject(Object key, Object value) {
        JedisConnection conn = null;
        try{
            conn = jedisConnectionFactory.getConnection();
            RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
            conn.set(serializer.serialize(key), serializer.serialize(value));
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(conn != null){
                conn.close();  } }}
        //获取缓存
    public Object getObject(Object key) {
        JedisConnection conn = null;
        Object res = null;
        try{
            conn = jedisConnectionFactory.getConnection();
            RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
            byte[] bs = conn.get(serializer.serialize(key));
            res = serializer.deserialize(bs);
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(conn != null){
                conn.close(); } } return res; }
           //移除缓存
    public Object removeObject(Object key) {
        JedisConnection conn = null;
        Object res = null;
        try{
            conn = jedisConnectionFactory.getConnection();
            RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
            conn.expire(serializer.serialize(key), 0);
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(conn != null){
                conn.close();}}
        return res; }
        //清空缓存
    public void clear() {
        JedisConnection conn = null;
        try{
            conn = jedisConnectionFactory.getConnection();
            conn.flushDb();
            conn.flushAll();
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(conn != null){
                conn.close();} } }
           //获取缓存大小
    public int getSize() {
        JedisConnection conn = null;
        int res = 0;
        try{
            conn = jedisConnectionFactory.getConnection();
            res = Integer.parseInt(conn.dbSize().toString());
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(conn != null){
                conn.close(); }}
        return res; }
        //缓存获取读写锁
    public ReadWriteLock getReadWriteLock() {
        return readWriteLock; }
    public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
        RedisCache.jedisConnectionFactory = jedisConnectionFactory;}
    第二步:/*将第三方缓存实现类注入spring管理*/
    public class RedisCacheTransfer {
    @Autowired
    public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
        RedisCache.setJedisConnectionFactory(jedisConnectionFactory);}}   
    第三步:/*在spring.xml配置文件中引入实现spring-redis注入*/
<bean id="jedisConnectionFactory" class="com.tp.soft.redis.RedisCacheTransfer">
        <property name="jedisConnectionFactory" ref="connectionFactory" />
</bean>
    第四步:/*注入缓存接口实现类,调用对应方法即可*/
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    //连接redis缓存服务器
    redisConnectionFactory.getConnection());
    //向缓存服务器存储数据
    redisTemplate.opsForValue().set("name", "fsx");
    //获取缓存服务器中存储的数据
    System.out.println(redisTemplate.opsForValue().get("name"));

3.Jedis and JedisPool summary

(1)Jedis线程不安全,JedisPool线程安全
(2)Redis Client拥有众多对接版本,目前使用Jedis为官方推荐Java对接客户端
(3)基于其对Redis良好的版本支持和API对接,另外编码中尽量避免使用废弃接口
Published 143 original articles · won praise 10 · views 7534

Guess you like

Origin blog.csdn.net/qq591009234/article/details/103786452