يعتبر Redis (Remote Dictionary Server) بجدارة رجلًا عجوزًا في عالم حلول NoSql. يدور هذا المنشور حول كيفية عمل Spring Data معه. نشأت فكرة كتابة هذا المنشور لأن Redis لا يشبه قاعدة البيانات المألوفة تمامًا ، فهو يدعم أنواع البيانات غير الملائمة للاستخدام في تخزين الكائنات (ذاكرة التخزين المؤقت لا تهم) والبحث عن حقول معينة. هنا ، مع أمثلة ، سأحاول وصف كيفية عمل Spring Data معها من خلال CrudRepository و QueryDSL المألوفين. هذا ليس مثالًا على HowTo ، حيث يوجد الكثير منها. من يهتم بالدواخل يذهب أبعد من ذلك.
ستستند الأمثلة على مشروع بسيط . يرتفع Redis في حاوية عامل إرساء ، وهو تطبيق زنبركي يتواصل معه أيضًا في الحاوية. يحتوي التطبيق على نموذج بسيط ومستودع وخدمة ووحدة تحكم. يمكنك لمس كل هذا من خلال اختيال على المضيف المحلي: 8080.
بالإضافة إلى الأوامر التي تنفذها الخدمة لقاعدة البيانات ، سأقدم أيضًا رمزًا زائفًا صغيرًا يصف ما يحدث بشكل أوضح.
سنعمل مع كيان الطالب:
@Data
@AllArgsConstructor
@NoArgsConstructor
@RedisHash("Student")
public class Student {
@Id
private String id;
private String name;
private int age;
}هنا ، من الضروري توضيح أن التعليق التوضيحي @RedisHash("Student")ينص على أي مفتاح سيتم تجميع جميع الكيانات.
دعنا نحاول الاحتفاظ بالطالب الأول:
curl -X POST "http://localhost:8080/save" -H "accept: */*" -H "Content-Type: application/json" -d "{\"id\":\"1\",\"name\":\"Stephen\",\"age\":12}"تم تنفيذ 3 أوامر:
"DEL" "Student:1"
"HMSET" "Student:1" "_class" "com.odis.redisserviceweb.model.Student" "id" "1" "name" "Stephen" "age" "12"
"SADD" "Student" "1" , - "DEL" "Student:1", "Student:1". @RedisHash + @Id.
"HMSET" "Student:1" "_class" "com.odis.redisserviceweb.model.Student" "id" "1" "name" "Stephen" "age" "12". "Student:1". -
Map "Student:1";
"Student:1".put("_class", "com.odis.redisserviceweb.model.Student");
"Student:1".put("id", "1");
"Student:1".put("name", "Stephen");
"Student:1".put("age", "12"); - "SADD" "Student" "1" - "Student" "1".
? Redis. - "Student:1", - "Student".
keys * - ( ) :
127.0.0.1:6379> keys *
1) "Student"
2) "Student:1", :
127.0.0.1:6379> type "Student"
set
127.0.0.1:6379> type "Student:1"
hash- ? .
@Id :
curl -X GET "http://localhost:8080/get/1" -H "accept: */*""Student:1" , :
"HGETALL" "Student:1"
1) "_class"
2) "com.odis.redisserviceweb.model.Student"
3) "id"
4) "1"
5) "name"
6) "Stephen"
7) "age"
8) "12", , :
curl -X POST "http://localhost:8080/save" -H "accept: */*" -H "Content-Type: application/json" -d "{\"id\":\"2\",\"name\":\"Macaulay\",\"age\":40}"
curl -X GET "http://localhost:8080/get" -H "accept: */*"3 :
"SMEMBERS" "Student"
1) "1"
2) "2"
"HGETALL" "Student:1"
1) "_class"
2) "com.odis.redisserviceweb.model.Student"
3) "id"
4) "1"
5) "name"
6) "Stephen"
7) "age"
8) "12"
127.0.0.1
"HGETALL" "Student:2"
1) "_class"
2) "com.odis.redisserviceweb.model.Student"
3) "id"
4) "2"
5) "name"
6) "Macaulay"
7) "age"
8) "40" . - "Student" - , "Student:@Id". , O (N) N - .
:
curl -X DELETE "http://localhost:8080/delete/1" -H "accept: */*":
"HGETALL" "Student:1"
1) "_class"
2) "com.odis.redisserviceweb.model.Student"
3) "id"
4) "1"
5) "name"
6) "Stephen"
7) "age"
8) "12"
"DEL" "Student:1"
(integer) 1
"SREM" "Student" "1"
(integer) 1
"SMEMBERS" "Student:1:idx"
(empty array)
"DEL" "Student:1:idx"
(integer) 0, Id . "Student" "1".
Student:1:idx. . , . :
List<Student> findAllByName(String name);:
curl -X POST "http://localhost:8080/save" -H "accept: */*" -H "Content-Type: application/json" -d "{\"id\":\"1\",\"name\":\"Stephen\",\"age\":12}"
curl -X GET "http://localhost:8080/get/filter/Stephen" -H "accept: */*", Redis :
"SINTER" "Student:name:Stephen"
(empty array) "SINTER" - , , - "Student:name:Stephen" .
, , @Id, @Indexed Spring Data , . . Redis . name :
@Data
@AllArgsConstructor
@NoArgsConstructor
@RedisHash("Student")
public class Student {
@Id
private String id;
@Indexed
private String name;
private int age;
}:
curl -X POST "http://localhost:8080/save" -H "accept: */*" -H "Content-Type: application/json" -d "{\"id\":\"1\",\"name\":\"Stephen\",\"age\":12}":
"DEL" "Student:1"
"HMSET" "Student:1" "_class" "com.odis.redisserviceweb.model.Student" "id" "1" "name" "Stephen" "age" "12"
"SADD" "Student" "1"
"SADD" "Student:name:Stephen" "1"
"SADD" "Student:1:idx" "Student:name:Stephen" , : "Student:name:Stephen" , , @Indexed . Id . Id Stephen Id . , . - :
Map "Student:1";
"Student:1".put("_class", "com.odis.redisserviceweb.model.Student");
"Student:1".put("id", "1");
"Student:1".put("name", "Stephen");
"Student:1".put("age", "12");
Set "Student";
"Student".add("1");
Set "Student:name:Stephen";
"Student:name:Stephen".add("1");
Set "Student:1:idx";
"Student:1:idx".add("Student:name:Stephen");, , Redis :
"SINTER" "Student:name:Stephen"
"HGETALL" "Student:1" Id , . .
SINTER . id .
.
, Spring Data Redis. Spring.
العيب هو أن الحقول التي سيتم إجراء البحث عليها يجب تمييزها بتعليق توضيحي @Indexedمن البداية. وبخلاف ذلك ، سيتم إنشاء "الفهارس" فقط للميزات التي يتم الاحتفاظ بها بعد إضافة هذا التعليق التوضيحي. ونعم ، أفهم أن Redis ليس الحل الأفضل لمثل هذه الاحتياجات ، ولكن إذا كان من الضروري استخدامه بسبب موقف معين ، فسيكون SpringData قادرًا على القيام بذلك بشكل جيد.