zoukankan      html  css  js  c++  java
  • reids笔记(1)

    redis是一个高性能的key-value数据库,也是NOSQL数据库,是为了解决高并发,高扩展,大数据存储等问题而产生的数据库解决方案,是一个非关系型数据库,并且Redis是基于内存的单线程数据库(6.0之后支持多线程)。

    redis支持数据结构类型包括:字符串,链表,哈希表,集合,有序集合等。为了保证读取的效率redis把数据对象都存储在内存中,它可以支持周期性的把更新的数据写入磁盘文件中,而且他还提供了交集和并集,以及一些不同方式排序的操作

    1.NoSql优点

      1.对数据库高并发读写需求
      2.对海量数据的高效率存储和访问
      3.对数据库的高扩展性和高可用性的需求

    2.主要的NoSql数据库分类

    分类
    数据库
    应用场景
    数据类型
    优点
    缺点
    键值
    (key-value)
    Redis,Tokyo,
    Oracle BDB
    内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统
    Kye指向Value的键值对,通常用hash table来实现
    查询速度快
    数据无结构化,通常只被当作字符串或二进制数据
    列表存储
    Cassandra,HBase,Riak
    分布式文件系统
    以列簇式存储,将同一列数据存在一起
    查询速度快,可扩展性强,更容易进行分布式扩展
    功能相对局限
    文档型数据库
    CouchDB,
    MongoDB
    web应用(与key-value类似,value是结构化的不同的是数据库可以了解value的内容)
    key-value对应的键值对,Value为结构化数据
    数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构
    查询性能不高,而且缺乏统一性的查询语法
    图形数据库
    Neo4J,InfoGrid,Infinite Graph
    社交网络,推荐系统等。专注于构件关系图谱
    图结构
    利用图结构相关算法,比如最短路径寻址,N度关系查找等
    很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案

      MongoDB:

        MongoDB数据库是一个基于分布式文件存储的数据库,C++编写,主要来处理大量的文档,MongoDB是一个介于关系型数据库和非关系型数据库中间的产品,MongoDB是非关系型数据库中功能最丰富,最像关系型数据库的

      图形数据库保存的是这种关系:

          

    3.Redis特点

      1.redis是一个开源的使用c语言编写的 key-value数据库,并提供多种语言的AIP
     
      2.redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并在此基础上实现了master-slave(主从)同步
     
      3.主从同步:数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器
     
      4.redis是基于内存操作的,cpu不是redis性能瓶颈,redis的瓶颈是机器的内存和网络的宽带,redis可以作为数据库,缓存和消息中间件来使用

    4.redis性能测试

      redis-benchmark 是一个官方自带的压力测试工具

     

     压力测试命令(在bin下执行):

      redis-benchmark -h 127.0.0.1 -p 6379 -c 100 -n 1000

    5 基础命令 :

    涵义
    命令
    注释
    windows连接redis
    redis-cli -h 127.0.0.1 -p 6379
    在bin目录运行
    linux连接redis
    redis-cli -p 6397
     
    得到redis安装目录
    config get dir
     
    切换数据库
    select 1
    redis默认有16个数据库,默认使用第0个
    查询数据库大小
    dbsize
     
    查询所有的key
    keys *
     
    清空数据库
    flushall
     
    清空当前数据库
    flushdb
     
    设置键值
    set key value
     
    得到值
    get key
     
    删除key
    del key
     
    移除key
    move key 数据库编号
     
    判断key是否存在
    exists key
     
    设置过期时间
    expire key 时间
    时间单位为秒
    查询剩余时间
    ttl key
     
    查询key类型
    type key
     
    获取配置信息
    CONFIG GET *
    也可以使用 CONFIG GET "配置名" 得到配置信息
    修改配置信息
    CONFIG SET 配置名 “值”
     
     

    6.redis数据类型及窗口命令 :

      1.String(字符串):
    涵义
    命令
    注释
    设置键值
    setnx key val
    当key存在不做任何操作
    批量设置键值
    mset key1 val1 key2 val2
     
    批量获取值
    mget key1 key2
    这个操作是一个原子性操作,要么一起成功要么一起失败
    组合getset
    getset key val
    key不存在创建,key存在覆盖原来的
    追加内容
    append key val
    如果当前key不存在,执行新增操作
    获取值长度
    strLen key
     
    根据key加一
    incr key
     
    根据key减一
    decr key
     
    根据key增加指定值
    incrby key 10
     
    根据key减少指定值
    decryby key 10
     
    字符串截取
    getrange key 开始位置 结束位置
    下标从0开始,结束位置-1为最后
    替换字符串
    setrange key 替换的位置 替换的值
    原字符串:aabbcc 从1替换值 xx
    结果: axxbcc
    设置key及过期时间
    setex key 过期时间 值
     
      
        mset和mget拓展思路用法:
      
    //设置值
    mset user:name 张三 user:age 18
    //获取值
    mget user:name user:age
    //得到结果:
              张三
              18
    
    这个样设置key向设置对象一样,方便查询和管理        
      2.hashes(散列):

         hashes散列存储的值为map集合,效果:key val(val为map集合)
         hashes散列的命令开头都是H
    涵义
    命令
    注释
    添加
    Hset key key val
     
    获取
    Hget key key
     
    添加多个
    Hmset key key val key2 val2
     
    获取所有的值
    Hgetall key
     
    获取长度
    Hlen key
     
    判断key是否存在
    Hexists key key
     
    获取所有的key
    Hkeys key
     
    获取所有的val
    Hvals key
     
     
      3.lists(列表):
        list命令都是L开头
      
    涵义
    命令
    注释
    首部添加值
    Lpush key val
    例子:Lpush a one
    Lpush a two
    尾部添加值
    Rpush key val
     
    获取
    Lrange key 开始下标 结束下标
    下标从0开始,结束位置为-1拿全部,先入后出
    删除数据
    Lpop key 删除左边第一个
    Rpop key 删除右边第一个
     
    根据下标获取值
    Lindex key 下标
     
    获取列表长度
    Llen key
     
    移除指定值
    Lrem key 移除个数 值
    因为list是可重复的
    截取指定范围内的值
    Ltrim key 前下标 后下标
    截取后list只剩那几个值了
    移除列表最后一个元素,移动到新列表中
    RpopLpush key1 key2
    将key1的最后一个值移动到key2n内
    替换值
    Lset key 位置 替换的值
    位置不存在会报错
    在指定位置插入
    Linsert key 位置 原值 插入值
    原值是在哪插
        
    list在指定位置插入语句实例: 
    Jedis jedis = new Jedis("127.0.0.1",6379);
    
    jedis.lpush("a","值1","值2","值3");
    
    List<String> a = jedis.lrange("a", 0, -1);
    
    for (String s:a){
       System.out.println(s);
    }
    
    System.out.println("插入");
    //在指定的位置插入
    jedis.linsert("a", ListPosition.BEFORE,"值2","值5");
    
    List<String> b = jedis.lrange("a", 0, -1);
    
    for (String s:b){
        System.out.println(s);
    }

    List小结:

      list实际上是一个链表,before Node after(前后) ,left , right 都可以插入

      如果key不存在,创建新的链表

      如果key存在,新增内容

      如果移除了所有的值,空链表,也代表不存在

      两边插入修改的效率最高,中间元素相对效率低
     

      4.set(集合)

    涵义
    命令
    注释
    添加
    Sadd key val
     
    查询
    Smembers key
     
    判断值是否存在
    Sismember key val
     
    获取set大小
    Scard key
     
    删除值
    Srem key val
     
    随机获取值
    Srandmember key
     
    获取指定数量的随机值
    Srandmember key 数量
     
    删除随机的key
    Spop key
     
    将一个指定的值移动到另一个集合
    Smove 原key 目标key 移动val
     
    获取差集
    Sdiff key1 key2
     
    获取交集
    Sinter key1 key2
     
    获取并集
    Sunlon key1 key2
     

      5.zset(有序集合):

        zset是在set的基础上增加了一个排序值,zset k1 排序值 v1 

    涵义
    命令
    注释
    新增
    Zadd key 排序 val
     
    排序从小到大
    ZrangeBySecore key -inf +inf
    -inf负无穷,+正无穷
    排序从大到小
    Zrevrange key 0 -1
     
    查询
    Zrange key
     
    移除
    Zrem key val
     
    获取集合长度
    Zcard key
     
    获取指定区间的数量
    Zcount key 1 3
     

      6.geospatial(地理位置):

        可以推算地理位置信息,两地之间的距离,方圆几里的人

    涵义
    命令
    注释
    添加位置
    Geoadd key 经度 纬度 城市名称 经度 纬度 城市名称
    两极无法添加
    获取指定城市经纬度
    Geopos key 城市名
     
    获取两点之间直线距离
    Geodist key 城市1 城市2 距离单位
    距离单位:
    m : 米
    km : 千米
    mi : 英里
    ft: 英尺
    获取附近位置
    Georadius key 经度 纬度 半径 距离单位
     
    获取指定个数的数据
    Geradius key 经度 纬度 半径 距离单位 withdist withcoord count 数量
    例子:
    Ceoradius key 100 30 200 km withdist withcoord count 2
     
    找出指定位置的数据
    GeoradiusByMember key 城市名 半径 距离单位
     
    根据key和城市名获取kash值
    geohash key 城市名 城市名
    将二维的经纬度转换为一维的字符串,如果两个字符串越近那么距离越近

        Geo底层实现原理为zset可以使用zset命令操作Geo的值

      7.HyperLogLog:

        基数不重复的元素

    涵义
    命令
    注释
    新增
    PFadd key val
     
    统计(忽略重复数据)
    PFcount key
     
    合并
    PFmerge 新key 被合并key1 被合并key2
     

            问题:

              一个人访问一个网站多次但是还是算一个人

           传统解决:

              set集合保存用户id,然后就可以统计set中的元素数量来做判断,但是这个方式如果保存大量的用户id会比较麻烦

           用HyperLogLog解决:

              优点:

                占用的内存是固定的,2^64不同的元素技术,只需要用12kb的内存

              缺点: 

                有0.81%的错误率

      8.BitMaps(位存储):

         BitMaps位图数据结构,都是操作二进制位来进行记录,就只有0和1两个状态

    涵义
    命令
    注释
    添加
    setbit key 位 值
    例子:
    setbit key 1 a
    获取值
    setbit key 位
     
    统计
    bitcount key
     

    7.redis事务 :

      1.Redis单条命令是保证原子性的,但是事务不保证原子性,Redis事务本质就是一组命令的集合,在事务执行过程中会按照顺序执行
      2.Redis事务没有隔离级别的概念,所有的命令在事务中,并没有直接执行,只有发起执行命令的时候才会执行
      
      事务命令:
        开启事务:Multi
        命令队列:需要执行的命令
        执行事务:exec
    multi
    set key val
    set key1 val2
    get key
    exec
    执行后会输出结果

        取消事务:discard

    multi
    set key val
    set key1 val2
    get key
    discard
    
    事务队列内的东西都不会执行

    当redis内有编译异常时所有操作都不会成功,但是当有运行时异常只有报异常的那个命令不会成功

      监控:

        悲观锁:

          很悲观,感觉什么时候都会出问题,无论做什么都会加锁

        乐观锁:

          很乐观,感觉什么时候都不会出问题,无论什么时候都不加锁。

        更新的时候去判断一下在此期间是否有人修改过这条数据。

      加锁:watch key 

    set qian 100
    
    用户一:
    watch qian
    mulit
    set qian 200
    
    //在这个时候用户二先执行了
    
    exec 执行事务;这个时候会执行失败,因为乐观锁会去对比版本号,版本号对应不上所以执行失败,执行失败后乐观锁会自动解锁
    
    用户二;
    set qian 10

      解锁:unwatch

    8.Jedis :

       Jedis是redis官方推荐的连接java连接Redis的中间件
      
      1.引入依赖
        <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
        </dependency>

      2.事务操作

    Jedis jedis = new Jedis("127.0.0.1",6379);
    Transaction multi = jedis.multi();
    multi.set("测试的值","测试的值");
    multi.exec();

    其他的操作和命令是一样的

    9.SpringBoot整合Redis:

       在SpringBoot2.x之后链接redis使用的是lettuce,因为jedis采用的是直连,多个线程操作的话是不安全的,如果想要避免线程不安全需要使用jedis线程池,而lettuce采用netty实例可以在多个线程中进行共享,不存在线程不安全的情况。
         
        1.引入依赖
         <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
         </dependency>

        2.application配置

    spring.redis.host=127.0.0.1 
    spring.redis.port=6379    
    spring.redis.database=0

        3.注入redisTemplate

    @Autowired
    private ReisTemplate redisTemplate;
    
    //操作不同的数据类型:
    //操作字符串:redisTemplate.opsForValue() 
    //操作list:redisTemplate.opsForList()
    //操作set:redisTemplate.opsForSet()
    //操作Hash:redisTemplate.opsForHash()
    //操作ZSet:redisTemplate.opsForZSet()
    //操作Geo:redisTemplate.opsForGeo()
    //操作HyperLogLog:redisTemplate.opsForHyperLogLog()      
    
    //获取redis连接对象:
    RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
    //清除数据库内容
    connection.flushDb();

        4.解决redis中文乱码问题

                  

                因为redis默认使用jdk序列化,所以会导致中文乱码,所以需要我们自己来配置
                
     
     
      5.定义自己的RedisTemplate
        (1)序列化类型
                       
      
        (2)配置RedisConfig类
    @Configuration
    public class RedisConfig {
    
        @Bean
        public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
            RedisTemplate<String, Object> template = new RedisTemplate<>();
    
            //配置参数序列化方式
            Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
    
            //对json进行转译
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL)
            jackson2JsonRedisSerializer.setObjectMapper(om);
    
            template.setKeySerializer(jackson2JsonRedisSerializer);
    
            //String序列化
            StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    
            //设置key采用String方式序列化
            template.setKeySerializer(stringRedisSerializer);
            //设置hash的key采用String方式序列化
            template.setHashKeySerializer(stringRedisSerializer);
            //设置value采用json序列化
            template.setValueSerializer(jackson2JsonRedisSerializer);
            //设置hash的val采用json序列化
            template.setHashValueSerializer(jackson2JsonRedisSerializer);
            
            template.afterPropertiesSet();
    
            //设置连接工厂
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }
    }

  • 相关阅读:
    企业付款到零钱,现金红包
    Ubuntu 添加,删除ppa
    Ubuntu16.04下的主题美化
    Mysql 统计查询
    crontab修改默认编辑器
    highcharts PHP中使用
    解决ubuntu开机进入grub界面的问题
    商城功能,助力商家
    PHP获取固定概率
    PHP概率,抽奖
  • 原文地址:https://www.cnblogs.com/HQ0422/p/10719254.html
Copyright © 2011-2022 走看看