您的位置:首页 > 数据库 > Redis

非关系型数据库Redis之Nosql

2018-11-05 22:23 330 查看

1)概念:开源的高性能的Nosql非关系型数据库,数据能保存内存,也可以做持久化操作,以key-value存储格式,实质时一种数据结构化存储方法的集合;

2)关系型数据库:由行和列组成的数据表结构,表之间存在联系;

3)非关系型数据库改变web的发展

  • Web1.0:只提供数据的读的能力
  • Web2.0:更强调写的能力。论坛,购物,贴吧..
  • Web3.0: 移动化,物联化供数据的读能力,虚拟化,智能化、云计算。
  • Web4.0  直播(并发技术)、AI(学习能力)、大数据(IT-DT)

4)常见的非关系型数据库产品

键值格式的代表Redis、Oracle BDB 场景高并发、涉及处理大数据;

列存储的代表HBase                            场景分布式的文件系统 比如 百度云

文档型的代表MongoDb                       百度地图

图形数据库代表的                                游戏任务地图

5)Redis优点:

1数据在内存,读写快、并发能力强

2支持存储的数据类型有string、list、set、zset、hset;

3支持数据持久化,支持订阅发布(subscribe/publish)

4断电数据不丢失:pdb(改变key生成数据文件)、aof(启动默认记录数据)

5Java,C/C++,C#,PHP,JavaScript等客户端,使用很方便

6)Mysql、Memcached和Redis

Mysql      不支持存储内存,能做持久化、关系型、读写弱

Memcached 支持存储内存,不支持持久化、非关系型、读写强;

Redis       既支持内存存储又支持本地磁盘存储、非关系型、读写强;

7)Redis使用场景

1)缓存:经常查询的数据存放内存,读写快,节约时间,减轻数据库压力

2)计数器应用:统计用户注册数量、网址访问数量

3)实时防攻击系统:当遇到暴力攻击,把访问ip保存数据库判断,设置过期时间,在这时间内超过多少次访问可以判断是网络暴力,并进行封ip,并设置过期时间解封,人为是不可能在指定时间请求那么多次请求的;

4)排行场景:周积分、月积分、季度积分等

5)设定有效期的应用:有期限的游戏道具、会员等...

6)自动去重:因为set集合的key-value的key是唯一性的,相同key添加会追加;

7)队列场景:秒杀购物、,内存就能处理高并发访问。限流

8)消息订阅/发布

8)windows下的安装和使用

解压Redis

设置启动文件

设置启动时默认的数据库密码(在redis.conf设置requirepass 密码)

Nosql的sql语句使用

Set key value 设置值

Get key 获取值

mset 同时设置一个或多个 key-value 对 merge

mget 返回所有(一个或多个)给定 key 的值

incr key 将 key 中储存的数字值增1(key不存在,则初始化为0,再加1)

decr key 将 key 中储存的数字值减1(key不存在,则初始化为0,再减1)

incrBy key num自增多少

decrBy key  num

Setex key seconds value 同时设置key的过期时间和值

keys *  获取所有key列表

del key  删除key

expire key xx 设置key的过期时间(xx秒后过期)

ttl key 查看key的过期时间

flushall 清空整个redis服务器数据所有的数据库全部清空

flushdb  清除当前库,redis中默认有16个数据库,名称分别为0,1,2.。。15(可以用select index 命令来切换数据库)

list集合可以看成是一个左右排列的队列(列表)

lpush key value 将一个或多个值 value 插入到列表 key 的表头(最左)

rpush key value 将一个或多个值 value 插入到列表 key 的表尾(最右边)

lpop key 移除并返回列表 key 的头(最左)元素。

rpop key 移除并返回列表 key 尾(最右)元素。

lrange key start stop 返回列表 key 中指定区间内的元素,查询所有的stop为-1即可

lrem key count value 根据count值移除列表key中与参数 value 相等的元素count > 0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。count = 0 : 移除表中所有与 value 相等的值。

lindex key index 返回列表 key 中,下标为 index 的元素

ltrim key start stop 对一个列表进行修剪,保留start和stop范围内的值

set集合一个无序的不重复值队列

set集合的常用操作

set集合是一个无序的不含重复值的队列

sadd  key member 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略

srem key member 移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略

smembers key   返回集合 key 中的所有成员。

对SortedSet(有序集合)的操作

hash类型类似于php的数组  java map

hset key name value//添加一个name=>value键值对到key这个hash类型

hget key name //获取hash类型的name键对应的值

hmset key name1 key1 name2 key2 //批量添加name=>value键值对到key这个hash类型

hmget key name1 name2//批量获取hash类型的键对应的值

hkeys //返回哈希表 key 中的所有键

hvals //返回哈希表 key 中的所有值

hgetall //返回哈希表 key 中,所有的键和值

事物(弱事物)

multi  标记一个事务块的开始

exec     执行所有事务块内的命令

订阅消息发布消息

9)Redis持久化配置(解决断电数据丢失问题)

Rdb数据文件

Redis.conf:根据900秒后 有1个key改变 就保存数据文件

Aof日志更新

启动redis服务就开始记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集,默认关闭该模式;

默认开启的appendonly yes   yes 开启,no 关闭

 

10)spring集成Redis

导spring依赖包、Redis核心包

asm-3.3.1.jar

cglib-2.2.2.jar

com.springsource.org.aopalliance-1.0.0.jar

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

commons-logging-1.1.1.jar

commons-pool2-2.4.3.jar

javassist-3.17.1-GA.jar

jedis-2.9.0.jar

log4j-1.2.17.jar

slf4j-api-1.7.2.jar

slf4j-log4j12-1.7.2.jar

spring-aop-4.1.2.RELEASE.jar

spring-aspects-4.1.2.RELEASE.jar

spring-beans-4.1.2.RELEASE.jar

spring-context-4.1.2.RELEASE.jar

spring-core-4.1.2.RELEASE.jar

spring-expression-4.1.2.RELEASE.jar

spring-test-4.1.2.RELEASE.jar

配置文件(Redis用户手册)applicationContext-redis.xml

[code]<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"  
    xmlns:context="http://www.springframework.org/schema/context"  
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xsi:schemaLocation="  
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">  
<!-- 扫描 -->
    <context:component-scan base-package="com.yyg" />
<!-- 连接池其他配置 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 忙时最大连接数 -->
        <property name="maxTotal" value="50" />
<!-- 最大空闲数 -->
        <property name="maxIdle" value="8" />
<!-- 最大等待时间 -->
        <property name="maxWaitMillis" value="1000" />
<!-- 测试连接库是否通畅 -->
        <property name="testOnBorrow" value="true"/>
<!-- 测试连接库返回信息 -->
        <property name="testOnReturn" value="true"/>
       <!--  <property name="testWhileIdle" value="true"/> -->
    </bean>

<bean id="shardedJedisPool"
class="redis.clients.jedis.ShardedJedisPool"  scope="singleton">
        <constructor-arg index="0" ref="jedisPoolConfig" />
        <constructor-arg index="1">
            <list>
<!-- 配置的redis连接属性 -->
                <bean class="redis.clients.jedis.JedisShardInfo">
<!-- 配置的redis连接池属性 密码 -->
                    <property name="password" value="123456"/>
<!-- 配置的redis连接池属性 本地ip-->
                    <constructor-arg name="host" value="localhost" />
<!-- 配置的redis连接池属性  端口号-->
                    <constructor-arg name="port" value="6379" />
<!-- 配置的redis连接池属性   过期-->
                    <constructor-arg name="timeout" value="2000" />

                </bean>
            </list>
        </constructor-arg>
    </bean>
</beans>

配置文件变量名需要的值

RedisDataSource接口 设值取值接口

getRedisClient() : 取得redis的客户端,可以执行命令了。
returnResource(ShardedJedis shardedJedis) : 将资源返还给pool
returnResource(ShardedJedis shardedJedis, boolean broken) : 出现异常后,将资源返还给pool (其实不需要第二个方法)

[code]/**
 * @author 阳彦刚
 *
 */
public interface RedisDataSource {
    public abstract ShardedJedis getRedisClient();
    public void returnResource(ShardedJedis shardedJedis);
    public void returnResource(ShardedJedis shardedJedis,boolean broken);

}

RedisDataSourceImpl实现 封装设值取值的实现类

[code]package com.yyg.redis;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
@Repository("redisDataSource")

public class RedisDataSourceImpl implements RedisDataSource {
   private static final Logger log =
                         LoggerFactory.getLogger(RedisDataSourceImpl.class);
    @Autowired
    private ShardedJedisPool    shardedJedisPool;
    public ShardedJedis getRedisClient() {
        try {
            ShardedJedis shardJedis = shardedJedisPool.getResource();
            return shardJedis;
        } catch (Exception e) {
            log.error("getRedisClent error", e);
        }
        return null;
}

//异常时返还pool
    public void returnResource(ShardedJedis shardedJedis) {
        shardedJedisPool.returnResource(shardedJedis);
    }

    public void returnResource(ShardedJedis shardedJedis, boolean broken) {
        if (broken) {
            shardedJedisPool.returnBrokenResource(shardedJedis);
        } else {
            shardedJedisPool.returnResource(shardedJedis);
        }
    }
}

RedisClientTemplate(最终取到或设值的类)

第二层的封装:RedisClientTemplate,例子实现了放值和取值。最后代码提供了全部命令的实现。
        代码就是映射性质的又一次调用jedis的方法而已,用了个broken来做标示符,决定返还资源的方式。
        这一层的目的主要也是让再上层的调用不需要关心pool中链接的取得和返还问题了

[code]package com.yyg.redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import redis.clients.jedis.ShardedJedis;

/**
* @author Administrator 阳彦刚
*/
@Repository("redisClientTemplate")
public class RedisClientTemplate {

private static final Logger log = LoggerFactory.getLogger(RedisClientTemplate.class);
@Autowired
private RedisDataSource redisDataSource;

public void disconnect() {
ShardedJedis shardedJedis = redisDataSource.getRedisClient();
shardedJedis.disconnect();
}

/**
* 设置单个值
*
* @param key
* @param value
* @return
*/
public String set(String key, String value) {
String result = null;
ShardedJedis shardedJedis = redisDataSource.getRedisClient();
if (shardedJedis == null) {
return result;
}
boolean broken = false;
try {
result = shardedJedis.set(key, value);
} catch (Exception e) {
log.error(e.getMessage(), e);
broken = true;
} finally {
redisDataSource.returnResource(shardedJedis, broken);
}
return result;
}

/**
* 获取单个值
*
* @param key
* @return
*/
public String get(String key) {
String result = null;
ShardedJedis shardedJedis = redisDataSource.getRedisClient();
if (shardedJedis == null) {
return result;
}

boolean broken = false;
try {
result = shardedJedis.get(key);

} catch (Exception e) {
log.error(e.getMessage(), e);
broken = true;
} finally {
redisDataSource.returnResource(shardedJedis, broken);
}
return result;
}
}

测试类

[code]package com.yyg.test;

import static org.junit.Assert.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.yyg.redis.RedisClientTemplate;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-redis.xml")
public class Redis_Spring_Test {
@Autowired
RedisClientTemplate redisClientTemplate;
/**
* @throws Exception
*	redis集成spring测试
*/
@Test
public void testName() throws Exception {
try {
//设值
String set = redisClientTemplate.set("name","yyg");
System.out.println(set);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

11)集群

简单介绍:一台服务器的内存是不够用于存储大量数据的,所以需要集群汇集多个服务器存储数据;

12)Redis实战 缓存的使用

一 Crm导入Redis的2个包

commons-pool2-2.4.3.jar

jedis-2.9.0.jar

二 配置文件applicationContext-Redis.xml,applicationContex引入

注意 更新配置文件里的连接信息配置,文档与jar包代码不一致;

三 缓存数据库数据

导入使用Redis需要的对象资源接口、资源实现类、客户端模版

四 代码实现service实现层

[code]public class SystemMenuServiceImpl extends BaseServiceImpl<SystemMenu> implements ISystemMenuService{

private static final String menu ="menu";

@Autowired 

private SystemMenuMapper menuMapper;

@Autowired

private RedisClientTemplate redisClientTemplate;

@Override

public List<SystemMenu> getTreeData() {

List<SystemMenu> list=null;

//缓存 先找redis 没有找到就找数据库

String mensJson = redisClientTemplate.get(menu);//查询到数据

if(!StringUtils.isEmpty(mensJson)){

//找到 不查数据库 反序列化成list集合

list=JSON.parseArray(mensJson,SystemMenu.class);

return list;

}

//没找到 从数据库查询出来的集合变成json字符串  放入redis

list= menuMapper.getTreeData();

String jsonString= JSON.toJSONString(list);

redisClientTemplate.set(menu, jsonString);

return list;

}

13)淘汰策略

淘汰一些数据,达到redis数据量是有限制的,下面有7个淘汰策略

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还会根据引用计数器进行释放),这时如果内存不够时,会直接返回错误)

7)redis 确定驱逐某个键值对后,会删除这个数据并,并将这个数据变更消息发布到本地(AOF 持久化)和从机(主从连接)

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: