redis笔记
什么是redis?
redis是使用c语言开发的一个高性能的键值对数据库。
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
redis与其他key-value存储的不同
1、redis有着更为复杂的数据结构,并且提供对他们的原子性操作,这是一个不同于其他数据库的进化路径。redis的数据类型都是基于基本数据结构的,同时对程序员透明,无需进行额外的抽象。
2、redis运行在内存中,但是可以持久化到磁盘,所以在对不同数据集进行高速读写时需要权衡内存,因为数据量不能大于硬件内存。在内存数据库方面的另一个优点是,相比在磁盘上相同的复杂的数据结构,在内存中操作起来非常简单,这样redis可以做很多内部复杂性很强的事情。同事,在磁盘格式方面他们是紧凑的以追加的方式产生的,因为他们并不需要进行随机访问。
redis内存占用情况
100万个键值对,0-999999,值为hello world,在32位系统笔记本上用100MB,同样的数据放到一个key里,需要16MB,这是因为键值是一个很大的开销,在Memcached上执行也是类似的结果,但是相对redis的开销要小一点,因为redis会记录类型信息引用计数等。
大键值对时两者的比例要好很多。
64位的系统比32位系统需要更多的内存开销,尤其是键值对较小时,这是因为64位的系统里指针占用了8个字节。但是,64位系统支持更大的内存,所以为了运行大型的redis服务器或多或少的需要使用64位的系统。
一个redis实例最多能存放多少的keys,List、Set、Sorted Set他们最多能存放多少元素?
理论上redis可以处理多大232的key是,并且在实际中,每个实例至少存放2亿5千万的keys。
任何list/set/sorted set都可以放2^32个元素。换句话说,redis的存储极限是系统中的可用内存值。
redis的内存用完了会发生什么?
随着现代操作系统的malloc,返回null是不常见的,通常服务器会启动swap交换,这样redis的性能会随之降低。info命令可以查看redis的使用量,因此可以编写一个监视redis服务器状态的临界监控脚本以检查服务器的状态。或者可以在配置文件中使用maxmemory配置redis可以使用的最大内存,如果达到设置的上限,redis的写命令会返回错误信息(但是读命令还可以正常返回)或者你可以将redis当缓存来使用配置淘汰机制,当reids达到内存上限时会冲刷掉旧的的内容。
**
redis应用场景
**
缓存(数据查询、短链接、新闻内容、商品内容等等)
分布式集群加载中的session分离
聊天室的在线好友列表
任务队列(秒杀、抢购、12306等)
应用排行榜
网站访问统计
数据过期处理,精确到毫秒
存放读写频繁的数据:用户身份验证token,使用redis list存放与时间顺序有关的id列表、编码等。
redis安装
1、官网下载
2、安装VMware,并且在VMware中安装centos系统。
3、将redis的压缩包,上传到linux系统
4、对redis的压缩包解压(解压后的文件是用c语言写的源码文件)
tar -zxf redis-3.2.8.tar.gz /opt/softwares/
5.安装c语言环境(安装centos之后,自带c语言环境)
yum install gcc-c++
6、编译redis源码
cd redis-3.2.8
make
7、安装redis
make install
redis启动
前端启动:src目录下redis-server&
前端关闭:ctrl+c
正常关闭:src目录下redis-cli shutdown
后端启动
1、将redis加压之后的源码包中的redis.conf文件拷贝到bin目录下
2、修改redis.conf文件,将daemonize改为yes
3、使用命令后端启动./redis-server redis.conf
4、查看是否启动成功 ps -aux | grep redis
关闭后端启动方式
强制关闭:kill -9 5071
正常关闭: ./redis-cli shutdown
如果强制关闭,不会进行持久化操作,会造成部分数据丢失。
redis自带客户端
启动redis-cli -h127.0.0.1 -p 6379
关闭ctrl+c quit
redis图形界面客户端
redis.conf中的数据库数量的设置:16个
如果不指定哪个数据库的话,默认将数据存储到下标为0的数据库中。
jedis客户端
reds不仅使用命令来操作,现在主流的语言基本都有支持。在官网网站里一些java的客户端,有Jedis,Redission,Jredis等。官网推荐Jedis/Redission.
单实例链接redis
Jedis jedis = new Jedis(“192.168.1.128”,6379);
jedis连接池链接redis服务器
JedisPool pool = new JedisPool(“192.168.1.128”,6379);
Jedis jedis = pool.getResource();
spring整合jedisPool
添加spring的jar包
配置spring配置文件applicationContext.xml
redis数据类型
1. String
赋值set key value
set test 123
取值get key
get test
取值并赋值getset key value(取出来的是原值)
getset s2 222
设置多个键值
mset key value[key value…]
获取多个键值
mget key[key…]
mset k1 v1 k2 v2 k3 v3
mget k1 k3
删除del key
del test
数值递增incr key,让当前键值递增,并返回递增后的值
incr num
增加指定的整数incrby key increment
incrby num 2 每次递增2
递减数值decr key
decr num
减少指定的整数decrby key decrement
decrby num 2
向尾部追加值append key value(向键值的末尾追加value,如果键不存在则将该键的值设置为value,即相当于set key value.返回值是追加后字符串的总长度)
append ste ” world!”
获取字符串长度strlen key
strlen str
2.Hash散列类型
hah叫散列类型,它提供了字段和字段值的映射,字段值只能是字符串类型,不支持散列类型、集合类型等其他类型。
赋值hset key field value 一次只能设置一个字段值。该命令不区分插入和更新操作,当执行插入操作时HSET命令返回1,当执行更新操作时返回0。
hset user username zhanglong
hmset key field value [field value …] 一次可以设置多个字段值
hmset user age 20 username lisi sex f
hsetnx key field value ,类似hset,区别:如果字段存在,该命令不执行任何操作
hsetnx user age 30
取值
hget key field 一次只能获取一个字段值
hget user username
hmget key field[field…]一次可以获取多个字段值
hmget user age username
hgetall key 获取key的所有字段值
hgetall user
删除字段
hdel key field[field…] 可以删除一个或者多个字段,返回值是被删除的字段个数
hdel user age
hdel user age username
增加数字
hincrby key field increment
hincrby user age 2 将用户的年龄加2
hexists key field 判断字段是否存在
hexitsts user name
hkeys key 只获取字段名
hkeys user
hvals key 只获取字段值
hvals user
hlen key获取字段数量
hlen user
3.list
有序可重复
ArrayList是使用数组来存储数据,查询块,增删慢
LinkedList是使用双向链表存储数据,增删块,查询慢,但是查询链表两端的数据也很快
redis的list是使用LinkedList来存储的,所以redis的list的操作,是操作list的两端数据来操作的。
lpush key value[value…] 向列表左边增加元素
lpush list:1 3 5
rpush key value[value…] 向列表右边增加元素
rpush list:1 6 7
lrange key start stop查看列表,获取列表中的某个片段,将返回start/stop之间的所有元素,包含两端的元素,索引从0开始,索引可以是负数,-1代表最右边的一个元素。
lrange list:1 0 2
lrange list:1 0 -1
lpop key 从列表左边弹出一个元素(将列表左边的元素从列表中移除,返回被移除的元素值)
lpop list:1
rpop key 从列表右边弹出一个元素
lpop list
llen key 获取列表中元素的个数
llen list:1
lrem key count value 删除列表中指定的值,删除列表中前count个值为value的元素,返回实际删除的元素个数。根据count值的不同,该命令的执行方式会有所不同:
当count>0,lrem会从列表左边开始删除。
当count=0,lrem会删除所有值为value的元素。
当count<0,lrem会从列表右边开始删除。
lindex key index 获得指定索引的元素值
lindex l:list 2
lset key index value设置指定索引的元素值
lset l:list 2 3
ltrim key start stop 只保留列表指定片段
ltrim l:list 0 2
linsert key before|after pivot value 该命令首先会在列表中从左到右查找值为pivot的元素,然后根据第2个参数是before还是after来决定将value插入到该元素的前面还是后面、
linsert list after 3 5
rpoplpush source destination 将元素从一个列表转移到另一个列表中
rpoplpush list newlist
4.Set
无序不可重复
sadd key member[member…] 增加元素
sadd set a b c
srem key member[member…]删除元素
srem set c d
smembers key 获得集合中的所有元素
smembers set
sismember key member 判断元素是否在集合中
sismember set a
sdiff key [key…] 集合的差集
sdiff setb seta 返回属于setb但不属于seta的元素
sinter key[key…] 集合的交集
sinter seta setb
sunion key[key…] 集合的并集
sunion seta setb
scard key 获得集合中元素的个数
scard seta
spop key 从集合中弹出一个元素。由于集合是无序的,所有该命令会从集合中随机选择一个元素弹出。
spop seta
5.Sortedset
又叫zset,是有序集合,可排序,但是唯一。
会给set中的元素添加一个分数,然后通过这个分数进行排序。
zadd key score member[score member…] 向有序集合中加入一个元素和该元素的分数,如果该元素已经存在则会用新的分数替换原有的分数。返回值是新加入到集合中的元素个数,不包含之前已经存在的元素。
zadd scoreboard 80 zhangsan 89 lisi 99 wangpan
zscore key member 获取元素的分数
zscore scoreboard lisi
zrem key member [member…] 移除有序集合key中的一个或多个成员,不存在的成员被忽略。当key存在但不是有序集合类型时,返回一个错误。
zrem scoreboard lisi
zrange key start stop[withscores] 获得排名在某个范围的元素列表,按照元素的分数从小到大的顺序返回索引从start到stop之间的所有元素,包含两端的元素。
zrange scoreboard 0 2
zrevrange key start stop [withscores] 获得排名在某个范围的元素列表,按照元素的分数从大到小的顺序返回索引从start到stop之间的所有元素,包含两端的元素。
zrevrange scoreboard 0 2
如果需要获得元素的分数,可以在命令尾部加上withscores参数
zrank key member 获取元素的排名,从小到大
zrang scoreboard lisi
zrevrank key member 获取元素的排名,从大到小
zrevrank socreboard lisi
zrangebyscore key min max [withscores][limit offset count]获得指定分数范围的元素
zrangebyscore scoreboard 90 97 withscores limit 1 2
zincrby key increment member 增加某个元素的分数,返回值是更改后的分数
zincrby scoreboard 4 lisi
zcard key 获得集合中元素的数量
zcard scoreboard
zcount key min max 获得指定分数范围内的元素个数
zcount scoreboard 80 90
zremrangebyrank key start stop 按照排名范围删除元素
zremrangebyrank scoreboard 0 1
zremrangebyscore key mix max 按照分数范围删除元素
zremrangebyscore scoreboard 80 100
常用命令
keys mylist* 返回满足给定pattern的所有key
exists key 确认一个key是否存在,存在返回1,不存在返回0
del key 删除一个key。
rename key newname 重命名key
type key 返回key对应值的类型
expire key seconds 设置key的生存时间,单位秒,key在多少秒后会自动删除。
ttl key 查看key生与的生存时间
persist key 清楚生存时间
pexpire key milliseconds 生存时间设置单位为毫秒
redis持久化
1、rdb方式
redis默认的方式,redis通过快照来讲数据持久化到磁盘中。
设置持久化快照的条件:
在redis.conf中修改持久化快照的条件,如下:
save 900 1
save 300 10
save 60 10000
持久化文件存储的目录
在redis.conf中可以指定持久化文件存储的目录
dbfilename dump.rdb
dir ./
一旦redis非法关闭,会丢失最后一次持久化之后的数据。
如果数据不重要,则不必关心;
如果数据不能允许丢失,那么要使用aof方式。
2、AOF方式
aof方式的持久化,是操作一次redis数据库,则将操作的记录存储到aof持久化文件中。
开启aof方式的持久化,将redis.conf中的appendonly改为yes,即开启aof方式的持久化方案。
aof文件存储目录和rdb方式的一样
aof文件存储的名称appendfilename “appendonly.aof”
使用aof和rdb方式时,如果redis重启,则数据从aof文件加载。
redis主从复制
持久化保证了即使redis服务重启也不会丢失数据,因为redis服务重启后会将硬盘上持久化的数据恢复到内存中,但是当redis服务器的硬盘损坏了可能会导致数据丢失,如果通过redis的主从复制机制,就可以避免这种单点故障。
说明:
主redis中的数据有两个副本,即从redis1,从redis2。即使一台redis服务器宕机,其他两台redis服务也可以继续提供服务。
主redis中的数据和从reids上的数据保持实时同步,当主redis写数据时,通过主从复制机制会复制到两个redis服务上。
只有一个主redis,可以有多个从redis。
主从复制不会阻塞master,在同步数据时,master可以继续处理客户端请求,一个redis可以即使主又是从
主从复制设置
主机无需配置
丛机配置:
复制出一个从机
修改从机的redis.conf
语法:slaveof masterip masterport
在redis.conf中修改丛机的port为6380
清除从机中的持久化文件rm -rf appendonly.aof dump.rdb
启动从机 ./redis-server redis.conf
启动6380的客户端 ./redis-cli -p 6380
注意:一个主机发生增删该操作,那么从机会将数据同步到从机中,从机不能执行写操作。
redis集群
1、所有的redis节点彼此互联,内部使用二进制协议优化传输速度和带宽;
2、节点的fail是通过集群中超过半数的节点检测失效时才生效
3、客户端与redis节点直连,不需要中间proxy层,客户端不需要链接集群中所有节点,链接集群中任何一个可用节点即可
4、redis-cluster把所有的物理节点映射到0-16383 slot上,cluster负责维护node<->slot<->value
redis集群中内置了16384个哈希槽,当需要在redis集群中放置一个key-value时,redis先对key使用crc16算法算出一个结果,然后把结果对16384求余数,这样每个key都会对应一个编号在0-16384之间的哈希槽,redis会根据节点数量大致均等的将哈希槽映射到不同的节点。
redis-cluster投票:容错
1、集群中所有master参与投票,如果半数以上的master节点与其中一个master节点通信超过(cluster-node-timeout),认为该master节点挂掉。
2、什么时候整个集群不可用(cluster_state:fail)
如果集群任意master挂掉,且当前master没有slave,则集群进入fail状态,也可以理解成集群的slot映射不完全时进入fail状态。
如果集群中超过半数以上的master挂掉,无论是否有slave,集群进入fail状态。
安装ruby
集群管理工具redis-trib.rb是使用ruby脚本语言编写的。
1、安装ruby
yum install ruby
yum install rubygems
2、将一下文件上传到linux系统
redis-3.2.8.gem
3、安装ruby和redis借口
gem install redis-3.2.8.gem
4、将redis.3.2.8包下src目录中的一下文件拷贝到redis-cluster中
redis-trib.rb
5、查看是否拷贝成功
搭建集群
搭建集群最少需要3台主机,如果每台主机再配置一台从机的话,则最少需要6台机器。
端口设计:7001-7006
1、复制出一个7001机器cp bin ./redis-cluster/7001 -r
2、如果存在持久化文件,则删除rm -rf appendonly.aof dump.rdb
3、设置集群参数cluster-enabled yes
4、修改端口port 7001
5、复制出7002-7006机器cp 7001/ 7002-r
6、修改7002-7006机器端口
7、启动六台机器 cd 7001
./redis-server redis.conf
8、修改start-all.sh文件的权限chmod u+x start-all.sh
./start-all.sh
9、创建集群
./redis-trib.rb create –replicas 1 192.168.1.128:7001 192.168.1.128:7002 192.168.1.128:7003
连接集群
./redis-cli -h 192.168.1.128 -p 7001 -c
-c 指定是集群连接
查看集群信息
cluster info
192.168.242.137:7002> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:2
cluster_stats_messages_sent:2372
cluster_stats_messages_received:2372
查看集群几点
cluster nodes
jedis连接集群
1、设置防火墙
vim /etc/sysconfig/iptables
添加-A INPUT -m state –state NEW -m tcp -p tcp –dport 7001 -j ACCEPT
service iptables restart
2、代码
Set nodes = new HashSet<>();
nodes.add(new HostAndPort(“192.168.1.128”,7001));
JedisCluster cluster = new JedisCluster(nodes);
cluster.set(“key”,”ddd”);
cluster.get(“key”);
cluster.close();
3、使用spring
配置aplicationContext.xml