字符串类型是 Redis 中最基本的数据类型,掌握好它以及相关命令的使用是一切的一切的基础。
Redis 的 String 类型可以是字符串(简单的字符串、复杂的字符串(例如 JSON、XML))、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB;
最基本的 set 和 get 命令,但是要注意这样的代码块会在高并发的时候出现 race condition,后续可以使用原子操作来解决这个问题:
@Test public void setAndGetTest() { String status = j.set("views", "123"); assertEquals("OK", status); String value = j.get("views"); assertEquals("123", value); int newViews = Integer.parseInt(value) + 1; status = j.set("views", String.valueOf(newViews)); assertEquals("OK", status); assertEquals("124", j.get("views")); }
当存储的字符串是整数形式时,redis 提供了一个原子的自增操作:
@Test public void incrAndIncrBy() { String status = j.set("view", "123"); assertEquals("OK", status); Long view = j.incr("view"); assert (124L == view); view = j.incrBy("view", 2L); assert (126L == view); }
Redis 键命名没有统一规范,但最好使用:
对象类型:对象ID:对象属性 apple:1:color room:2:chairs
对于多个单词,不推荐使用驼峰命名或者是下划线连接,而是使用.
连接,比如:
post:123:page.view
用来表示 ID 为 123 的文章的 page_view 或者是 pageView。
看到递增就不免让人想到递增主键,在 MySQL 中只需要将字段设置成 AUTO_INCREMENT 就能在插入的时候实现自增。在使用 redis 时,我们只需要存储一个名为 object_names:count 的键来存储当前类型对象的数量,每增加一个对象的时候都使用 incr 命令增加它的值。
当 incr 命令所执行的键没有实际对应时(不存在这个键),redis 会自动创建这个键,设初值为 0 并且马上自增 1,返回的结果也是 1。
开篇就介绍过了,String 类型能够存储几乎所有的内容,前提时要经过序列化。这里我演示一个序列化对象的例子:
public class Apple implements Serializable { long serialVersionUID = 1L; String color = "red"; float weight = 3.14f; @Override public boolean equals(Object obj) { Apple target = (Apple) obj; return this.color.equals(target.color) && this.weight == target.weight && this.serialVersionUID == target.serialVersionUID; } } @Test public void setAndGetObject() { // 序列化对象得到字符串,使用 base64 编码 // may occur that invalid header for outPutStream/InputStream Apple oldApple = new Apple(); ByteArrayOutputStream bos = null; ObjectOutputStream oos = null; String oldAppleStr = null; try { bos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(bos); oos.writeObject(oldApple); oldAppleStr = Base64.getEncoder().encodeToString(bos.toByteArray()); } catch (IOException e) { e.printStackTrace(); } String status = j.set("apple", oldAppleStr); assertEquals("OK", status); String newAppleStr = j.get("apple"); assertEquals(oldAppleStr, newAppleStr); ByteArrayInputStream bis = null; ObjectInputStream ois = null; try { bis = new ByteArrayInputStream(Base64.getDecoder().decode(newAppleStr)); ois = new ObjectInputStream(bis); Apple newApple = (Apple) ois.readObject(); assertEquals(oldApple, newApple); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } try { oos.close(); bos.close(); ois.close(); bis.close(); } catch (IOException e) { e.printStackTrace(); } }
如果测试通过,可以看到将对象序列化并且编码成字符串后可以存储到 redis 中,并且能够通过相反的过程重新反序列化回来。这个过程就有两点值得注意,一个是序列化,一个是编码。