首页 > 代码库 > Redis学习
Redis学习
打算认真地系统地学习一下redis,本文为鉴,笑。
先说认识
这货是一个数据库,特点是:NoSQL + 内存型!
只是,其实多数人使用的都是“内存型”这个特性 -- 因为速度快,NoSQL 反而没那么显眼。
当然,如果只是“内存型”,其实还有很多选择,例如ehcache、memcache等,甚至web应用的session也算一个,或者,还可以自己构建一个Map用于存取数据。
之所以使用Redis,是因为它还提供了很多其他特性,例如多种数据格式、事务、集群、主从、持久化、订阅/发布等等。 -- 鉴于没有深入研究过ehcache、memcache,就不列出对比了。
开始
官方网站 redis.io 下载后,需要安装方可使用,详情请搜索之。--建议使用Linux运行,因为多数开源工具都优先支持Linux,总要接触的,不如直接开始。当然也有windows版本的,版本较旧就是。
Linux下安装后的内容:
[root@localhost redis-3.2.6]# cd /usr/local/bin/ [root@localhost bin]# ll 总用量 26344 -rw-r--r--. 1 root root 377 12月 24 14:55 dump.rdb -rwxr-xr-x. 1 root root 5580287 12月 24 01:45 redis-benchmark -rwxr-xr-x. 1 root root 22177 12月 24 01:45 redis-check-aof -rwxr-xr-x. 1 root root 7826296 12月 24 01:45 redis-check-rdb -rwxr-xr-x. 1 root root 5708996 12月 24 01:45 redis-cli lrwxrwxrwx. 1 root root 12 12月 24 01:45 redis-sentinel -> redis-server -rwxr-xr-x. 1 root root 7826296 12月 24 01:45 redis-server [root@localhost bin]#
需要说明的是,redis-server可以直接启动,但是仅限于本机使用。正确的启动方式应该附加配置文件redis.conf -- 可以在redis解压后的目录中找到,如下:
[root@localhost bin]# ll ~/software/redis-3.2.6 总用量 200 -rw-rw-r--. 1 root root 80406 12月 6 16:38 00-RELEASENOTES -rw-rw-r--. 1 root root 53 12月 6 16:38 BUGS -rw-rw-r--. 1 root root 1805 12月 6 16:38 CONTRIBUTING -rw-rw-r--. 1 root root 1487 12月 6 16:38 COPYING drwxrwxr-x. 7 root root 4096 12月 24 01:42 deps -rw-rw-r--. 1 root root 11 12月 6 16:38 INSTALL -rw-rw-r--. 1 root root 151 12月 6 16:38 Makefile -rw-rw-r--. 1 root root 4223 12月 6 16:38 MANIFESTO -rw-rw-r--. 1 root root 6834 12月 6 16:38 README.md -rw-rw-r--. 1 root root 46695 12月 6 16:38 redis.conf -rwxrwxr-x. 1 root root 271 12月 6 16:38 runtest -rwxrwxr-x. 1 root root 280 12月 6 16:38 runtest-cluster -rwxrwxr-x. 1 root root 281 12月 6 16:38 runtest-sentinel -rw-rw-r--. 1 root root 7606 12月 6 16:38 sentinel.conf drwxrwxr-x. 2 root root 4096 12月 24 01:42 src drwxrwxr-x. 10 root root 4096 12月 6 16:38 tests drwxrwxr-x. 7 root root 4096 12月 6 16:38 utils [root@localhost bin]#
但是,默认的配置仅限于回环访问,就是仅限于127.0.0.1访问,其他地址不行,所以需要修改一下(建议备份原有的)。
[root@localhost redis-3.2.6]# cat redis.conf # 许可IP bind 127.0.0.1 # 监听端口 port 6379 tcp-backlog 511 # 客户端空闲N秒后关闭连接(0是禁用) timeout 0 tcp-keepalive 300 # 是否改为守护进程 daemonize no supervised no pidfile /var/run/redis_6379.pid loglevel notice logfile "" databases 16 ################################ SNAPSHOTTING ################################ # 持久化(保存到硬盘上) # 900秒(15分钟)后,如果至少一个key发生改变 save 900 1 # 300秒(5分钟)后,如果至少十个key发生改变 save 300 10 # 50秒后,如果至少10000个key发生改变 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes # 持久化的目标文件名 dbfilename dump.rdb # 持久化的目标目录 dir ./ # 主从 slave-serve-stale-data yes slave-read-only yes repl-diskless-sync no repl-diskless-sync-delay 5 repl-disable-tcp-nodelay no slave-priority 100 ################################## SECURITY ################################### # 安全 # 要求客户端在处理命令之前先AUTH <PASSWD> # 鉴于Redis非常快速,外部用户每秒可以尝试150K次密码,所以建议启用一个非常强壮的密码,否则很容易被破解。--本人建议配合bind使用或者仅使用bind。 # 默认注释,即不需要密码。这里我给放开了,所以需要密码foobared requirepass foobared # maxclients 10000 # maxmemory <bytes> # maxmemory-policy noeviction # maxmemory-samples 5 appendonly no # The name of the append only file (default: "appendonly.aof") appendfilename "appendonly.aof" # appendfsync always appendfsync everysec # appendfsync no no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes # Set it to 0 or a negative value for unlimited execution without warnings. lua-time-limit 5000 ################################ REDIS CLUSTER ############################### # cluster-enabled yes # cluster-config-file nodes-6379.conf # cluster-node-timeout 15000 # cluster-slave-validity-factor 10 # cluster-migration-barrier 1 # cluster-require-full-coverage yes ################################## SLOW LOG ################################### slowlog-log-slower-than 10000 slowlog-max-len 128 ################################ LATENCY MONITOR ############################## latency-monitor-threshold 0 ############################# EVENT NOTIFICATION ############################## notify-keyspace-events "" ############################### ADVANCED CONFIG ############################### hash-max-ziplist-entries 512 hash-max-ziplist-value 64 list-max-ziplist-size -2 list-compress-depth 0 set-max-intset-entries 512 zset-max-ziplist-entries 128 zset-max-ziplist-value 64 hll-sparse-max-bytes 3000 activerehashing yes client-output-buffer-limit normal 0 0 0 client-output-buffer-limit slave 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 aof-rewrite-incremental-fsync yes
以上是精简版,去掉了大段的英文注释。因为我使用了虚拟机+桥接方式,所以不能通过127.0.0.1:6379访问,所以放开了requirepass,这样就可以通过auth来验证了。
数据格式
Redis支持的数据格式有五种:string、list、hash、set、sortedset!
需要注意的是,这些数据格式的键和值 -- 本质上都是字节数组(byte[])!
所以,Redis的任何一种格式都可以存储Java的所有的类型 -- 只要你将其转成字节数组 (byte[])!
Java中对象转成字节数组(byte[])的方式,最基本的是通过ByteArrayOutputStream和ObjectOutputStream将实现了Serializable接口的类对象转成字节数组。如下:
Person p = new Person(); p.setName("小雯"); p.setId("456321789"); p.setAge(13); p.setWords("豆蔻年华二月初"); ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ObjectOutputStream objectOutputStream = new ObjectOutputStream(out); objectOutputStream.writeObject(p); byte[] byteArray = out.toByteArray(); } catch (IOException e) { e.printStackTrace(); }
或者,使用Jackson等序列化工具进行序列化 -- 更简洁明了,因为都是字符串。
需要提一句,不建议使用ByteArrayOutputStream和ObjectOutputStream这种原始方式进行序列化,因为会序列化很多不必要的信息。以上面的代码为例,实际上我们只需要name、id、age、words这四个properties的信息就足够了,但原始的序列化还会附加很多信息(如继承的类、接口等等),这样会浪费时间和空间。
所以,推荐使用Jackson、fastjson、gson等序列化工具。
客户端
Java的客户端推荐使用Jedis(其实我就知道这个),自带连接池、集群等配置,其方法与Redis完全一致。与Spring结合时可以使用RedisTemplate,类似RestTemplate。
新建maven项目,添加依赖即可:
<!-- jackson新版本 --> <!-- jackson-databind依赖core和annation,所以不必重复导入 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.5</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-joda</artifactId> <version>2.8.5</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
现在就可以使用Jedis了,先放一个小例子,后面详细研究下每种数据格式对应的方法。
public class BasicDemo { private static final String PREFIX = "ABCDEF."; private static Jedis redis; // redis默认开启了保护,只允许本地回环连接请求(就是127.0.0.1),需要在redis.conf中修改。或设置密码、或bind许可ip。 @Before public void setUp() { String host = "192.168.0.210"; int port = 6379; redis = new Jedis(host, port); redis.auth("foobaredauth"); } // STRING 操作 --TODO:实际上存储的是byte[],所以可以存储任意内容 @Test public void string() { // SET key value: 将字符串值value关联到key。 redis.set("name", "wangjun1"); redis.set("id", "123456"); redis.set("address", "guangzhou"); // SETEX key seconds value :将值value关联到key,并将key的生存时间设为seconds(以秒为单位)。 redis.setex("foo", 5, "haha"); // MSET key value [key value ...] :同时设置一个或多个key-value对。 redis.mset("haha", "111", "xixi", "222"); // redis.flushAll();清空所有的key System.out.println(redis.dbSize());// dbSize是多少个key的个数 // APPEND key value :如果key已经存在并且是一个字符串,APPEND命令将value追加到key原来的值之后。 redis.append("foo", "*00");// 如果key已经存在并且是一个字符串,APPEND命令将value追加到key原来的值之后。 // GET key 返回key所关联的字符串值 String foo = redis.get("foo"); System.out.println(foo); // MGET key [key ...] 返回所有(一个或多个)给定key的值 List<String> list = redis.mget("haha", "xixi"); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } } }
未完待续
参考:
Redis 命令参考
为什么要选择使用 Redis ?
Redis学习