最近实习了,来了公司,接触到的都是分布式技术,同时要求对Rdis会用,所以就一遍看书学习,学了一段时间了,把自己所学总结下:
非关系型数据库,是键值对类型数据库。Redis,以字典的形式存储数据,类似于关系型数据库中的一个数据库实例可以有多个数据库一样。
Redis是将数据存储在内存中的。定时将内存中的数据与硬盘上的,或者文件中的数据进行同步。
安装和启动配置。
tar命令解压后,使用make命令安装,安装完以后相应的配置
daemonize: 如果需要在后台运行,把该项设为yes
pidfile: 配置多个pid的地址 默认在/var/run/redis/redis.pid
bind: 绑定IP,设置后只接受来自该ip的请求
port:监听端口,默认为6379
timeout:设置客户端连接时的超时时间,单位为秒
loglevel:分为4级,debug,verbose,notice,warnning
logtile:配置log文件地址
databases:设置数据库的个数,默认使用的数据库为0
save:设置redis进行数据库镜像的频率
Redis文件说明:
redis-server: Redis服务器
redis-cli: Redis命令行客户端
redis-benchmark: Redis性能测试工具
redis-check-aof: AOF文件修复工具
redis-check-dump: ROB文件检查工具
···如果想以后台形式启动redis,那么先修改上面的配置,然后在运行redis-server时,指定配置文件redis.cofig去运行就好了。
Redis的键的命名规范:
没有强制要求,但一般是采用"对象类型:对象ID:对象属性"来命名一个键。
····关于Reis的数据类型:5种
String是最简单的类型,一个Key对应一个Value,String类型是二进制安全的。Redis的String可以包含任何数据,比如JPG图片或者序列化的对象
1).Set方法:设置Key对应的值为String类型的Value(相同键值重复设置会覆盖)
eg: set name lijie
OK
2).Setnx方法:设置key对应的值为string类型的value,如果key已经存在,则返回0,反之返回1 nx是 no exist的意思。
eg: setnx name lijie_new //添加一个name=lajie_new.
0
3).Setex方法:设置key对应的值为String类型的Value,并指定此键值对应的有效期。
eg: setex haircolor 10 red
OK
4).Setrange方法:设置指定key的value值的子字符串(替换value的部分子串,从指定位置(下标从0开始)开始,用目标字符替换原字符,如果原字符长度大于目标字符,剩余字符仍然保留)
eg: setrange name 2 guo
(Integer)5 ---//“liguo”
5).Mset方法:批量设置数据,一次设置多个key的值,各个key-value之间用空格分隔,成功返回OK,表示所有值都设置了,失败返回0,表示没有值被设置
eg:mset key1 guobin key2 diwu key3 womenshiairen
OK
1).Get方法:通过键获取对应的值,一般是字符串类型
eg: get name
"lijie"
2).Getset方法:设置Key的值,返回Key的旧值
eg: getset name lijie
"guobin"
3).Getrange方法:获取指定key的Value值的子字符串。(可以指定返回子串位置,下标从0开始)
eg:getrange key3 2 4
"men"
4).Mget方法:批量获取数据,一次获取多个key的值,如果对于key不存在则返回nil
eg:mget key1 key2 key3 key4
1) "123"
2) "guobin"
3) "diwuaiguobin"
4) (nil)
5).incr方法:对Key的value值做++操作,并返回新的值。
eg: incr key1
(integer) 124
6).incrby方法:对Key的value值做+指定值的操作,如果key不存在时候会设置key,并默认值为0,并返回新的值。
eg: INCRBY key1 100
(integer) 234
INCRBY key4 0
(integer) 0
7).decr方法:对Key的value值做--操作,并返回新的值。
eg: incr key1
(integer) 124
8).decrby方法:对Key的value值做--指定值的操作,如果key不存在时候会设置key,并默认值为0,并返回新的值。
eg: INCRBY key1 100
(integer) 34
INCRBY key4 0
(integer) 0
这几个操作加减数的方法,如果是对于数据的正负是有影响的。
9).append方法:给指定key的字符串追加Value,返回新字符串值的长度。
eg: append name @qqew
(integer) 10
10).strlen方法:获取指定Key的value值的长度。
eg: strlen name
(integer) 20
1).hset方法:设置hash field为指定值,如果key不存在则先创建。
eg: hset myhash field1 Hello
(integer)1
2).hsetnx方法:设置hash field为指定值,如果key不存在,则先创建,如果存在则返回0.
eg: hsetex myhash field1 Hello
(integer)0
3).hmset方法:同时设置多个hash的多个field。
eg: mhset user:003 name lejie age 20 sex 1
integer 0
4).hGet方法:通过指定hsah field键所对应的值,不存在则返回nil。
eg: hget user:003 name
"lijie"
5)hmget方法:获取全部指定的hash field
eg:hmget myhash field1 field2
1)"lijie"
2)"world"
6).hincrby方法:给指定的hsah field上加上给定的值(值得正副也会影响到)。
eg:hincrby myhash age 8
(integer) 18
7).hexists方法:测试指定的hash field是否存在。(存在返回1,不存在返回0)
eg:hexists user:003 name
(integer) 1
8).hlen方法:返回指定hash的field数量(返回hash中所有的键数)。
eg:hlen user:003
(integer) 1
9).hdel方法:删除指定的hash的field(删除成功则返回1,失败返回0).
eg: hdel user:003 name
(integer) 1
10).hkeys方法:返回hash的所有field(键值).
eg:hkeys user:003
1).name
2).age
3).sex
11).hvals方法:返回hash的所有value值。
eg:hvals user:003
1)."lajie"
2)."20"
3)."1"
12).hgetall方法:获取某个hash中全部的field以及value.
eg:hgetall user:003
1).name
2).lijie
3).age
4).20
5).sex
6).1
注意:在使用Hash时 必须先指定 hash表的值 hash字段 字段所对应的值
list是链表结构,主要的功能是push,pop,获取一个范围的所有值等等,操作中key理解为链表的名字。 Redis的list类型其实就是一个,每个子元素都是String类型的双向链表。使用push,和pop可以使list即作为栈也可以作为队列。
1).lpush方法:在key对应list的头部添加字符串元素,返回当前list中的元素个数。
eg:lpush mylist "Hello"
(integer) 1
lpush mylist "World"
(integer) 2 //--World Hello
2).lrange方法:获取指定list中指定位置的值.(正数代表从头开始,负数代表从尾部开始,然后从头index到尾index)。
eg: lrange mylist 0 -1
1).World
2).Hello
3).rpush方法:在key对应list的尾部添加字符串元素,返回当前list中的元素个数。
eg:rpush mylist "Hello"
(integer) 1
rpush mylist "World"
(integer) 2 //--Hello World
4).linsert方法:在key对应list的特定位置前(before)或后(after)添加字符串。返回插入后list的元素个数.(方向:从头到尾)
eg:linsert mylist before "Hello" "world"
(integer) 2 //--World Hello
5).lset方法:设置list中指定下标的元素值(替换指定下标元素的值),成功返回OK。(这里的下标,从头开始数,下标从0开始)
eg:lset mylist 0 "world1"
OK //--world1 World
6).lrem方法:从key对应list中删除n个和Value相同的元素。(n < 0从尾部删除,n=0全部删除,n > 0从头部删除),返回删除成功元素的个数。
eg:lrem mylist 1 world1
(integer) 1 //--World
7).ltrim方法:保留指定key的值范围中的数据,返回OK。(从头开始,保留在范围内的数据,其它数据都删除)
eg: ltrim mylist 1 -1
OK
8).lpop方法:从list的头部删除元素,并返回删除元素(返回删除元素的value)。
eg:lpop mylist
"Hello" //--World
9).rpop方法:从list的尾部删除元素,并返回删除元素(返回删除元素的value)。
eg:rpop mylist
"World" //--Hello
10).rpoplpush方法:从第一个list的尾部移除一个元素并将其添加到第二个list的头部。
eg:rpoplpush mylist1 mylist2 //mylist1--Hello World mylist2--nil
"Hello" //mylist1--World mylist2--Hello
11).lindex方法方法:返回名称为Key的list中index(元素索引)位置的元素
eg:lindex mylist 0
"Hello"
12).llen方法:返回list链表中的长度。
eg:llen mylist
(integer) 2
Set是集合,它是string类型的无序集合。set是通过hash table实现的,对集合我们可以取并集,交集,差集.(实际应用:好友推荐,blog标签管理)
1).sadd方法:向名称为key的set中添加元素,成功返回1,否则返回0(表中已经有了相同元素)。
eg:sadd myset "Hello"
(integer) 1
2).srem方法:删除名称为key的set中的元素。删除成功返回1,否则返回0
eg:srem myset "Hello"
(integer) 1
3).smembers方法:获取set集合中所有的value值。
eg:smembers myset
1)"three"
2)"one"
4).spop方法:随机返回并删除名称为key的set中一个元素。
eg:spop myset
"one"
5).sdiff方法:返回所有给定key与第一个key的差集(两个Set集合的差集,谁在前面,以谁为标准)。
eg:sdiff myset1 myset2
"three"
6).sdiffstore方法:返回所有给定key与第一个key的差集,并将结果存为另一个key。1代表成功,0代表失败(取差集结果,存入到另一个新集合(第一个key))
eg:sdiffstore myset1 myset2 myset3
(integer) 1 //--myset1 "three"
7).sinter方法:返回所有给定key的交集。
eg:sinter myset1 myset2 myset3
"one"
8).sinterstore方法:返回所有给定key的交集,并将结果存为另一个key(第一个key)。
eg:sinterstore myset1 myset2 myset3
(integer)1 //--myset1 "one"
9).sunion方法:返回所有给定key的并集。
eg:sunion myset1 myset2
1)"one"
2)"two"
3)"there"
10).sunionstore方法:返回所有给定key的并集,并将结果存为另一个key(第一个key)。
eg:sunionstore myset4 myset1 myset2 myset3
(integer) 1 //--myset4 "one,two,there"
11).smove方法:将第一个key对应的set中移除member并添加到第二个对应的set中(1标识成功,0标识失败)。
eg:smove myset1 myset2 two
(integer)1 //--myset2 "one,two,there" myset1 "one"
12).scard方法:返回名称为key的set的元素个数。
eg:scard myset1
(integer) 2
13).sismember方法:测试member是否是名称为key的set的元素,1表示是,0表示不是。(指定集合中是否存在member)
eg:sismember myset one
(integer) 1
14).srandmember方法:随机返回名称称为key的set的一个元素,但不删除元素。
eg:srandmember myset
"one"
sorted set是set的一个升级版本,它在set的基础上增加了一个顺序属性,这一属性在添加,修改元素的时候可以指定,每次指定后,zset会自动重新按新的值调整顺序。可以理解为有两列MySQL表,一列存value,一列存顺序。(操作中key理解为zset的名字)。
1).zadd方法:向名称为key的zset中添加元素member,score用于排序。如果该元素存在,则更新其顺序。
eg:zadd myzset 1 one
(integer) 1
2).zrange方法:按照所给范围按顺序输出元素,0表示第一个元素下表,-1表示最后一个元素下标。(如果加上withscores那么元素和顺序号都会输出,如果不加,则不会输出顺序号)
eg:zrange myzset 0 -1 withscores
1)"one"
2)"1"
3)"two"
4)"2"
3).zrem方法:删除名称为key的zset的元素memeber
eg:zrem myzset "one"
(integer) 1
4).zincrby方法:如果在名称为key的zset中已经存在元素member,则该元素的score增加increment,否则向该集合中添加该元素,其score的值为increment。
eg:zincrby myzset 2 "one"
"3"
5).zrank方法:返回名称为key的zset中member元素的排名(按score从小到大排序)即下标(索引值)。
eg:zrank myzset "one"
(integer) 1
6).zrevrank方法:返回名称为key的zset中member元素的排名(按score从大到小排序)即下标(索引值)。
eg:zrevrank myzset "one"
(integer) 2
7).zrevrange方法:按照所给范围按逆序输出元素。(如果加上withscores那么元素和顺序号都会输出,如果不加,则不会输出顺序号)
eg:zrevrange myzset 0 -1 withscores
1)"two"
2)"2"
3)"one"
4)"1"
8).zrangebyscore方法:返回集合中score在给定区间的元素,按sorce的范围来输出(score一般指的是顺序)。
eg:zrangebyscore myzset 1 2 withscores
1)"one"
2)"1"
3)"two"
4)"2"
9).zcountf方法:返回集合中socre在给定区间的元素个数。
eg:zcount myzset 1 2
(integer) 2
10).zcard方法:返回集合中所有元素的个数。
eg:zcard myzset
(integer) 2
11).zremrangebyrank方法:删除集合中排名在给定区间(索引:不是顺序,下标从0开始)的元素(rank一般指的是索引)。
eg:zremrangebyrank myzset 1 1
(integer) 1
12).zremrangebyscore方法:删除集合中排名在给定区间(顺序)的元素(score一般指的是顺序)。
eg:zremrangebyrank myzset 1 1
(integer) 1
Redis:提供了丰富的命令对数据库和各种数据类型进行操作,这些命令可以在Linux终端使用。
命令分为两大类:
1.键值相关命令
基本的四种操作:
1.获取符合规则的键名列表
KEYS patten
patten指的是glob风格通配符格式:
?:匹配一个字符 *:匹配任意个字符(包括0个)
[]:匹配括号间的任一字符,可以使用“-”符号表示一个范围,如a[b-d]可以匹配“ab,ac,ad”
2.判断一个键是否存在
EXISTS key
如果键存在则返回一个整数类型1,否则返回0.
3.删除键
DEL key [key...]
可以删除一个或者多个键,返回值是删除的键的个数。
4.获取键值的数据类型
TYPE key
TYPE命令用来获取键值的数据类型,返回值可能是String(字符串类型),hash(散列类型),list(列表类型),set(集合类型),zset(有序集合类型).
其它相关命令:
1.expire :设置一个key的过期时间,设置成功返回1。
eg:expire name 10
2.move:将当前数据库中的key转移到其它数据库中,成功返回1。
eg:move name 1
4.persist:移除给定key的过期时间。
eg: persist name
5.ttl:测试key的过期时间。如果存在过期时间,会返回。如果过期时间被移除会返回-1
eg:ttl name
6.randomkey:随机返回key空间的一个key
eg:randomkey
7.rename:重命名key
eg:rname name newname
2.服务器相关命令
1.ping :测试连接是否存活。有响应正常PONG。
2.echo : 在命令行打印一些内容。
3.select:选择数据库,Redis数据库中对数据库命名按编号来命名,一个实例有个数据库(编号从0-15)。
eg:select 1
4.quit/exit :退出连接。
5.dbsize : 返回当前数据库中key的总数目。
6.info : 获取服务器的信息和统计。
7.config get : 实时转储收到的请求。(后面加配置的参数,如果*是将全部的值都显示出来)
8.flushdb : 删除当前选择数据库中的所有key.
9.flushall :删除所有数据库中的所有的键
1.安全性:设置客户端连接后进行任何其他指定前需要使用密码,在配置文件中设置requirepass "口令" 。
1.进入数据库后auth授权命令,通过auth授权给当前用户,auth + "口令"。
2.登录进入客户端时候加-a + "口令"
2.主从复制:通过主从复制可以允许多个slave server拥有和master server相同的数据副本。
特点:1.Master可以拥有多个slave。
2.多个slave可以连接同一个master外,还可以连接到其它slave。
3.主从复制不会阻塞master,在同步数控时,master可以继续处理client请求。
4.提高系统的伸缩性
配置主从服务器,在slave上配置:
1.slaveof 主机IP 端口 2.masterauth 安全口令.(可以通过info 来确定主从关系)
3.事务处理:Redis对事物的支持目前还比较简单。Redis只能保证一个client发起事务中的命令可以连续执行,而中间不会插入其它的client命令(因为,当事务中出现错误时,错误之后的操作会回滚,之前的会执行)。
1.开启步骤:当一个client在一个连接中发出multi命令时开启事务,该连接后续的命令不会立即执行,而是先放入一个队列中,当执行exec命令时,redis会顺序的执行队列中的所有命令。
2.取消步骤:当一个client在一个连接中发出multi命令时开启事务,该连接后续的命令不会立即执行,而是先放入一个队列中,当执行discard命令时,取消事务,回滚事务。
3.乐观锁:大多数是基于数据版本(version)的记录机制实现的。一般是加一个"version"字段来实现,读出数据一同读出,之后更新时,对此版本号+1.当提交数据时将读出的版本号与数据库中的疾苦进行比较,如果提交的版本号>=数据库当前版本号,则予以更新,否则拒绝更新,视为过期数据。
Redis事务本身,如果开启watch(查看某个key是是否有更新)相当于加上乐观锁,断开连接,监视和事务都会被清除,exec,discard,unwatch都会清除连接中的监视。
4.持久化机制:需要经常内存中的数据同步到硬盘上来保证持久化。
Redis支持的两种持久化方式:
1.snapsshotting(快照)也是默认方式。
默认的持久化方式:这种放是将内存中的数据以快照的方式写入到二进制文件中,默认的文件名为dump.db,存的是数据。可以通过配置设置自动做快照持久化的方式,可以配置redis在n秒内如果超过m个key被修改就自动作快照。
eg: save 900 1 //--如果900秒内超过1个key被修改,则发起快照。
2.Append-only file(aof)的方式:快照的方式不够严谨,有可能会丢失最后一次修改。使用AOF时,redis会将每一个收到的命令都通过write函数追加到文件中,当redis重启时会通过重新执行文件中配置的命令在内存中重建整个数据库的内容,默认文件名为appendonly.aof,存的是操作。
配置:appendonly yes //启动AOF持久化方式
下列三种,根据需求选择一种:
#apendfsync always //收到写命令就往磁盘写,最慢,但是保证完全的持久化
#apendfsync everysec //每秒钟写入磁盘一次,在性能和持久化方面做了很好折中
#apendfsync no //完全依赖OS,性能最好,持久化没保证。
5.发布订阅消息:
发布和订阅(pub/sub)是一种消息通信模式,主要的目的是解除消息发布者和消息订阅者之间的耦合。redis充当一个消息路由的功能。订阅者可以通过subscribe和psubscribe命令向redis server订阅自己感兴趣的消息类型,redis将信息类型称为通道。订阅之后,发布者发布消息,所有的订阅者都会接收到。
6.虚拟内存的使用:虚拟内存就是把不经常访问的数据从内存交换到硬盘中。
VM的相关配置:
vm-enabled yes //开启vm的功能
vm-swap-file /temp/redis.swap //交换出来的value保持的文件路径
vm-max-memory 1000000 //redis使用的最大内存上限
vm-page-size 32 //每个页面的大小32字节
vm-pages 134217728 //最多使用多少页面
vm-max-threads 4 //用于执行value对象的工作线程数量
还需要配置文件上 加一段配置指令 really-use-vm yes
主要是Jedis的用法,参考官方文档,下面提供了一个封装的API
public class RedisAPI {
private static JedisPool pool = null;
/**
* 构建redis连接池
*
* @param ip
* @param port
* @return JedisPool
*/
public static JedisPool getPool() {
if (pool == null) {
JedisPoolConfig config = new JedisPoolConfig();
//控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;
//如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
config.setMaxActive(500);
//控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。
config.setMaxIdle(5);
//表示当borrow(引入)一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛出JedisConnectionException;
config.setMaxWait(1000 * 100);
//在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
config.setTestOnBorrow(true);
pool = new JedisPool(config, "192.168.2.191", 8888);
}
return pool;
}
/**
* 返还到连接池
*
* @param pool
* @param redis
*/
public static void returnResource(JedisPool pool, Jedis redis) {
if (redis != null) {
pool.returnResource(redis);
}
}
/**
* 获取数据
*
* @param key
* @return
*/
public static String get(String key){
String value = null;
JedisPool pool = null;
Jedis jedis = null;
try {
pool = getPool();
jedis = pool.getResource();
value = jedis.get(key);
} catch (Exception e) {
//释放redis对象
pool.returnBrokenResource(jedis);
e.printStackTrace();
} finally {
//返还到连接池
returnResource(pool, jedis);
}
return value;
}