Redis is a key-value-based nosql database that supports a variety of common data structures and very convenient operations, it is a server that stores various data structures. It's okay today. I used the Java Collection class to implement some basic functions of redis, so I can just look at java.
1. Get started with redis
Redis's key value is a string, but the value supports many types, such as string, list linked list, set unordered set, sortedset ordered set, and even hash table.
Different data structures are differentiated by different access methods. For example, set/get stores the value as string, lpush/lpop/lrange stores the value in a linked list, And sadd/zadd distinguishes unordered and Ordered Sets.
Next, let's take a look at how to implement these simple and convenient operations using basic collection classes in Java.
2. redis for Java
The code structure is as follows:
package com.cdai.studio.redis;import java.util.HashSet;import java.util.LinkedList;import java.util.TreeSet;@SuppressWarnings("unchecked")public class RedisDB {private Persistence persistence = new Persistence();private Serializer serializer = new Serializer();private static final Object[] NULL = new Object[0];// =================================================//String value// =================================================public void Set(String key, Object value) {persistence.put(key, serializer.marshal(value));}public Object Get(String key) {return serializer.unmarshal(persistence.get(key));}public Object[] MGet(String... keys) {Object[] values = new Object[keys.length];for (int i = 0; i < keys.length; i++)values[i] = Get(keys[i]);return values;}public int Incr(String key) {Object value = Get(key);Integer valueRef = (value == null) ? 1 : (Integer) value;Set(key, valueRef + 1);return valueRef;}// =================================================//List value// =================================================public void LPush(String key, Object... values) {Object list = persistence.get(key);if (list == null)list = new LinkedList<Object>();elselist = serializer.unmarshal(list);LinkedList<Object> listRef = (LinkedList<Object>) list;for (Object value : values)listRef.addFirst(value);persistence.put(key, serializer.marshal(list));}public void RPush(String key, Object... values) {Object list = persistence.get(key);if (list == null)list = new LinkedList<Object>();elselist = serializer.unmarshal(list);LinkedList<Object> listRef = (LinkedList<Object>) list;for (Object value : values)listRef.addLast(value);persistence.put(key, serializer.marshal(list));}public Object[] LRange(String key, int start, int end) {Object list = persistence.get(key);if (list == null)return NULL;LinkedList<Object> listRef = (LinkedList<Object>) serializer.unmarshal(list);if (end > listRef.size())end = listRef.size();return listRef.subList(start, end).toArray();}// =================================================//Unsorted Set value// =================================================public void SAdd(String key, Object... values) {Object set = persistence.get(key);if (set == null)set = new HashSet<Object>();elseset = serializer.unmarshal(set);HashSet<Object> setRef = (HashSet<Object>) set;for (Object value : values)setRef.add(value);persistence.put(key, serializer.marshal(set));}public Object[] SMembers(String key) {Object set = persistence.get(key);if (set == null)return NULL;set = serializer.unmarshal(set);return ((HashSet<Object>) set).toArray();}public Object[] SInter(String key1, String key2) {Object set1 = persistence.get(key1);Object set2 = persistence.get(key2);if (set1 == null || set2 == null)return NULL;HashSet<Object> set1Ref = (HashSet<Object>) serializer.unmarshal(set1);HashSet<Object> set2Ref = (HashSet<Object>) serializer.unmarshal(set2);set1Ref.retainAll(set2Ref);return set1Ref.toArray();}public Object[] SDiff(String key1, String key2) {Object set1 = persistence.get(key1);Object set2 = persistence.get(key2);if (set1 == null || set2 == null)return NULL;HashSet<Object> set1Ref = (HashSet<Object>) serializer.unmarshal(set1);HashSet<Object> set2Ref = (HashSet<Object>) serializer.unmarshal(set2);set1Ref.removeAll(set2Ref);return set1Ref.toArray();}// =================================================//Sorted Set value// =================================================public void ZAdd(String key, Object... values) {Object set = persistence.get(key);if (set == null)set = new TreeSet<Object>();elseset = serializer.unmarshal(set);TreeSet<Object> setRef = (TreeSet<Object>) set;for (Object value : values)setRef.add(value);persistence.put(key, serializer.marshal(set));}public Object[] SRange(String key, Object from) {Object set = persistence.get(key);if (set == null)return NULL;set = serializer.unmarshal(set);return ((TreeSet<Object>) set).tailSet(from).toArray();}}
package com.cdai.studio.redis;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.util.Arrays;class Serializer {Object marshal(Object object) {if (object == null)return null;return new BytesWrapper((Serializable) object);}Object unmarshal(Object object) {if (object == null)return null;return ((BytesWrapper) object).readObject();}}class BytesWrapper {private byte[] bytes;<T extends Serializable> BytesWrapper(T object) {writeBytes(object);}<T extends Serializable> void writeBytes(T object) {try {ByteArrayOutputStream buffer = new ByteArrayOutputStream();ObjectOutputStream output = new ObjectOutputStream(buffer);output.writeObject(object);output.flush();bytes = buffer.toByteArray();output.close();}catch (IOException e) {e.printStackTrace();throw new IllegalStateException(e);}}Object readObject() {try {ObjectInputStream input = new ObjectInputStream(new ByteArrayInputStream(bytes));Object object = input.readObject();input.close();return object;}catch (Exception e) {e.printStackTrace();throw new IllegalStateException(e);}}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + Arrays.hashCode(bytes);return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;BytesWrapper other = (BytesWrapper) obj;if (!Arrays.equals(bytes, other.bytes))return false;return true;}}
package com.cdai.studio.redis;import java.util.HashMap;class Persistence {private HashMap<String, Object> storage =new HashMap<String, Object>();void put(String key, Object value) {storage.put(key, value);}Object get(String key) {return storage.get(key);}}
3. Simple Client
package com.cdai.studio.redis;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.net.ServerSocket;import java.net.Socket;import java.util.List;public class RedisServer {private RedisDB redis;public RedisServer(RedisDB redis) {this.redis = redis;}@SuppressWarnings("unchecked")public void start() {ServerSocket serverSocket = null;try {serverSocket = new ServerSocket(1234);while (true) {Socket socket = serverSocket.accept();ObjectInputStream input = new ObjectInputStream(socket.getInputStream());List<Object> request = (List<Object>) input.readObject();Object response = null;if ("Set".equals(request.get(0))) {redis.Set((String) request.get(1), request.get(2));}else if ("Get".equals(request.get(0))) {response = redis.Get((String) request.get(1));}ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());output.writeObject(response);input.close();output.close();socket.close();}} catch (Exception e) {e.printStackTrace();}finally {if (serverSocket != null) {try {serverSocket.close();} catch (IOException e) {}}}}}
package com.cdai.studio.redis;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.net.Socket;import java.util.Arrays;import java.util.List;public class RedisClient {public <T extends Serializable> void Set(String key, Object value) {sendRequest(Arrays.asList("Set", key, value));}public Object Get(String key) {return sendRequest(Arrays.<Object>asList("Get", key));}private Object sendRequest(List<Object> payload) {Socket socket = null;try {socket = new Socket("localhost", 1234);ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());output.writeObject(payload);output.flush();ObjectInputStream input = new ObjectInputStream(socket.getInputStream());Object response = input.readObject();output.close();input.close();return response;} catch (Exception e) {e.printStackTrace();} finally {if (socket != null) {try {socket.close();} catch (Exception e) {}}}return null;}}
4. implement simple Twitter
package com.cdai.studio.redis;import java.util.Arrays;public class RedisTest {public static void main(String[] args) {RedisDB redis = new RedisDB();// 1.Create user follow relationshipredis.SAdd("users", "A", "B", "C");// User A follows B, Credis.SAdd("users:A:following", "B", "C");redis.SAdd("users:B:followers", "A");redis.SAdd("users:C:followers", "A");// User C follows B redis.SAdd("users:C:following", "B");redis.SAdd("users:B:followers", "C");// 2.1 B send tweetint tid = redis.Incr("tweets:next_id");redis.Set("tweets:" + tid, "B publish hello");redis.LPush("global:timeline", tid);redis.LPush("users:B:timeline", tid);for (Object follower : redis.SMembers("users:B:followers"))redis.LPush("users:" + follower + ":timeline", tid);// 2.2 C send tweet tid = redis.Incr("tweets:next_id");redis.Set("tweets:" + tid, "C publish world");redis.LPush("global:timeline", tid);redis.LPush("users:C:timeline", tid);for (Object follower : redis.SMembers("users:C:followers"))redis.LPush("users:" + follower + ":timeline", tid);Object[] tids = redis.LRange("global:timeline", 0, 9);String[] tweetids = new String[tids.length];for (int i = 0; i < tids.length; i++)tweetids[i] = "tweets:" + tids[i];System.out.println(Arrays.toString(redis.MGet(tweetids)));}}
5. Notes
By default, the equals and hashcode of byte arrays compare object addresses. The equals and hashcode methods of arrays are used.
Pay attention to the encoding format during string serialization and deserialization. The same encoding should be used for encoding and decoding.
Operations on the hashset, removeall complement set, retainall intersection, and addall Union set.
6. More powerful redis
Redis implements various data structures by itself, making it very convenient to add, delete, modify, and query data with high efficiency. Here we simply use Java to learn the basic functions of redis. In fact, redis also supports many other advanced functions, such as message subscription, data expiration settings, transactions, and data persistence. If you want to learn more, you can try to implement them in Java.