Redis概述 redis是一个开源的,先进的key-value存储的非关系型数据库. 它通常被称为数据结构服务器,因为键可以包含 字符串(strings),哈希(hashes),链表(lists),集合(sets)和有序集合(sorted sets) 这些数据类型都支持push/pop,add/remove及交集和并集,不同方式的排序及更丰富的操作 为了保证效率,数据都是缓存在内存中的,它也可以周期性的把更新的数据写入磁盘 页面教程: http://www.runoob.com/redis/redis-tutorial.html 优缺点 优点 非关系型的 分布式的 开源的 水平可扩展的 缺点 不支持sql标准 不遵循事务的ACID属性(不完善) 使用场景 对数据高并发读写 对海量数据的高效率存储和访问 对数据的高扩展性和高可用性 Redis适用场合 取最新的n个数据的操作 排行榜应用,取top n操作 需要精确设定过期时间的应用 计数器应用 unique操作,获取某段时间所有数据的去重复的值 实时系统,反垃圾系统 Pub/Sub构建实时消息系统 构建队列系统 缓存 下载 http://redis.io window可下载exe程序,无需编译(https://github.com/MSOpenTech/redis/releases) linux可下载源码,再编译 启动 服务端 运行redis-server.exe,第一个参数为配置文件的位置,默认端口号6379 redis-server redis.conf 如果需要后台运行,可修改配置文件 daemonize yes 客户端 运行redis-cli.exe redis-cli -h 127.0.0.1 -p 6379 redis-cli -h 127.0.0.1 -p 6379 -a 密码 常用命令 服务器命令 select 选择数据库(初始数据库为0-15) select 1 ping 测试连接是否正常(正常返回pong,否则返回Could not connect to Redis...) ping info 返回redis的相关信息 info config get 获得相关配置的值 config get * config get timeout 键值命令 keys 返回满足给定条件的所有key keys * --取出所有key keys my* --取出my开头的key randomkey 随机返回一个key randomkey dbsize 返回当前数据库key的数目 dbsize exists 判断一个key是否存在 exists name del 删除一个key del name flushdb 删除当前数据库的所有key flushdb flushall 删除所有数据库的所有key flushall rename 重命名key rename name newname move 将key移动到另一个数据库 move name 2 --将name键从当前数据库移动到2号数据库 expire 设置一个key的过期时间,单位为秒 expire name 10 persist 取消一个key的过期时间 persist name ttl 查看一个key的过期时间,单位为秒,过期或无过期时间返回-1 ttl name type 返回值的类型(不存在的key返回none) type name string操作 设置值 set name zhangsan --设置name的值为张三 setnx name zhangsan --设置name的值为张三,如果name键不存在,则设置值,返回1,如果键已经存在,则不设置值,返回0 mset name zhangsan age 14 --设置多个值,全部成功返回ok,全部没有成功返回0 msetnx name zhangsan age 14 --设置多个值,全部成功返回ok,全部没有成功返回0,如果有一个key是存在的,则全部不成功 setex name 10 zhangsan --设置name的值为张三,并设置有效期为10秒,过期后键值对(不只是值)被删除 获取值 get name mget name age --获取多个值 其他 替换值并获取原来的值 getset name zhangsan --设置name的值为张三,并返回name原本的值 设置/获取部分值 setrange email 6 qq.com --将email原先的值,从索引为6的位置开始后6个字符串替换为qq.com,替换完成后返回总字符串的长度 例: set email 1123734918@qq.com setrange email 11 163.com.cn get email --1123734918@163.com.cn setrange email 11 qq get email --1123734918@qq3.com.cn 注意这里的替换长度的问题,替换后的字符串长度不会低于原字符串长度 getrange name 0 5 --获取name索引为(0,5)的值,两边都包含 数字递增 incr age --使age的值自增1,如果age本来不存在,则默认为0 incrby age 5 --使age的值自增指定的数值,如果age本来不存在,则默认为0 decr age --使age的值自减1,如果age本来不存在,则默认为0 decrby age 5 --使age的值自减指定的数值,如果age本来不存在,则默认为0 注: incrby 和 decrby的参数可以为负数,所以incrby不一定为增加,也可以为减少 追加值 append name zhenshuai --追加字符串,并返回新字符串的长度 获得字符串长度 strlen name hashes操作 概述 Redis hash是一个string类型的field和value的映射表 hash特别适合存储对象,相较于string,hash会占用更少的内存,还可以更方便的获取整个对象 设置值 hset myhash name zhangsan --对哈希表myhash的键name设置值,myhash为自定义的hash的名称,注意:hash的名称中可以包含: hsetnx myhash name zhangsan --设置值,如果name已经存在返回0,设置成功返回1 hmset myhash name zhangsan age 14 --设置myhash的多个值 获取值 hget myhash name hmget myhash name age hkeys myhash --返回所有键 hvals myhash --返回所有值 hgetall myhash --返回所有的键和值 其他 数字递增 hincr age --使age的值自增1,如果age本来不存在,则默认为0 hincrby age 5 --使age的值自增指定的数值,如果age本来不存在,则默认为0 判断是否存在指定键 hexists myhash name --存在返回1,不存在返回0 删除键 hdel myhash age --成功返回1,不成功返回0 返回hash的所有键的数目 hlen myhash lists操作 概述 list是一个链表结构,主要功能是push,pop,获取一个范围内的所有值等,操作中key可以理解为链表的名称 Redis的list类型其实就是每个子元素都是string类型的双向链表,既可以从头部进和出,也可以从尾部进和出 添加元素 lpush mylist zhangsan --从头部添加字符串,返回list的大小 rpush mylist zhangsan --从尾部添加字符串,返回list的大小 linsert mylist before zhangsan lisi --在中间插入元素,在zhangsan前边(靠近头的位置)压入一个元素lisi,before为固定字符串 获取元素 lrange mylist 0 -1 --从头部获取元素,第一个参数为开始索引,第二个参数为结束索引,-1表示最后一个 lpop mylist --从头部弹出元素(获取并删除) rpop mylist --从尾部弹出元素(获取并删除) lindex mylist n --返回索引为n的元素 替换元素 lset mylist 0 zhangsan --将索引为0的元素替换为zhangsan 删除元素 lrem mylist n hello --从集合中删除值为hell的值,n为数字,当n>0时,表示删除的个数,n=0时表示全部删除,n<0时,表示从尾部删除n个.返回值为删除的个数 ltrim mylist 1 -1 --保留指定索引区间的值,其余的全部删除,成功返回ok 其它 将一个集合尾部的一个元素弹出并压入到第二个集合的头部 rpoplpush list1 list2 --返回值为移动的元素 获取集合长度 llen mylist sets操作 概述 set是string类型的无序集合 set中的元素是不可重复的 可以对集合进行取并集,交集,差集操作 添加元素 sadd myset hello --添加成功返回1,不成功返回0,如果添加重复值会返回0 获取元素 smembers myset --获取所有元素 spop myset --随机弹出一个元素(获取并删除) srandmember myset --随机返回一个元素(不删除) 删除元素 srem myset hello --返回值为0,1 其它 获取第一个集合对第二个集合的差集(返回第一个集合中存在而第二个集合中不存在的值) sdiff myset1 myset2 --注意:两个集合的位置不同,结果不同 获取第一个集合对第二个集合的差集,并存储 sdiffstore myset3 myset1 myset2 --将差集结果存储到myset3中,返回存储的元素个数 获取两个集合的交集 sinter myset1 myset2 获取两个集合的交集,并存储 sinterstore myset3 myset1 myset2 --将交集结果存储到myset3中,返回存储的元素个数 获取两个集合的并集 sunion myset1 myset2 获取两个集合的并集,并存储 sunionstore myset3 myset1 myset2 --将并集结果存储到myset3中,返回存储的元素个数 移动,从第一个集合移动到第二个集合 smove myset1 myset2 hello --将myset1中的hello元素移动到myset2中 返回集合的元素个数 scard myset 返回集合中是否存在指定元素 sismember myset hello sorted sets操作 概述 sorted set是set的一个升级版本,在set的基础上增加了一个顺序属性 顺序属性在修改元素时可以指定,每次指定后zset会自动重新按新的值调整顺序 顺序值可以相同,如果顺序值相同,则按字符串字典顺序进行排列. 添加元素 zadd myzset 1 hello --插入时要指定顺序值,从1开始,如果元素已存在且顺序和指定顺序值不同,则会更新顺序.返回值0,1(只更新顺序返回0) 获取元素 zrange myzset 0 -1 withscores --按顺序值升序排序,按索引值取,0,-1分别为开始索引和结束索引,withscores为固定字符串,表示输出顺序号 zrevrange myzset 0 -1 withscores --按顺序值降序排序,按索引值取 zrangebyscore myzset 2 3 withscores --按顺序值升序排序,按顺序值取 删除元素 zrem myzset one zremrangebyrank myzset 1 1 --按顺序值升序排序,按索引区间删除 zremrangebyscore myzset 2 3 --按顺序值升序排序,按顺序区间删除 其它 顺序自增 zincrby myzset 2 one --将one的顺序号增加2(其它元素的顺序号不变),返回改变后的值,增长值可为负数 返回指定元素的索引值(升序,按顺序值从小到大排列) zrank myzset one 返回指定元素的索引值(降序,按顺序值从大到小排列) zrevrank myzset one 返回指定顺序值区间的元素个数 zcount myzset 2 3 返回集合元素的总个数 zcard myzset 安全性 设置密码 在配置文件中设置.设置完后重启服务 requirepass 密码 登陆 连接服务器时 redis-cli -a 密码 或在连接到服务器后 auth 密码 主从复制 通过主从复制可以允许多个slave server拥有和master server相同的数据库副本. redis主从复制的特点 master可以拥有多个slave 多个slave可以连接master外,还可以连接到其它slave 主从复制不会阻塞master,在同步数据时,master可以继续处理client请求 提高系统的伸缩性 redis主从复制的过程 slave与master建立连接,发送sync同步命令 master会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集写命令并缓存 后台完成保存后,就将此文件发送会slave slave将此文件保存到硬盘上 操作 在slave的配置文件中加入配置 slaveof 主机ip 主机端口 masterauth 主机密码 主从信息可以使用info命令查看 role,slave0,master_link_status 事务处理 Redis对事务的支持目前还比较简单.Redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其它client的命令 当一个client在一个连接中发出multi命令时,这个连接会进入一个事务上下文 该连接后续的命令不会立即执行,而是先放到一个队列中,当执行exec命令时,redis会顺序的执行队列中的所有命令 事务命令 开启事务 multi 这样,当再执行命令时,会返回QUEUED,表示放入队列,并没有被执行,在这时进行get语句也不能获得值,而是命令被放入队列 如果在事务中修改了age的值但没有执行事务,则另一个客户端访问age会得到原来的值,表示未提交的事务没有被执行 执行事务 exec 取消事务 discard 注意:redis中如果事务中的某个操作没有成功,整个事务不会回滚 乐观锁 watch命令会监视给定的key,当exec时候如果监视的key从调用watch后发生过编号,则整个事务会失败(注意,只针对事务,对没有开启事务的操作无效) 可以调用watch多次监视多个key,这样就可以对指定的key加乐观锁了. watch是对连接有效的,事务也一样.如果连接断开,监视和事务对会被自动清除 执行exec,discard,unwatch命令也都会清除连接中的所有监视 命令示例: watch age 持久化机制 Redis是一个支持持久化的内存数据库,也就是说redis需要经常讲内存中的数据同步到硬盘来保证持久化 Redis支持两种持久化方式: 1.snapshotting(快照),默认方式 2.Append-only file(缩写aof) snapshotting方式 快照是默认的持久化方式,这种方式是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb 可以通过配置设置自动做快照持久化的方式.我们可以配置在n秒内如果超过m可key被修改就自动做快照 即最多每n秒做一次快照,这样就存在风险 在配置文件中修改 save 60 1000 --每60s检测一次,如果数据距上次持久化时超过1000个key被修改,则进行快照(可设置多个save条件) aof方式 aof比快照方式有更好的持久化性,是由于在使用aof时,redis会将每一个收到的写命令都通过write函数追加到文件中 当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容 在配置文件中修改 appendonly yes --启用aof持久化方式 下面三个选项选一个 appendfsync always --收到命令就立即写入磁盘,效率低,但保证完全的持久化 appendfsync everysec --每秒写入磁盘一次 appendfsync no --完全依赖操作系统,性能最高,但持久化没有保证 发布与订阅信息 发布/订阅(pub/sub)是一种消息通信模式,主要的目的是解除消息发布者和消息订阅者的耦合 Redis作为一个pub/sub的server,在订阅者和发布者之间起到了消息路由的功能 订阅者可以通过subscribe和psubscribe命令向redis server订阅自己感兴趣的消息类型,redis将消息类型称为通道(channel) 当发布者通过publish命令向redis server发送特定类型的消息时,订阅该消息类型的全部client都会收到此消息 订阅者订阅某个消息类型 subscribe tv1 tv2 发布者发布消息 publish tv1 woshizhangsan 当订阅者订阅消息类型时,会阻塞当前会话.当发布者发布消息时,订阅者会同步收到通知 message tv1 woshi zhangsan 虚拟内存 Redis的虚拟内存与操作系统的虚拟内存不是一回事,但是思路和目的都是相同的 就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出宝贵的内存空间用于其他需要访问的数据 配置文件中修改 vm-enabled yes --开启vm功能 vm-swap-file /tmp/redis.swap --交换出来的value保存的文件路径 vm-max-memory 1000000 --redis使用的最大内存上限 vm-page-size 32 --每个页面的大小,32字节 vm-pages 134217728 --最多使用多少个页面 vm-max-threads 4 --用于执行内存交换的线程数量 really-use-vm yes --确定使用vm功能 使用java操作Redis 导入jar包 jedis-2.1.0.jar 示例程序 @Test public void TestConn() { // 连接本地的 Redis 服务 Jedis jedis = new Jedis("127.0.0.1", 6379); // 查看服务是否运行 System.out.println("Server is running: " + jedis.ping()); } @Test public void TestString() { // 连接本地的 Redis 服务 Jedis jedis = new Jedis("127.0.0.1", 6379); // 设置 redis 字符串数据 jedis.set("name", "wangmazi"); // 获取存储的数据并输出 System.out.println("name: " + jedis.get("name")); } @Test public void TestList() { // 连接本地的 Redis 服务 Jedis jedis = new Jedis("127.0.0.1", 6379); // 存储数据到列表中 jedis.lpush("tutorial-list", "Redis"); jedis.lpush("tutorial-list", "Mongodb"); jedis.lpush("tutorial-list", "Mysql"); // 获取存储的数据并输出 List<String> list = jedis.lrange("tutorial-list", 0, -1); for (int i = 0; i < list.size(); i++) { System.out.println("Stored string in redis: " + list.get(i)); } } @Test public void TestKeys() { // 连接本地的 Redis 服务 Jedis jedis = new Jedis("127.0.0.1", 6379); // 获取数据并输出 Set<String> set = jedis.keys("*"); for (String key : set){ System.out.println(key); } }
redis
最新推荐文章于 2024-04-04 11:33:29 发布