redis基础整理

非关系型数据库NoSQL:

NoSQL特点:易扩展、灵活的数据模型、大数据量,高性能、高可用

 为什么使用:

  高并发读写High performance  实时统计,在线人数

  海量数据高效存储和访问 Huge Storage

  高可扩展和高可用性 High Scalability High

NoSQL数据库四大分类:键值存储、列存储、文档数据库、图形数据库 

Redis

REmote DIctionary Server(远程字典服务器)

C语言开发的一个开源高性能键值对分布式内存数据库,

支持数据持久化,支持异步将内存中数据保存在磁盘中,同时不影响服务,重启时可再次加载使用

支持的多种键值数据类型

字符串类型、列表类型、有序集合类型、散列类型、集合类型

(官方测试性能:五十个并发程序执行十万次请求,读速度11万次/秒 写8万次/秒)

应用场景:

  1. 缓存:数据查询、新闻商品内容,聊天室在线好友列表
  2.  任务队列,秒杀、抢购
  3. 网站访问统计
  4. 数据过期处理精确到毫秒,
  5. 应用排行榜,
  6. 分布式集群架构中的session分离

安装:

Windows下:下载安装包解压即可

Linux下:

启动方式:

  前端启动:window下运行根目录redis-server.exe或者cmd进入目录运行 redis-server.exe

Linux下进入bin路径输入:redis-server

后端启动:修改conf配置文件,将daemonize no改为daemonize yes,然后进入bin目录运行redis-server ./redis.conf

执行ps -ef | grep -i redis 查看是否运行

进入bin目录执行redis-cli shutdown 停止redis运行

给redis发送命令操作数据库

启动redis服务后,进入bin目录执行redis-cli

存入数据:set name zhangsan

获取数据:get name

  查看key:keys *

  删除键值对:del name

传统的数据库的ACID

A 原子性atomicity 事务的所有操作要么全做完,要么都不做(回滚)

C 一致性Consistency 数据库要一直处于一致性的状态

I 独立性 Isolation 并发的事务间不会互相影响

D 持久性 Durability 事务提交后数据会保存在数据库,宕机也不会丢失

 

NoSQL中的CAP  (一个分布式系统不能三个都满足,最多只能满足两个)

C 强一致性 Consistency

A 可用性 Availability

P 分布式容错性Partition tolerance

因此

CA 传统Oracle数据库满足

AP +弱一致性,大多数网站架构选择

CP Redis、MongoDB

BASE 解决强一致性引起的可用性问题而提出的解决方案

BASE 即基本可用,软状态,最终一致

 

分布式:不同的多台服务器上部署不同的服务模块,他们之间通过Rpc/Rmi之间通信和调用,对外提供服务和组内协作

集群:不同的多台服务器上部署相同服务模块,通过分布式调度软件进行统一调度,对外提供服务和访问

 

安装和测试

下载:wget http://download.redis.io/releases/redis-4.0.11.tar.gz

解压: tar -zxvf redis-4.0.11.tar.gz

没安装gcc的安装gcc到系统:yum install gcc

编译:make

将命令文件加到bin目录下:make install

报错可能是bin目录下没有执行文件,从而不能在任意目录下执行

可将执行文件拷贝到目录 cp -r /usr/local/bin/.  /usr/bin

查看是否运行  ps -ef|grep redis

启动redis命令:

   进入到bin目录,执行指令文件:

[root@izvluy1jk36n8jz admin]# cd /usr/local/bin

[root@izvluy1jk36n8jz bin]# ls -l

total 21872

-rwxr-xr-x 1 root root 2451208 Oct  2 22:34 redis-benchmark

-rwxr-xr-x 1 root root 5774352 Oct  2 22:34 redis-check-aof

-rwxr-xr-x 1 root root 5774352 Oct  2 22:34 redis-check-rdb

-rwxr-xr-x 1 root root 2617232 Oct  2 22:34 redis-cli

lrwxrwxrwx 1 root root      12 Oct  2 22:34 redis-sentinel -> redis-server

-rwxr-xr-x 1 root root 5774352 Oct  2 22:34 redis-server

[root@izvluy1jk36n8jz bin]# redis-server /redis/redis.conf

7580:C 03 Oct 11:33:33.718 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo

7580:C 03 Oct 11:33:33.718 # Redis version=4.0.11, bits=64, commit=00000000, modified=0,

 

pid=7580, just started

7580:C 03 Oct 11:33:33.718 # Configuration loaded

 

测试性能

[admin@izvluy1jk36n8jz bin]$ redis-benchmark

启动客户端

[root@izvluy1jk36n8jz bin]# redis-cli -p 6379

输入ping测试是否成功连接

127.0.0.1:6379> ping

PONG

连接成功,存键值对

127.0.0.1:6379> set name zhangsan

OK

读取键值对

127.0.0.1:6379> get name

"zhangsan"

127.0.0.1:6379> shutdown

not connected> exit

 

Redis基础知识

  1. redis是单进程模型处理客户端请求
  2. 默认16个数据库

  选择切换第2个库:输入: select 1

  1. Dbsize 查看当前库的key数量
  2.  keys * 列出所有key

    Keys  k? 就像正则表达式,列出k开头的key

  1. FLUSHDB 清空当前数据库所有key

   FLUSHALL 清空所有数据库的key

  1. Redis索引都是从零开始,默认端口6379
  2. 数据类型

     String类型二进制安全的,可以是任何数据,包括图片或序列化的对象,理论最大支持512M

DEL name 删除

append  name  111  由张三变成zhangsan111

STRLEN name  则显示name的值zhangsan111的strlen是11

值是数字,则可加减 ,必须是数字

Incr 、decr、incrby、decrby

127.0.0.1:6379> set k2 10

OK

127.0.0.1:6379> set k3 v3

OK

127.0.0.1:6379> incr k2

(integer) 11

127.0.0.1:6379> incr k2

(integer) 12

127.0.0.1:6379> decr k2

(integer) 11

127.0.0.1:6379> decr k2

(integer) 10

127.0.0.1:6379> incrby k2 3

(integer) 13

127.0.0.1:6379> incrby k2  5

(integer) 18

127.0.0.1:6379> decrby k2 4

(integer) 14

127.0.0.1:6379> decrby k2 1

(integer) 13

Getrange和setrange

127.0.0.1:6379> set k3 abc123abc

OK

127.0.0.1:6379> get k3

"abc123abc"

127.0.0.1:6379> getrange k3 2 6

"c123a"

127.0.0.1:6379> setrange k3 2 666

(integer) 9

127.0.0.1:6379> get k3

"ab6663abc"   

setex (即是set with expire的意思) 键秒 ,setnx(set if not exit)  

  127.0.0.1:6379> setex k4 10 vaaa123

OK

mset 、mget、 msetnx

127.0.0.1:6379> mset k3 v3 k4 v4

OK

127.0.0.1:6379> mget k3 k4

1) "v3"

2) "v4"

127.0.0.1:6379> msetnx k3 v33 k4 v44 k5 v55

(integer) 0

127.0.0.1:6379> mget k3 k4 k5

1) "v3"

2) "v4"

3) (nil)

127.0.0.1:6379> msetnx k4 v44 l5 v55

(integer) 0

127.0.0.1:6379> msetnx k5 v55 k6 v66

(integer) 1

127.0.0.1:6379> mget k5 k6

1) "v55"

2) "v66"

127.0.0.1:6379>

Hash类型:类似java的map<String,Object>,是一个键值对集合,hash是一个String类型的field和value的映射表,适合存储对象

     List类型

     Set集合类型 String类型的无序集合,通过HashTable实现

     Zset类型(sorted set :有序不可重复集合,带有可重复的double类型的分数)

常见数据类型操作命令:http://redisdoc.com

  1. NoSQL的数据操作指令

  Key关键字

Keys *

move name 2 将name键值对剪切到2数据库

Select 2

get name

clear 回到原来的指令状态

ttl name 查询name多久过期,-1则永不过期,-2已过期

EXPIRE name 10  设置name将10s过期

type name 查看name是什么类型

  1. Redis的发布订阅

  发布订阅是进程间的一种消息通信模式:发送者发送消息,订阅者接收消息,实际上很少用redis做发布订阅

不过redis的主要应用是分布式数据缓存

订阅多个(c1、c2、c3): subscribe c1、c2、c3

消息发布:publish c2 hello  向 c2发送消息hello

订阅多个,通配符*,psubscribe new*

收取消息,publish new1 messagenew1

  1. Redis的复制机制

  也就是主从(master 、slave)复制,主机数据更新后根据配置和策略自动同步到备份的master/slaver机制,Master以写为主,slaver以读为主

  从而能实现读写分离、容灾恢复

使用:

  1. 配从不陪主
  2. 从库配置:slaveof主库IP主库端口
  3. 修改配置文件细节操作

拷贝多个redis.conf文件

开启daemonize yes

Pid文件名字,修改端口

指定duank

Log文件名字

Dump.rdp名字

  1. 常用三招

一主二仆

薪火相传

反客为主

哨兵模式

  Info replication 该命令查看主从角色信息

  一主二从:(中心化,主机负担重)在从机上 SLAVEOF 127.0.0.1 6380 设置127.0.0.1 6380为它的主机,主机的数据备份到从机,从机不可对数据进行更新。主机出现故障,从机的角色不变,还是从机。

主机恢复后,恢复正常。从机故障,故障期间更新的数据,在故障恢复后,故障恢复后的从机数据并没有更新备份,因此,每次从机与master主机断开后都要重新连接,即重新执行SLAVEOF 127.0.0.1 6380建立连接

  薪火相传:(去中心化,减轻主机负担,但有复制延时),上一个slave是下一个slave的master,从机的角色还是slave,只不过不过会有连接的从机

  反客为主: 原来的主机故障,从机中会有新主机。SLAVEOF no one(该指令使当前数据库成为主数据库) ,其余从机,与新主机建立连接。原来的主机恢复后,故障期间新主机产生的更新数据原主机不会有

  哨兵模式:sentinel ,(复制延迟)可以说是自动版的反客为主 ,slave启动成功后会发送一个sync命令,master接到后会在后台进程执行完毕后将数据文件传送到slave,完成同步。全量复制(一般首次是全量复制)和增量复制(主机数据更新后从机跟着复制更新的部分),但如果是重连master,都会执行全量复制。主机出现故障后会在从机选出新主机,当主机恢复正常后就变成新主机的从机

在conf文件目录下新建sentinel.conf文件 touch sentinel.conf

配置sentinel.conf:如 sentinel monitor host6379 127.0.0.1 6379 1   (1表示自动投票选出主机)

保存文件,启动哨兵:如:redis-sentinel  /redis/sentinel.conf

 

 

  1.  Java使用Redis

  public static void main(String[] args) {
    //连接本地的 Redis 服务
    Jedis jedis = new Jedis("localhost");
    System.out.println("连接成功");
    //设置 redis 字符串数据
    jedis.set("name", "zhangsan");
    // 获取存储的数据并输出
    System.out.println("redis 存储的字符串为: "+ jedis.get("name"));

    //存储数据到列表中
    jedis.lpush("site-list", "Runoob");
    jedis.lpush("site-list", "Google");
    jedis.lpush("site-list", "Taobao");
    // 获取存储的数据并输出
    List<String> list = jedis.lrange("site-list", 0 ,2);
    for(int i=0; i<list.size(); i++) {
        System.out.println("列表项为: "+list.get(i));
    }
    // 获取数据并输出
    Set<String> keys = jedis.keys("*");
    Iterator<String> it=keys.iterator() ;
    while(it.hasNext()){
        String key = it.next();
        System.out.println(key);
    }
}

 

  1. 事务

public static void main(String[]args){
   /* Jedis jedis=new Jedis("localhost", 6379);
    System.out.println(jedis.ping());
    System.out.println("连接成功");
    Transaction transaction=jedis.multi();

    transaction.set("k1","v1");
    transaction.set("k2","v2");*/

    /*transaction.exec();*///事务提交
    //transaction.discard(); 取消事务

    transMethod();
}
public static boolean transMethod(){
    Jedis jedis=new Jedis("localhost",6379);
    int balance;
    int debt;
    int amtToSubtract=10;
    balance=Integer.parseInt(jedis.get("balance"));
    jedis.watch("balance");

    if(balance<amtToSubtract){
        jedis.unwatch();
        System.out.println("额度不足");
        return false;
    }else {
        System.out.println("执行事务……");
        Transaction transaction=jedis.multi();
        transaction.decrBy("balance",amtToSubtract);
        transaction.incrBy("debt",amtToSubtract);
        transaction.exec();
        System.out.println("事务提交……");
        System.out.println("剩余额度:"+jedis.get("balance"));
        System.out.println("下月应还:"+jedis.get("debt"));
        return true;
    }
}

  1. 主从复制

public static void main(String[]args){
    Jedis jedis_M=new Jedis("localhost",6379);
    Jedis jedis_S=new Jedis("localhost",6380);
    jedis_S.slaveof("localhost",6379);
    jedis_M.set("testMS","vvv");
    System.out.println(jedis_S.get("testMS"));
}

 

  1. JedisPool,redis数据连接池

public final class JedisUtil {

    private JedisUtil() {}

    private static JedisPool jedisPool;

    private static int maxtotal;

    private static int maxwaitmillis;

    private static String host;

    private static int port;

 

    /*读取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 = 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();

        }

    }

}

1

 

public class TestTransaction {
    public static void main(String[]args){
       /* Jedis jedis=new Jedis("localhost", 6379);
        System.out.println(jedis.ping());
        System.out.println("连接成功");
        Transaction transaction=jedis.multi();

        transaction.set("k1","v1");
        transaction.set("k2","v2");*/

        /*transaction.exec();*///事务提交
        //transaction.discard(); 取消事务

        transMethod();
    }
    public static boolean transMethod(){
        Jedis jedis=new Jedis("localhost",6379);
        int balance;
        int debt;
        int amtToSubtract=10;
        balance=Integer.parseInt(jedis.get("balance"));
        jedis.watch("balance");

        if(balance<amtToSubtract){
            jedis.unwatch();
            System.out.println("额度不足");
            return false;
        }else {
            System.out.println("执行事务……");
            Transaction transaction=jedis.multi();
            transaction.decrBy("balance",amtToSubtract);
            transaction.incrBy("debt",amtToSubtract);
            transaction.exec();
            System.out.println("事务提交……");
            System.out.println("剩余额度:"+jedis.get("balance"));
            System.out.println("下月应还:"+jedis.get("debt"));
            return true;
        }
    }

 

public class Test3 {
    public static void main(String[]args){
        JedisPool jedisPool=JedisPoolUtil.getJedisPoolInstance();
        Jedis jedis=null;
        try {
            jedis=jedisPool.getResource();
            //...进行数据更新的代码
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JedisPoolUtil.release(jedisPool,jedis);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值