zoukankan      html  css  js  c++  java
  • Redis使用(Java)

    目录

    • 什么是Redis
    • 为什么用Redis
    • 如何使用Redis(5种数据类型)
    • 底层数据结构

    什么是Redis

    Redis是一个开源的高性能键值对数据库。它通过提供多种键值数据类型来适应不同场景下的存储需求,并借助许多高层级的接口使其可以胜任如缓存、队列系统等不同的角色

    为什么用Redis(特性)

    • 存储结构

    支持字符串、散列、列表、集合、有序集合等类型。与MySQL相比,对于小数据集的复杂关系操作更直观,性能更好

    • 内存存储与持久化

    Redis数据库中的所有数据都存储在内存中。由于内存的读写速度远快于硬盘,因此Redis在性能上对比其他基于硬盘存储的数据库有非常明显的优势

    Redis提供了对持久化的支持,即将可以内存中的数据异步写入到硬盘中,同时不影响继续提供服务

    • 功能丰富

    缓存:为每个键设置生存时间(Time To Live,TTL),生存时间到期后键会自动被删除

    队列:Redis的列表类型键可以用来实现队列,并且支持阻塞式读取,可以很容易地实现一个高性能的优先级队列

    构建聊天室等系统:支持“发布/订阅”的消息模式

    • 简单稳定

    如何使用Redis

    字符串

    1 public void testString(){
    2     Jedis jedis = RedisUtil.connect();
    3     jedis.set("testKey", "testValue");
    4     System.out.println("testKey: " + jedis.get("testKey"));
    5     Long delResult = jedis.del("testKey");
    6     System.out.println("del testKey, result = " + delResult);
    7     System.out.println("del后,testKey: " + jedis.get("testKey"));
    8 }
    View Code
    • 问题:字符串直接用char数组就好了,但是redis做了一些优化

    目的:提高空间的利用率

    方法:tryObjectEncoding包含的主要逻辑,依次执行以下策略

    1. 判断长度小于20,且可以将它转换为long类型的值:int string2l(const char *s, size_t slen, long *lval)

    2. 把value放在和与对象相同的内存块中:robj *createEmbeddedStringObject(const char *ptr, size_t len)

    注:o对象(即返回结果)获得如下全部的内存空间,value是设置的值,与o对象分配在同一块中

    3. 无法转换,把多分配的空间remove

    列表

     1 public void testList(){
     2     String testKey = "testKey";
     3     jedis.lpush(testKey, "testValue", "testValue2");
     4     System.out.println("testKey: " + jedis.lrange(testKey, 0, -1));
     5     jedis.lpush(testKey, "testValue", "testValue2", "testValue3");
     6     System.out.println("testKey set new: " + jedis.lrange(testKey, 0, -1));
     7     jedis.lrem(testKey, 2, "testValue");
     8     System.out.println("testKey lrem 2个数据后: " + jedis.lrange(testKey, 0, -1));
     9     Long delResult = jedis.del(testKey);
    10     System.out.println("del testKey, result = " + delResult);
    11     System.out.println("del后,testKey: " + jedis.get(testKey));
    12     System.out.println("del后,testKey: " + jedis.lrange(testKey, 0, -1));
    13 }
    View Code

    集合

    1 public void testSet(){
    2     String testKey = "testKey";
    3     jedis.sadd(testKey, "testValue", "testValue2");
    4     System.out.println("testKey: " + jedis.smembers(testKey));
    5     jedis.sadd(testKey, "testValue", "testValue2", "testValue3");
    6     System.out.println("testKey set new: " + jedis.smembers(testKey));
    7     jedis.srem(testKey, "testValue");
    8     System.out.println("testKey srem后: " + jedis.smembers(testKey));
    9 }
    View Code

    有序集合

     1 public void testSortedSet(){
     2     String testKey = "testKey";
     3     jedis.zadd(testKey, 5, "testValue5");
     4     jedis.zadd(testKey, 2, "testValue2");
     5     System.out.println("testKey: " + jedis.zrange(testKey, 0, -1));
     6     jedis.zadd(testKey, 2, "testValue2-2");
     7     jedis.zadd(testKey, 9, "testValue9");
     8     System.out.println("testKey zadd: " + jedis.zrange(testKey, 0, -1));
     9     jedis.zrem(testKey, "testValue2");
    10     System.out.println("testKey zrem后: " + jedis.zrange(testKey, 0, -1));
    11 }
    View Code

    哈希

     1 public void testHash(){
     2     String testKey = "testKey";
     3     jedis.hset(testKey, "field", "100");
     4     System.out.println("testKey: " + jedis.hget(testKey, "field"));
     5     jedis.hincrBy(testKey, "field", 100);
     6     System.out.println("testKey 的value hincrBy: " + jedis.hvals(testKey));
     7 
     8     jedis.hset(testKey, "field", "testValue");
     9     jedis.hset(testKey, "field2", "testValue2");
    10     jedis.hset(testKey, "field3", "testValue3");
    11     System.out.println("testKey new hset, keys= " + jedis.hkeys(testKey));
    12     System.out.println("testKey new hset, values= " + jedis.hvals(testKey));
    13     jedis.hdel(testKey, "field3");
    14     System.out.println("testKey hdel, keys= " + jedis.hkeys(testKey));
    15     System.out.println("testKey hdel, values= " + jedis.hvals(testKey));
    16 }
    View Code

    底层数据结构

      1 /*3个基础数据结构 */
      2 typedef struct dict {
      3     dictType *type;
      4     void *privdata;
      5     dictht ht[2];// 有两个table
      6     long rehashidx; 
      7     unsigned long iterators;
      8 } dict;
      9 
     10 /* hash table结构 */
     11 typedef struct dictht {
     12     dictEntry **table;
     13     unsigned long size;
     14     unsigned long sizemask;
     15     unsigned long used;
     16 } dictht;
     17 
     18 /* 节点结构*/
     19 typedef struct dictEntry {
     20     void *key;
     21     union {
     22         void *val;
     23         uint64_t u64;
     24         int64_t s64;
     25         double d;
     26     } v;
     27     struct dictEntry *next;
     28 } dictEntry;
     29 
     30 
     31 /* 
     32 * 根据key查找entry 
     33 * key 通过hash获取index,冲突则通过挂链方式继续查找
     34 */
     35 dictEntry *dictFind(dict *d, const void *key)
     36 {
     37     dictEntry *he;
     38     uint64_t h, idx, table;
     39 
     40     if (d->ht[0].used + d->ht[1].used == 0) return NULL; /* dict is empty */
     41     if (dictIsRehashing(d)) _dictRehashStep(d);
     42     h = dictHashKey(d, key);
     43     for (table = 0; table <= 1; table++) {
     44         idx = h & d->ht[table].sizemask;
     45         he = d->ht[table].table[idx];
     46         while (he) {//遍历该位置下所有key
     47             if (key == he->key || dictCompareKeys(d, key, he->key))
     48                 return he;
     49             he = he->next;
     50         }
     51         if (!dictIsRehashing(d)) return NULL;
     52     }
     53     return NULL;
     54 }
     55 
     56 /* 创建dict,初始化时dictht大小为0 */
     57 dict *dictCreate(dictType *type,
     58     void *privDataPtr)
     59 {
     60     dict *d = zmalloc(sizeof(*d));
     61 
     62     _dictInit(d, type, privDataPtr);
     63     return d;
     64 }
     65 
     66 /* 扩展或创建dictht */
     67 int dictExpand(dict *d, unsigned long size)
     68 {
     69     /* the size is invalid if it is smaller than the number of
     70     * elements already inside the hash table */
     71     if (dictIsRehashing(d) || d->ht[0].used > size)
     72         return DICT_ERR;
     73 
     74     dictht n; /* the new hash table */
     75         /* 获取要分配的dictht的大小 */
     76     unsigned long realsize = _dictNextPower(size);
     77 
     78     /* Rehashing to the same table size is not useful. */
     79     if (realsize == d->ht[0].size) return DICT_ERR;
     80 
     81     /* Allocate the new hash table and initialize all pointers to NULL */
     82     n.size = realsize;
     83     n.sizemask = realsize - 1;
     84     n.table = zcalloc(realsize*sizeof(dictEntry*));
     85     n.used = 0;
     86 
     87     /* Is this the first initialization? If so it's not really a rehashing
     88     * we just set the first hash table so that it can accept keys. */
     89     if (d->ht[0].table == NULL) {
     90         d->ht[0] = n;
     91         return DICT_OK;
     92     }
     93 
     94     /* Prepare a second hash table for incremental rehashing */
     95     d->ht[1] = n;
     96     d->rehashidx = 0;
     97     return DICT_OK;
     98 }
     99 
    100 /* 
    101 * hash table的容量为2的幂
    102 * 初始化大小为4
    103 */
    104 static unsigned long _dictNextPower(unsigned long size)
    105 {
    106     unsigned long i = DICT_HT_INITIAL_SIZE;
    107 
    108     if (size >= LONG_MAX) return LONG_MAX + 1LU;
    109     while (1) {
    110         if (i >= size)
    111             return i;
    112         i *= 2;
    113     }
    114 }
    115 
    116 /* 添加一个kv */
    117 dictEntry *dictAddRaw(dict *d, void *key, dictEntry **existing)
    118 {
    119     long index;
    120     dictEntry *entry;
    121     dictht *ht;
    122 
    123     if (dictIsRehashing(d)) _dictRehashStep(d);
    124 
    125     /* Get the index of the new element, or -1 if
    126     * the element already exists. */
    127     if ((index = _dictKeyIndex(d, key, dictHashKey(d, key), existing)) == -1)
    128         return NULL;
    129 
    130     /* 最新的kv放在链表的第一个,该kv最可能被访问到*/
    131     ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0];
    132     entry = zmalloc(sizeof(*entry));
    133     entry->next = ht->table[index];
    134     ht->table[index] = entry;
    135     ht->used++;
    136 
    137     /* Set the hash entry fields. */
    138     dictSetKey(d, entry, key);
    139     return entry;
    140 }
    View Code
  • 相关阅读:
    Python基础-EMS系统
    python基础-数据结构及数据读取操作
    python基础-猜数游戏
    python基础-质数判断及优化
    利用5次shift漏洞破解win7密码
    python基础-水仙花数判断
    pickle,json ;random,shelve
    block母版继承,include模板导入,inclusion_tag自定义模板
    多道技术,阻塞非阻塞,同步异步,udp,tcp,孤儿僵尸进程
    深度广度继承,抽象类接口,绑定方法,@propertry,继承封装接口多态鸭子类型关系,组合
  • 原文地址:https://www.cnblogs.com/coolqiyu/p/12150736.html
Copyright © 2011-2022 走看看