1 引言
随着业务的增长和产品的完善,急速增长的数据给Oracle数据库带来了很大的压力,而随着我们对产品服务质量要求的提高,传统的数据查询方式已无法满足我们需求。为此我们需要寻找另外一种模式来提高数据查询效率。NoSQL内存数据库是最近兴起的新型数据库,它的特点就是把数据放在内存中操作,数据处理速度相对于磁盘提高了好几个量级,因此,通过把经常访问的数据转移到内存数据库中,不但可以缓解Oracle的访问压力,而且可以极大提高数据的访问速度,提高用户体验。
2 概述
Redis是一个开源的,先进的key-value持久化产品。它通常被称为数据结构服务器,它的值可以是字符串(String)、哈希(Map)、列表(List)、集合(Sets)和有序集合(Sorted sets)等类型。可以在这些类型上面做一些原子操作,如:字符串追加、增加Hash里面的值、添加元素到列表、计算集合的交集,并集和差集;或者区有序集合中排名最高的成员。为了取得好的性能,Redis是一个内存型数据库。不限于此,Redis也可以把数据持久化到磁盘中,或者把数据操作指令追加了一个日志文件,把它用于持久化。也可以用Redis容易的搭建master-slave架构用于数据复制。其它让它像缓存的特性包括,简单的check-and-set机制,pub/sub和配置设置。Redis可以用大部分程序语言来操作:C、C++、C#、Java、Node.js、php、ruby等等。Redis是用ANSIC写的,可以运行在多数POSIX系统,如:Linux,*BSD,OS X和Soloris等。官方版本不支持Windows下构建,可以选择一些修改过的版本,照样可以使用Redis。
3 Redis介绍
3.1 五种数据类型
3.1.1 String类型
String是最基本的类型,而且string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如 jpg 图片或者序列化的对象。从内部实现来看其实 string 可以看作 byte 数组,最大上限是 1G 字节。
string类型数据操作指令简介
1. set keyvalue设置key对应string类型的值,返回1表示成功,0失败。
2. setnx keyvalue如果key不存在,设置key对应string类型的值。如果key已经存在,返回0。
3. get key获取key对应的string值,如果key不存在返回nil
4. getsetkey value先获取key的值,再设置key的值。如果key不存在返回nil。
5. mget key1key2 ...... keyN一次获取多个key的值,如果对应key不存在,则对应返回nil
6. mset key1value1 ...... keyN valueN一次设置多个key的值,成功返回1表示所有的值都设置了,失败返回0表示没有任何值被设置。
7. msetnxkey1 value1 ...... keyN valueN一次设置多个key的值,但是不会覆盖已经存在的key incr key 对key的值做++操作,并返回新的值。注意incr一个不是int的value会返回错误,incr一个不存在的key,则设置key值为1。
8. decr key: 对key的值做--操作,decr一个不存在key,则设置key值为-1。
9. incrbykey integer对key加上指定值,key不存在时候会设置key,并认为原来的value 是0。
10. decrbykey integer对key减去指定值。decrby完全是为了可读性,我们完全可以通过incrby一个负值来实现同样效果,反之一样。
3.1.2 hash类型
hash是一个string类型的field和value的映射表。添加,删除操作都是O(1)(平均)。 hash特别适合用于存储对象。相对于将对象的每个字段存成单个string类型。将一个对象存储在hash类型中会占用更少的内存,并且可以更方便的存取整个对象。省内存的原因是新建一个hash对象时开始是用 zipmap(又称为 small hash)来存储的。这个 zipmap 其实并不是hashtable,但是zipmap相比正常的hash实现可以节省不少hash本身需要的一些元数据存储开销。尽管zipmap的添加,删除,查找都是 O(n),但是由于一般对象的field 数量都不太多。所以使用zipmap也是很快的,也就是说添加删除平均还是O(1)。如果field 或者 value的大小超出一定限制后,redis会在内部自动将zipmap替换成正常的hash实现.这个限制可以在配置文件中指定。
hash类型数据操作指令简介
1. hset keyfield value 设置hash field为指定值,如果key不存在,则创建。
2. hget keyfield 获取指定的hash field。
3. hmget keyfiled1....fieldN 获取全部指定的hash filed。
4. hmset keyfiled1 value1 ...... filedN valueN 同时设置hash的多个field。
5. hincrbykey field integer 将指定的hashfiled 加上指定值。成功返回hashfiled变更后的值。
6. hexistskey field 检测指定field是否存在。 hdelkey field 删除指定的hash field。
7. hlen key 返回指定hash的field数量。 hkeys key 返回hash的所有field。
8. hvals key 返回hash的所有value。
9. hgetall 返回hash的所有filed和value。
3.1.3 List类型
list是一个链表结构,可以理解为一个每个子元素都是 string 类型的双向链表。主要功
能是push、pop、获取一个范围的所有值等。操作中key理解为链表的名字。
List类型数据操作指令简介
1. lpush keystring 在key对应list的头部添加字符串元素,返回1表示成功,0表示key存在且不是list类型。
2. rpush keystring 在key对应list的尾部添加字符串元素。
3. llen key 返回key对应list的长度,如果key不存在返回0,如果key对应类型不是list 返回错误。
4. lrangekey start end 返回指定区间内的元素,下标从0开始,负值表示从后面计算,-1表示倒数第一个元素 ,key不存在返回空列表。
5. ltrim keystart end 截取list指定区间内元素,成功返回1,key不存在返回错误。
6. lset keyindex value 设置list中指定下标的元素值,成功返回1,key或者下标不存在返回错误。
7. lrem keycount value 从 List 的头部(count正数)或尾部(count负数)删除一定数量(count)匹配value的元素,返回删除的元素数量。count为0时候删除全部。
8. lpop key 从list的头部删除并返回删除元素。如果key对应list不存在或者是空返回nil,如果key对应值不是list返回错误。
9. rpop key从list的尾部删除并返回删除元素。
10. blpopkey1 ...... keyN timeout 从左到右扫描,返回对第一个非空list进行lpop操作并返回,比如blpop list1 list2 list3 0 ,如果list不存在list2,list3都是非空则对list2做 lpop并返回从list2中删除的元素。如果所有的list都是空或不存在,则会阻塞timeout秒,timeout为0表示一直阻塞。当阻塞时,如果有client对key1...keyN中的任意key 进行push操作,则第一在这个key上被阻塞的client会立即返回。如果超时发生,则返回 nil。有点像unix的select或者poll。
11. brpop 同blpop,一个是从头部删除一个是从尾部删除。
3.1.4 Set类型
set是无序集合,最大可以包含(2的 32 次方-1)个元素。set 的是通过 hash table 实现的,所以添加,删除,查找的复杂度都是 O(1)。hash table 会随着添加或者删除自动的调整大小。需要注意的是调整 hash table 大小时候需要同步(获取写锁)会阻塞其他读写操作。可能不久后就会改用跳表(skip list)来实现。跳表已经在 sorted sets 中使用了。关于 set 集合类型除了基本的添加删除操作,其它有用的操作还包含集合的取并集(union),交集(intersection),差集(difference)。通过这些操作可以很容易的实现 SNS 中的好友推荐和 blog 的 tag 功能。
set类型数据操作指令简介
1. sadd keymember 添加一个string元素到key对应set集合中,成功返回1,如果元素以及在集合中则返回0,key对应的set不存在则返回错误。
2. srem keymember 从key对应set中移除指定元素,成功返回1,如果member在集合中不存在或者key不存在返回0,如果key对应的不是set类型的值返回错误。
3. spop key 删除并返回key对应set中随机的一个元素,如果set是空或者key不存在返回 nil。
4. srandmemberkey 同spop,随机取set中的一个元素,但是不删除元素。
5. smovesrckey dstkey member 从srckey对应set中移除member并添加到dstkey对应set中,整个操作是原子的。成功返回1,如果member在srckey中不存在返回0,如果key不是set 类型返回错误。
6. scard key 返回set的元素个数,如果set是空或者key不存在返回0。
7. sismemberkey member 判断member是否在set中,存在返回1,0表示不存在或者key不存在。
8. sinterkey1 key2 …… keyN 返回所有给定key的交集。
9. sinterstoredstkey key1 ....... keyN 返回所有给定key的交集,并保存交集存到dstkey下。
10. sunionkey1 key2 ...... keyN 返回所有给定key的并集。
11. sunionstoredstkey key1 ...... keyN 返回所有给定key的并集,并保存并集到dstkey下。
12. sdiffkey1 key2 ...... keyN 返回所有给定key的差集。
13. sdiffstoredstkey key1 ...... keyN 返回所有给定key的差集,并保存差集到dstkey下。
14. smemberskey 返回key对应set的所有元素,结果是无序的。
3.1.5 Sorted Set
sorted set是有序集合,它在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,会自动重新按新的值调整顺序。可以理解了有两列的 mysql表,一列存value,一列存顺序。操作中key理解为sorted set的名字。
Sorted Set类型数据操作指令简介
1. add keyscore member 添加元素到集合,元素在集合中存在则更新对应score。
2. zrem keymember 删除指定元素,1 表示成功,如果元素不存在返回 0。
3. zincrbykey incr member 增加对应 member 的 score 值,然后移动元素并保持skip list 保持有序。返回更新后的 score 值。
4. zrank keymember 返回指定元素在集合中的排名(下标),集合中元素是按 score 从小到大排序的。
5. zrevrankkey member 同上,但是集合中元素是按score 从大到小排序。
6. zrangekey start end 类似 lrange 操作从集合中去指定区间的元素。返回的是有序结果
7. zrevrangekey start end 同上,返回结果是按 score 逆序的。
8. zrangebyscorekey min max 返回集合中 score 在给定区间的元素。
9. zcountkey min max 返回集合中 score 在给定区间的数量。
10. zcard key 返回集合中元素个数。
11. zscorekey element 返回给定元素对应的 score。
12. zremrangebyrankkey min max 删除集合中排名在给定区间的元素。
13. zremrangebyscorekey min max 删除集合中 score 在给定区间的元素。
3.2 Redis主从复制
3.2.1 主从复制介绍
Redis支持将数据同步到多台从库上,这种特性对提高读取性能非常有益。master可以有多个slave。除了多个slave连到相同的master外,slave也可以连接其它slave形成图状结构。主从复制不会阻塞master。也就是说当一个或多个slave与master进行初次同步数据时,master可以继续处理客户端发来的请求。相反slave在初次同步数据时则会阻塞不能处理客户端的请求。
主从复制可以用来提高系统的可伸缩性,我们可以用多个slave 专门用于客户端的读请求,比如sort操作可以使用slave来处理。也可以用来做简单的数据冗余。可以在 master 禁用数据持久化,只需要注释掉 master 配置文件中的所有 save 配置,然后只在 slave 上配置数据持久化。
3.2.2 主从复制过程
当设置好 slave 服务器后,slave 会建立和 master 的连接,然后发送 sync命令。无论是第一次同步建立的连接还是连接断开后的重新连接,master 都会启动一个后台进程,将数据库快照保存到文件中,同时 master 主进程会开始收集新的写命令并缓存起来。后台进程完成写文件后,master 就发送文件给 slave,slave 将文件保存到磁盘上,然后加载到内存恢复数据库快照到 slave 上。接着 master 就会把缓存的命令转发给 slave。而且后续 master 收到的写命令都会通过开始建立的连接发送给slave。从master到slave的同步数据的命令和从客户端发送的命令使用相同的协议格式。当 master 和 slave 的连接断开时 slave 可以自动重新建立连接。如果 master 同时收到多个 slave 发来的同步连接命令,只会启动一个进程来写数据库镜像,然后发送给所有 slave。
配置 slave服务器很简单,只需要在配置文件中加入如下配置
slaveof 192.168.1.1 6379 #指定 master的 ip 和端口。
3.3 Redis持久化
通常Redis将数据存储在内存中或虚拟内存中,但它提供了数据持久化功能可以把内存中的数据持久化到磁盘。持久化有什么好处呢?比如可以保证断电后数据不会丢失,升级服务器也会变得更加方便。Redis提供了两种数据持久化的方式。
3.3.1 RDB Snapshotting方式持久化(默认方式)
这种方式就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为 dump.rdb。客户端也可以使用save或者bgsave命令通知redis做一次快照持久化。save操作是在主线程中保存快照的,由于redis是用一个主线程来处理所有客户端的请求,这种方式会阻塞所有客户端请求。所以不推荐使用。另一点需要注意的是,每次快照持久化都是将内存数据完整写入到磁盘一次,并不是增量的只同步增量数据。如果数据量大的话,写操作会比较多,必然会引起大量的磁盘IO操作,可能会严重影响性能。
这种方式的缺点也是显而易见的,由于快照方式是在一定间隔时间做一次的,所以如果 redis 意外当机的话,就会丢失最后一次快照后的所有数据修改。
3.3.2 AOF方式持久化
这种方式 redis 会将每一个收到的写命令都通过 write 函数追加到文件中(默认 appendonly.aof)。当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。当然由于操作系统会在内核中缓存write做的修改,所以可能不是立即写到磁盘上。这样的持久化还是有可能会丢失部分修改。不过我们可以通过配置文件告诉 redis我们想要通过fsync函数强制操作系统写入到磁盘的时机。有三种方式如下(默认是:每秒fsync一次)
appendonly yes //启用日志追加持久化方式
1. appendfsync always //每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全持久化,不推荐使用。
2. appendfsync everysec //每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折中,推荐使用。
3. appendfsync no //完全依赖操作系统,性能最好,持久化没保证。
日志追加方式同时带来了另一个问题。持久化文件会变的越来越大。例如我们调用 incr test 命令 100 次,文件中必须保存全部 100 条命令,其实有 99 条都是多余的。因为要恢复数据库状态其实文件中保存一条 set test 100 就够了。为了压缩这种持久化方式的日志文件。 redis 提供了 bgrewriteaof 命令。收到此命令 redis 将使用与快照类似的方式将内存中的数据以命令的方式保存到临时文件中,最后替换原来的持久化日志文件。
3.4 Redis虚拟内存
3.4.1 虚拟内存介绍
首先说明下redis的虚拟内存与操作系统虚拟内存不是一码事,但是思路和目的都是相同的。就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出宝贵的内存空间。对于 redis这样的内存数据库,内存总是不够用的。除了可以将数据分割到多个redis 服务器以外。另外的能够提高数据库容量的办法就是使用虚拟内存技术把那些不经常访问的数据交换到磁盘上。如果我们存储的数据总是有少部分数据被经常访问,大部分数据很少被访问,对于网站来说确实总是只有少量用户经常活跃。当少量数据被经常访问时,使用虚拟内存不但能提高单台redis数据库服务器的容量,而且也不会对性能造成太多影响。
redis没有使用操作系统提供的虚拟内存机制而是自己在用户态实现了自己的虚拟内
存机制。主要的理由有以下两点,操作系统的虚拟内存是以4k/页为最小单位进行交换的。而redis的大多数对象都远小于4k,所以一个操作系统页上可能有多个redis对象。另外redis的集合对象类型如 list,set可能存在于多个操作系统页上。最终可能造成只有10%的key被经常访问,但是所有操作系统页都会被操作系统认为是活跃的,这样只有内存真正耗尽时操作系统才会进行页的交换。相比操作系统的交换方式。redis可以将被交换到磁盘的对象进行压缩,保存到磁盘的对象可以去除指针和对象元数据信息。一般压缩后的对象会比内存中的对象小 10倍。这样redis的虚拟内存会比操作系统的虚拟内存少做很多IO操作。
3.4.1 虚拟内存相关设置
vm-enabled yes 开启虚拟内存功能
vm-swap-file /tmp/redis.swap 交换出来value保存的文件路径/tmp/redis.swapvm-max-memory268435456 redis使用的最大内存上限(256MB),超过上限后 redis开始交换value到磁盘swap文件中。建议设置为系统空闲内存的60 %-80%
vm-page-size 32 每个redis页的大小32个字节
vm-pages 134217728 最多在文件中使用多少个页,交换文件的大小 =(vm-page-size* vm-pages)4 GB
vm-max-threads 8 用于执行value对象换入换出的工作线程数量。0 表示不使用工作线程
3.5 Redis集群
Redis最新稳定版还不支持集群,会在以后的V3.0提供集群功能,现在进度是V3.0已经发布Beta-7版,计划今年年底正式推出稳定版。Redis提供了Partitioning(类似于Memcached在客户端进行Hash映射)机制以支持多实例,下面介绍下Partitioning目标:
1. 突破了单一计算机内存限制,可以利用到多个计算机的内存和
2. 通过配置多个计算机来拓展计算能力,解决网络、网卡瓶颈
Partitioning支持:
1. 通过Client端实现Partitioning,即Client端在读写数据的时候根据自己的选择算法自动选择合适的Redis实例
2. 代理Partitioning,即客户端把读写请求发到代理,由来自选择合适的实例,twitter为Redis和Memcached专门写了一个代理 Twemproxy
3. 查询时自动routing:客户端随机发送命令到任何一个实例,这个实例会把请求转发给合适的实例,这个功能现在还不支持,3.0版本实现的集群功能支持
3.6 其它参考资料
所有特性请参考:http://redis.io/documentation
所有命令请参考:http://redis.io/commands#sorted_set
4 环境安装
4.1 下载、解压、安装
$ wget http://download.redis.io/releases/redis-2.8.13.tar.gz
$ tar xzf redis-2.8.13.tar.gz
$ cd redis-2.8.13
$ make
4.2 启动Redis实例
$ src/redis-server
4.3 通过内置客户端进行测试
$ src/redis-cli
redis> set foo bar
OK
redis> get foo
"bar"
具体请参考:http://redis.io/download
5 配置文件
1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
daemonize yes
2. 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
pidfile/usr/local/redis/var/redis.pid
3. 指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字。
port 6379
4. 绑定的主机地址
bind 127.0.0.1
5. 当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
timeout 0
6. 对客户端发送ACK信息,linux中单位为秒
tcp-keepalive 0
7. 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为notice
loglevel notice
8. 日志记录位置,默认为标准输出
logfile/usr/local/redis/var/redis.log
9. 设置数据库的数量,默认数据库为0,可以使用SELECT 命令在连接上指定数据库id
databases 16
10. 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
Save分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。
Redis默认配置文件中提供了三个条件:
save 900 1
save 300 10
save 60 10000
11. 持久化失败以后,redis是否停止
stop-writes-on-bgsave-erroryes
12. 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大
rdbcompression yes
rdbchecksum yes
13. 指定本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb
14. 指定本地数据库存放目录
dir /usr/local/redis/var
15. 设置当本机为slave服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
slaveof
16. 当master服务设置了密码保护时,slave服务连接master的密码
masterauth
17. 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH 命令提供密码,默认关闭
requirepass foobared
18. 设置同一时间最大客户端连接数,在 Redis2.4中,最大连接数是被直接硬编码在代码里面的,而在2.6版本中这个值变成可配置的。maxclients 的默认值是 10000,你也可以在 redis.conf 中对这个值进行修改。当然,这个值只是 Redis 一厢情愿的值,Redis 还会照顾到系统本身对进程使用的文件描述符数量的限制。在启动时 Redis 会检查系统的 soft limit,以查看打开文件描述符的个数上限。如果系统设置的数字,小于咱们希望的最大连接数加32,那么这个 maxclients 的设置将不起作用,Redis 会按系统要求的来设置这个值。(加32是因为 Redis 内部会使用最多32个文件描述符,所以连接能使用的相当于所有能用的描述符号减32)。当上面说的这种情况发生时(maxclients 设置后不起作用的情况),Redis 的启动过程中将会有相应的日志记录。比如下面命令希望设置最大客户端数量为10000,所以 Redis 需要 10000+32 个文件描述符,而系统的最大文件描述符号设置为10144,所以 Redis 只能将maxclients 设置为 10144 – 32 = 10112。
maxclients 10000
19. 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区
maxmemory
slave-serve-stale-data yes
slave-read-only yes
repl-disable-tcp-nodelay no
slave-priority 100
20. 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为Redis本身同步数据文件是按上面slave条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no
appendonly no
21. 指定更新日志文件名,默认为appendonly.aof
appendfilename appendonly.aof
22. 指定更新日志条件,共有3个可选值:
no:表示等操作系统进行数据缓存同步到磁盘(快)
always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
everysec:表示每秒同步一次(折衷,默认值)
appendfsync everysec
23. 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)
vm-enabled no
24. 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
vm-swap-file /tmp/redis.swap
25. 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。
vm-max-memory 0
26. Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不确定,就使用默认值
vm-page-size32
27. 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。
vm-pages 134217728
28. 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4
vm-max-threads 4
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
29. 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
30. 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)
activerehashing yes
client-output-buffer-limit normal 0 00
client-output-buffer-limit slave256mb 64mb 60
client-output-buffer-limit pubsub32mb 8mb 60
hz 10
31. 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
具体请参考:https://raw.githubusercontent.com/antirez/redis/2.6/redis.conf
6 示例代码
我们选择的Redis客户端实现是Jedis,这是比较成熟的Redis客户端,也是官网力荐的。因为Redis本身不支持集群功能,我们的思路是在集群中启动多个独立的实例,在客户端通过“一致性hash”技术来实现对集群中各个Redis实例进行读写,Jedis通过ShardJedis对象对”一致性hash”提供支持。
6.1 定义一个ShardJedisPool
static ShardedJedisPoolpool;
static {
//配置
JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(1024);
config.setMaxIdle(5);
config.setMaxWaitMillis(1000*2);
//创建ShardJedis对象
String masterA = "10.10.0.3";
String masterB = "10.10.0.131";
int port = 6379;
List
JedisShardInfo infoA = new JedisShardInfo(masterA, port);
JedisShardInfo infoB = new JedisShardInfo(masterB, port);
jdsInfoList.add(infoA);
jdsInfoList.add(infoB);
//创建ShardJedisPool
pool = new ShardedJedisPool(config, jdsInfoList, Hashing.MURMUR_HASH, Sharded.DEFAULT_KEY_TAG_PATTERN);
}
6.2 使用ShardJedis对象
ShardedJedis jedis= pool.getResource();//从池中获取
jedis.set("foo","bar");//写入Redis
String value = jedis.get("foo");//读出
pool.returnResource(jedis);//释放掉资源
————————————————
版权声明:本文为CSDN博主「Heaven-Wang」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/suifeng3051/article/details/38657613